types.c 32 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4 5
/*
 * File types.c - datatype handling stuff for internal debugger.
 *
 * Copyright (C) 1997, Eric Youngdale.
 *
6 7 8 9 10 11 12 13 14 15 16 17
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 20
 *
 * Note: This really doesn't do much at the moment, but it forms the framework
21
 * upon which full support for datatype handling will eventually be built.
Alexandre Julliard's avatar
Alexandre Julliard committed
22 23
 */

24
#include "config.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
25 26 27
#include <stdlib.h>

#include "debugger.h"
28 29 30
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
Alexandre Julliard's avatar
Alexandre Julliard committed
31

32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
/******************************************************************
 *		types_get_real_type
 *
 * Get rid of any potential typedef in the lvalue's type to get
 * to the 'real' type (the one we can work upon).
 */
BOOL types_get_real_type(struct dbg_type* type, DWORD* tag)
{
    if (type->id == dbg_itype_none) return FALSE;
    do
    {
        if (!types_get_info(type, TI_GET_SYMTAG, tag))
            return FALSE;
        if (*tag != SymTagTypedef) return TRUE;
    } while (types_get_info(type, TI_GET_TYPE, &type->id));
    return FALSE;
}

50
/******************************************************************
51
 *		types_extract_as_longlong
52 53 54
 *
 * Given a lvalue, try to get an integral (or pointer/address) value
 * out of it
Alexandre Julliard's avatar
Alexandre Julliard committed
55
 */
56 57
LONGLONG types_extract_as_longlong(const struct dbg_lvalue* lvalue,
                                   unsigned* psize, BOOL *issigned)
Alexandre Julliard's avatar
Alexandre Julliard committed
58
{
59
    LONGLONG            rtn = 0;
60 61
    DWORD               tag, bt;
    DWORD64             size;
62
    struct dbg_type     type = lvalue->type;
63
    BOOL                s = FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
64

65
    if (!types_get_real_type(&type, &tag))
66
        RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL);
Alexandre Julliard's avatar
Alexandre Julliard committed
67

68
    if (type.id == dbg_itype_segptr)
69
    {
70
        return (LONG_PTR)memory_to_linear_addr(&lvalue->addr);
71 72
    }

73
    if (psize) *psize = 0;
74
    if (issigned) *issigned = FALSE;
75
    switch (tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
76
    {
77
    case SymTagBaseType:
78 79
        if (!types_get_info(&type, TI_GET_LENGTH, &size) ||
            !types_get_info(&type, TI_GET_BASETYPE, &bt))
80 81 82
        {
            WINE_ERR("Couldn't get information\n");
            RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
83
            return rtn;
84
        }
85
        if (size > sizeof(rtn))
86
        {
87
            WINE_ERR("Size too large (%s)\n", wine_dbgstr_longlong(size));
88
            RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL);
89
            return rtn;
90 91 92
        }
        switch (bt)
        {
93
        case btChar:
94
        case btInt:
95
            if (!dbg_curr_process->be_cpu->fetch_integer(lvalue, (unsigned)size, s = TRUE, &rtn))
96
                RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
97 98
            break;
        case btUInt:
99
            if (!dbg_curr_process->be_cpu->fetch_integer(lvalue, (unsigned)size, s = FALSE, &rtn))
100
                RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
101 102 103 104
            break;
        case btFloat:
            RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL);
        }
105
        if (psize) *psize = (unsigned)size;
106
        if (issigned) *issigned = s;
107 108
        break;
    case SymTagPointerType:
109
        if (!dbg_curr_process->be_cpu->fetch_integer(lvalue, sizeof(void*), s = FALSE, &rtn))
110
            RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
111 112 113
        break;
    case SymTagArrayType:
    case SymTagUDT:
114
        if (!dbg_curr_process->be_cpu->fetch_integer(lvalue, sizeof(unsigned), s = FALSE, &rtn))
115
            RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
116 117
        break;
    case SymTagEnum:
118
        /* FIXME: we don't handle enum size */
119
        if (!dbg_curr_process->be_cpu->fetch_integer(lvalue, sizeof(unsigned), s = FALSE, &rtn))
120 121 122
            RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
        break;
    case SymTagFunctionType:
123
        rtn = (ULONG_PTR)memory_to_linear_addr(&lvalue->addr);
124 125
        break;
    default:
126
        WINE_FIXME("Unsupported tag %u\n", tag);
127
        RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL);
Alexandre Julliard's avatar
Alexandre Julliard committed
128 129
    }

130
    return rtn;
Alexandre Julliard's avatar
Alexandre Julliard committed
131 132
}

133 134 135 136 137 138 139 140
/******************************************************************
 *		types_extract_as_integer
 *
 * Given a lvalue, try to get an integral (or pointer/address) value
 * out of it
 */
long int types_extract_as_integer(const struct dbg_lvalue* lvalue)
{
141
    return types_extract_as_longlong(lvalue, NULL, NULL);
142 143
}

144 145 146 147 148
/******************************************************************
 *		types_extract_as_address
 *
 *
 */
149
void types_extract_as_address(const struct dbg_lvalue* lvalue, ADDRESS64* addr)
150 151 152 153 154 155 156 157
{
    if (lvalue->type.id == dbg_itype_segptr && lvalue->type.module == 0)
    {
        *addr = lvalue->addr;
    }
    else
    {
        addr->Mode = AddrModeFlat;
158
        addr->Offset = types_extract_as_longlong(lvalue, NULL, NULL);
159 160 161
    }
}

162 163 164 165 166 167 168 169 170
BOOL types_store_value(struct dbg_lvalue* lvalue_to, const struct dbg_lvalue* lvalue_from)
{
    LONGLONG    val;
    DWORD64     size;
    BOOL        is_signed;

    if (!types_get_info(&lvalue_to->type, TI_GET_LENGTH, &size)) return FALSE;
    if (sizeof(val) < size)
    {
171
        dbg_printf("Insufficient size\n");
172 173 174 175
        return FALSE;
    }
    /* FIXME: should support floats as well */
    val = types_extract_as_longlong(lvalue_from, NULL, &is_signed);
176
    return dbg_curr_process->be_cpu->store_integer(lvalue_to, size, is_signed, val);
177 178
}

179 180 181 182 183
/******************************************************************
 *		types_get_udt_element_lvalue
 *
 * Implement a structure derefencement
 */
184 185
static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, 
                                         const struct dbg_type* type, long int* tmpbuf)
186
{
187
    DWORD       offset, bitoffset;
188
    DWORD       bt;
189 190
    DWORD64     length;

191 192
    unsigned    mask;

193 194
    types_get_info(type, TI_GET_TYPE, &lvalue->type.id);
    lvalue->type.module = type->module;
Eric Pouech's avatar
Eric Pouech committed
195 196
    if (!types_get_info(type, TI_GET_OFFSET, &offset)) return FALSE;
    lvalue->addr.Offset += offset;
197

198
    if (types_get_info(type, TI_GET_BITPOSITION, &bitoffset))
199
    {
Eric Pouech's avatar
Eric Pouech committed
200 201 202 203 204 205
        types_get_info(type, TI_GET_LENGTH, &length);
        /* FIXME: this test isn't sufficient, depending on start of bitfield
         * (ie a 32 bit field can spread across 5 bytes)
         */
        if (length > 8 * sizeof(*tmpbuf)) return FALSE;
        lvalue->addr.Offset += bitoffset >> 3;
206 207 208 209 210
        /*
         * Bitfield operation.  We have to extract the field and store
         * it in a temporary buffer so that we get it all right.
         */
        if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE;
211
        mask = 0xffffffff << (DWORD)length;
212 213 214
        *tmpbuf >>= bitoffset & 7;
        *tmpbuf &= ~mask;

215
        lvalue->cookie      = DLV_HOST;
216
        lvalue->addr.Offset = (ULONG_PTR)tmpbuf;
217 218 219 220 221 222

        /*
         * OK, now we have the correct part of the number.
         * Check to see whether the basic type is signed or not, and if so,
         * we need to sign extend the number.
         */
223
        if (types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt) && 
224
            bt == btInt && (*tmpbuf & (1 << ((DWORD)length - 1))))
225 226 227 228
        {
            *tmpbuf |= mask;
        }
    }
Eric Pouech's avatar
Eric Pouech committed
229
    else
230
    {
Eric Pouech's avatar
Eric Pouech committed
231
        if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE;
232
    }
Eric Pouech's avatar
Eric Pouech committed
233
    return TRUE;
234 235
}

236 237 238 239 240
/******************************************************************
 *		types_udt_find_element
 *
 */
BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name, long int* tmpbuf)
Alexandre Julliard's avatar
Alexandre Julliard committed
241
{
242 243 244 245 246
    DWORD                       tag, count;
    char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
    TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
    WCHAR*                      ptr;
    char                        tmp[256];
247
    struct dbg_type             type;
Alexandre Julliard's avatar
Alexandre Julliard committed
248

249
    if (!types_get_real_type(&lvalue->type, &tag) || tag != SymTagUDT)
250
        return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
251

252
    if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
Alexandre Julliard's avatar
Alexandre Julliard committed
253
    {
254 255 256 257
        fcp->Start = 0;
        while (count)
        {
            fcp->Count = min(count, 256);
258
            if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
259
            {
260
                unsigned i;
261
                type.module = lvalue->type.module;
262 263 264
                for (i = 0; i < min(fcp->Count, count); i++)
                {
                    ptr = NULL;
265 266
                    type.id = fcp->ChildId[i];
                    types_get_info(&type, TI_GET_SYMNAME, &ptr);
267 268 269 270 271
                    if (!ptr) continue;
                    WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
                    HeapFree(GetProcessHeap(), 0, ptr);
                    if (strcmp(tmp, name)) continue;

272
                    return types_get_udt_element_lvalue(lvalue, &type, tmpbuf);
273 274 275 276 277
                }
            }
            count -= min(count, 256);
            fcp->Start += 256;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
278
    }
279
    return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
280 281
}

282 283 284 285 286
/******************************************************************
 *		types_array_index
 *
 * Grab an element from an array
 */
287
BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, struct dbg_lvalue* result)
Alexandre Julliard's avatar
Alexandre Julliard committed
288
{
289 290
    struct dbg_type     type = lvalue->type;
    DWORD               tag, count;
291 292 293 294

    memset(result, 0, sizeof(*result));
    result->type.id = dbg_itype_none;
    result->type.module = 0;
295

296
    if (!types_get_real_type(&type, &tag)) return FALSE;
297 298 299
    switch (tag)
    {
    case SymTagArrayType:
300
        if (!types_get_info(&type, TI_GET_COUNT, &count)) return FALSE;
301
        if (index < 0 || index >= count) return FALSE;
302
        result->addr = lvalue->addr;
303
        break;
304
    case SymTagPointerType:
305 306
        if (!memory_read_value(lvalue, dbg_curr_process->be_cpu->pointer_size, &result->addr.Offset))
            return FALSE;
307
        result->addr.Mode = AddrModeFlat;
308
        switch (dbg_curr_process->be_cpu->pointer_size)
309 310 311 312 313
        {
        case 4: result->addr.Offset = (DWORD)result->addr.Offset; break;
        case 8: break;
        default: assert(0);
        }
314 315 316
        break;
    default:
        assert(FALSE);
Alexandre Julliard's avatar
Alexandre Julliard committed
317
    }
318 319 320
    /*
     * Get the base type, so we know how much to index by.
     */
321 322 323 324 325 326 327 328 329
    if (!types_get_info(&type, TI_GET_TYPE, &result->type.id)) return FALSE;
    result->type.module = type.module;
    if (index)
    {
        DWORD64             length;
        if (!types_get_info(&result->type, TI_GET_LENGTH, &length)) return FALSE;
        result->addr.Offset += index * (DWORD)length;
    }
    /* FIXME: the following statement is not always true (and can lead to buggy behavior).
330
     * There is no way to tell where the deref:ed value is...
331 332 333 334 335 336 337 338 339 340 341 342
     * For example:
     *	x is a pointer to struct s, x being on the stack
     *		=> lvalue is in debuggee, result is in debugger
     *	x is a pointer to struct s, x being optimized into a reg
     *		=> lvalue is debugger, result is debuggee
     *	x is a pointer to internal variable x
     *	       	=> lvalue is debugger, result is debuggee
     * So we always force debuggee address space, because dereferencing pointers to
     * internal variables is very unlikely. A correct fix would be
     * rather large.
     */
    result->cookie = DLV_TARGET;
343 344
    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
345

346 347
struct type_find_t
{
348
    unsigned long       result; /* out: the found type */
349 350
    enum SymTagEnum     tag;    /* in: the tag to look for */
    union
Alexandre Julliard's avatar
Alexandre Julliard committed
351
    {
352 353
        unsigned long           typeid; /* when tag is SymTagUDT */
        const char*             name;   /* when tag is SymTagPointerType */
354 355
    } u;
};
Alexandre Julliard's avatar
Alexandre Julliard committed
356

357
static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
Alexandre Julliard's avatar
Alexandre Julliard committed
358
{
359
    struct type_find_t* user = _user;
360
    BOOL                ret = TRUE;
361
    struct dbg_type     type;
362
    DWORD               type_id;
Alexandre Julliard's avatar
Alexandre Julliard committed
363

364
    if (sym->Tag == user->tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
365
    {
366 367 368 369 370 371 372 373 374 375
        switch (user->tag)
        {
        case SymTagUDT:
            if (!strcmp(user->u.name, sym->Name))
            {
                user->result = sym->TypeIndex;
                ret = FALSE;
            }
            break;
        case SymTagPointerType:
376 377
            type.module = sym->ModBase;
            type.id = sym->TypeIndex;
378
            if (types_get_info(&type, TI_GET_TYPE, &type_id) && type_id == user->u.typeid)
379 380 381 382
            {
                user->result = sym->TypeIndex;
                ret = FALSE;
            }
383
            break;
384 385
        default: break;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
386
    }
387
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
388 389
}

390 391 392 393 394 395
/******************************************************************
 *		types_find_pointer
 *
 * Should look up in module based at linear whether (typeid*) exists
 * Otherwise, we could create it locally
 */
396
struct dbg_type types_find_pointer(const struct dbg_type* type)
Alexandre Julliard's avatar
Alexandre Julliard committed
397
{
398
    struct type_find_t  f;
399 400
    struct dbg_type     ret;

401 402
    f.result = dbg_itype_none;
    f.tag = SymTagPointerType;
403 404 405 406 407
    f.u.typeid = type->id;
    SymEnumTypes(dbg_curr_process->handle, type->module, types_cb, &f);
    ret.module = type->module;
    ret.id = f.result;
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
408 409
}

410 411 412 413 414 415
/******************************************************************
 *		types_find_type
 *
 * Should look up in the module based at linear address whether a type
 * named 'name' and with the correct tag exists
 */
416
struct dbg_type types_find_type(unsigned long linear, const char* name, enum SymTagEnum tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
417

418 419
{
    struct type_find_t  f;
420 421
    struct dbg_type     ret;

422 423 424 425
    f.result = dbg_itype_none;
    f.tag = tag;
    f.u.name = name;
    SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f);
426 427 428
    ret.module = linear;
    ret.id = f.result;
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
429 430
}

431 432 433 434 435 436
/***********************************************************************
 *           print_value
 *
 * Implementation of the 'print' command.
 */
void print_value(const struct dbg_lvalue* lvalue, char format, int level)
Alexandre Julliard's avatar
Alexandre Julliard committed
437
{
438
    struct dbg_type     type = lvalue->type;
439 440 441 442
    struct dbg_lvalue   lvalue_field;
    int		        i;
    DWORD               tag;
    DWORD               count;
443
    DWORD64             size;
Alexandre Julliard's avatar
Alexandre Julliard committed
444

445 446 447 448 449 450 451
    if (!types_get_real_type(&type, &tag))
    {
        WINE_FIXME("---error\n");
        return;
    }

    if (type.id == dbg_itype_none)
Alexandre Julliard's avatar
Alexandre Julliard committed
452
    {
453 454 455
        /* No type, just print the addr value */
        print_bare_address(&lvalue->addr);
        goto leave;
Alexandre Julliard's avatar
Alexandre Julliard committed
456 457
    }

458
    if (format == 'i' || format == 's' || format == 'w' || format == 'b' || format == 'g')
Alexandre Julliard's avatar
Alexandre Julliard committed
459
    {
460 461
        dbg_printf("Format specifier '%c' is meaningless in 'print' command\n", format);
        format = '\0';
Alexandre Julliard's avatar
Alexandre Julliard committed
462 463
    }

464
    switch (tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
465
    {
466 467 468
    case SymTagBaseType:
    case SymTagEnum:
    case SymTagPointerType:
469 470 471
        /* FIXME: this in not 100% optimal (as we're going through the typedef handling
         * stuff again
         */
472
        print_basic(lvalue, format);
473 474
        break;
    case SymTagUDT:
475
        if (types_get_info(&type, TI_GET_CHILDRENCOUNT, &count))
476 477 478 479 480 481
        {
            char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
            TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
            WCHAR*                      ptr;
            char                        tmp[256];
            long int                    tmpbuf;
482
            struct dbg_type             sub_type;
483 484 485 486 487 488

            dbg_printf("{");
            fcp->Start = 0;
            while (count)
            {
                fcp->Count = min(count, 256);
489
                if (types_get_info(&type, TI_FINDCHILDREN, fcp))
490 491 492 493
                {
                    for (i = 0; i < min(fcp->Count, count); i++)
                    {
                        ptr = NULL;
494 495 496
                        sub_type.module = type.module;
                        sub_type.id = fcp->ChildId[i];
                        types_get_info(&sub_type, TI_GET_SYMNAME, &ptr);
497 498 499 500 501
                        if (!ptr) continue;
                        WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
                        dbg_printf("%s=", tmp);
                        HeapFree(GetProcessHeap(), 0, ptr);
                        lvalue_field = *lvalue;
502
                        if (types_get_udt_element_lvalue(&lvalue_field, &sub_type, &tmpbuf))
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
                        {
                            print_value(&lvalue_field, format, level + 1);
                        }
                        if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
                    }
                }
                count -= min(count, 256);
                fcp->Start += 256;
            }
            dbg_printf("}");
        }
        break;
    case SymTagArrayType:
        /*
         * Loop over all of the entries, printing stuff as we go.
         */
        count = 1; size = 1;
520 521
        types_get_info(&type, TI_GET_COUNT, &count);
        types_get_info(&type, TI_GET_LENGTH, &size);
522 523

        if (size == count)
Alexandre Julliard's avatar
Alexandre Julliard committed
524
	{
525 526 527 528 529 530 531
            unsigned    len;
            char        buffer[256];
            /*
             * Special handling for character arrays.
             */
            /* FIXME should check basic type here (should be a char!!!!)... */
            len = min(count, sizeof(buffer));
532
            memory_get_string(dbg_curr_process,
533
                              memory_to_linear_addr(&lvalue->addr),
534
                              lvalue->cookie == DLV_TARGET, TRUE, buffer, len);
535 536 537 538
            dbg_printf("\"%s%s\"", buffer, (len < count) ? "..." : "");
            break;
        }
        lvalue_field = *lvalue;
539
        types_get_info(&type, TI_GET_TYPE, &lvalue_field.type.id);
540 541
        dbg_printf("{");
        for (i = 0; i < count; i++)
Alexandre Julliard's avatar
Alexandre Julliard committed
542
	{
543 544 545
            print_value(&lvalue_field, format, level + 1);
            lvalue_field.addr.Offset += size / count;
            dbg_printf((i == count - 1) ? "}" : ", ");
Alexandre Julliard's avatar
Alexandre Julliard committed
546
	}
547 548 549 550 551
        break;
    case SymTagFunctionType:
        dbg_printf("Function ");
        print_bare_address(&lvalue->addr);
        dbg_printf(": ");
552
        types_print_type(&type, FALSE);
553
        break;
554 555 556 557 558
    case SymTagTypedef:
        lvalue_field = *lvalue;
        types_get_info(&lvalue->type, TI_GET_TYPE, &lvalue_field.type.id);
        print_value(&lvalue_field, format, level);
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
559
    default:
560
        WINE_FIXME("Unknown tag (%u)\n", tag);
561 562
        RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
563 564
    }

565
leave:
Alexandre Julliard's avatar
Alexandre Julliard committed
566

567
    if (level == 0) dbg_printf("\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
568 569
}

570
static BOOL CALLBACK print_types_cb(PSYMBOL_INFO sym, ULONG size, void* ctx)
Alexandre Julliard's avatar
Alexandre Julliard committed
571
{
572 573 574
    struct dbg_type     type;
    type.module = sym->ModBase;
    type.id = sym->TypeIndex;
575
    dbg_printf("Mod: %08lx ID: %08lx\n", type.module, type.id);
576
    types_print_type(&type, TRUE);
577 578
    dbg_printf("\n");
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
579 580
}

581
static BOOL CALLBACK print_types_mod_cb(PCSTR mod_name, DWORD64 base, PVOID ctx)
Alexandre Julliard's avatar
Alexandre Julliard committed
582
{
583
    return SymEnumTypes(dbg_curr_process->handle, base, print_types_cb, ctx);
Alexandre Julliard's avatar
Alexandre Julliard committed
584 585
}

586
BOOL print_types(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
587
{
588 589 590
    if (!dbg_curr_process)
    {
        dbg_printf("No known process, cannot print types\n");
591
        return FALSE;
592
    }
593
    SymEnumerateModules64(dbg_curr_process->handle, print_types_mod_cb, NULL);
594
    return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
595 596
}

597
BOOL types_print_type(const struct dbg_type* type, BOOL details)
Alexandre Julliard's avatar
Alexandre Julliard committed
598
{
599 600 601
    WCHAR*              ptr;
    char                tmp[256];
    const char*         name;
602 603
    DWORD               tag, udt, count;
    struct dbg_type     subtype;
Alexandre Julliard's avatar
Alexandre Julliard committed
604

605
    if (type->id == dbg_itype_none || !types_get_info(type, TI_GET_SYMTAG, &tag))
Alexandre Julliard's avatar
Alexandre Julliard committed
606
    {
607
        dbg_printf("--invalid--<%lxh>--", type->id);
608
        return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
609 610
    }

611
    if (types_get_info(type, TI_GET_SYMNAME, &ptr) && ptr)
Alexandre Julliard's avatar
Alexandre Julliard committed
612
    {
613 614 615
        WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
        name = tmp;
        HeapFree(GetProcessHeap(), 0, ptr);
Alexandre Julliard's avatar
Alexandre Julliard committed
616
    }
617
    else name = "--none--";
Alexandre Julliard's avatar
Alexandre Julliard committed
618

619
    switch (tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
620
    {
621 622
    case SymTagBaseType:
        if (details) dbg_printf("Basic<%s>", name); else dbg_printf("%s", name);
623
        break;
624
    case SymTagPointerType:
625 626 627
        types_get_info(type, TI_GET_TYPE, &subtype.id);
        subtype.module = type->module;
        types_print_type(&subtype, FALSE);
628
        dbg_printf("*");
629
        break;
630
    case SymTagUDT:
631 632
        types_get_info(type, TI_GET_UDTKIND, &udt);
        switch (udt)
633 634 635 636
        {
        case UdtStruct: dbg_printf("struct %s", name); break;
        case UdtUnion:  dbg_printf("union %s", name); break;
        case UdtClass:  dbg_printf("class %s", name); break;
637
        default:        WINE_ERR("Unsupported UDT type (%d) for %s\n", udt, name); break;
638 639
        }
        if (details &&
640
            types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
641
        {
642 643 644 645 646
            char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
            TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
            WCHAR*                      ptr;
            char                        tmp[256];
            int                         i;
647
            struct dbg_type             type_elt;
648 649 650 651
            dbg_printf(" {");

            fcp->Start = 0;
            while (count)
652
            {
653
                fcp->Count = min(count, 256);
654
                if (types_get_info(type, TI_FINDCHILDREN, fcp))
655 656 657 658
                {
                    for (i = 0; i < min(fcp->Count, count); i++)
                    {
                        ptr = NULL;
659 660 661
                        type_elt.module = type->module;
                        type_elt.id = fcp->ChildId[i];
                        types_get_info(&type_elt, TI_GET_SYMNAME, &ptr);
662 663 664 665
                        if (!ptr) continue;
                        WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
                        HeapFree(GetProcessHeap(), 0, ptr);
                        dbg_printf("%s", tmp);
666
                        if (types_get_info(&type_elt, TI_GET_TYPE, &type_elt.id))
667 668
                        {
                            dbg_printf(":");
669
                            types_print_type(&type_elt, details);
670 671 672 673 674 675
                        }
                        if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
                    }
                }
                count -= min(count, 256);
                fcp->Start += 256;
676
            }
677
            dbg_printf("}");
678 679
        }
        break;
680
    case SymTagArrayType:
681 682 683
        types_get_info(type, TI_GET_TYPE, &subtype.id);
        subtype.module = type->module;
        types_print_type(&subtype, details);
684 685 686 687
        if (types_get_info(type, TI_GET_COUNT, &count))
            dbg_printf(" %s[%d]", name, count);
        else
            dbg_printf(" %s[]", name);
688
        break;
689 690
    case SymTagEnum:
        dbg_printf("enum %s", name);
691
        break;
692
    case SymTagFunctionType:
693
        types_get_info(type, TI_GET_TYPE, &subtype.id);
694 695 696 697 698 699 700 701
        /* is the returned type the same object as function sig itself ? */
        if (subtype.id != type->id)
        {
            subtype.module = type->module;
            types_print_type(&subtype, FALSE);
        }
        else
        {
702
            subtype.module = 0;
703 704
            dbg_printf("<ret_type=self>");
        }
705
        dbg_printf(" (*%s)(", name);
706
        if (types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
707 708 709 710 711 712
        {
            char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
            TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
            int                         i;

            fcp->Start = 0;
713 714
            if (!count) dbg_printf("void");
            else while (count)
715 716
            {
                fcp->Count = min(count, 256);
717
                if (types_get_info(type, TI_FINDCHILDREN, fcp))
718 719 720
                {
                    for (i = 0; i < min(fcp->Count, count); i++)
                    {
721
                        subtype.id = fcp->ChildId[i];
722
                        types_get_info(&subtype, TI_GET_TYPE, &subtype.id);
723
                        types_print_type(&subtype, FALSE);
724 725 726 727 728 729 730 731
                        if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
                    }
                }
                count -= min(count, 256);
                fcp->Start += 256;
            }
        }
        dbg_printf(")");
732
        break;
733
    case SymTagTypedef:
734
        dbg_printf("%s", name);
735
        break;
736
    default:
737
        WINE_ERR("Unknown type %u for %s\n", tag, name);
738 739
        break;
    }
740
    
741
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
742 743
}

744 745 746
/* helper to typecast pInfo to its expected type (_t) */
#define X(_t) (*((_t*)pInfo))

747
BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
Alexandre Julliard's avatar
Alexandre Julliard committed
748
{
749 750
    if (type->id == dbg_itype_none) return FALSE;
    if (type->module != 0)
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
    {
        DWORD ret, tag, bt;
        ret = SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, ti, pInfo);
        if (!ret &&
            SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_SYMTAG, &tag) &&
            tag == SymTagBaseType &&
            SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_BASETYPE, &bt))
        {
            static const WCHAR voidW[] = {'v','o','i','d','\0'};
            static const WCHAR charW[] = {'c','h','a','r','\0'};
            static const WCHAR wcharW[] = {'W','C','H','A','R','\0'};
            static const WCHAR intW[] = {'i','n','t','\0'};
            static const WCHAR uintW[] = {'u','n','s','i','g','n','e','d',' ','i','n','t','\0'};
            static const WCHAR floatW[] = {'f','l','o','a','t','\0'};
            static const WCHAR boolW[] = {'b','o','o','l','\0'};
            static const WCHAR longW[] = {'l','o','n','g',' ','i','n','t','\0'};
            static const WCHAR ulongW[] = {'u','n','s','i','g','n','e','d',' ','l','o','n','g',' ','i','n','t','\0'};
            static const WCHAR complexW[] = {'c','o','m','p','l','e','x','\0'};
            const WCHAR* name = NULL;

            switch (bt)
            {
            case btVoid:        name = voidW; break;
            case btChar:        name = charW; break;
            case btWChar:       name = wcharW; break;
            case btInt:         name = intW; break;
            case btUInt:        name = uintW; break;
            case btFloat:       name = floatW; break;
            case btBool:        name = boolW; break;
            case btLong:        name = longW; break;
            case btULong:       name = ulongW; break;
            case btComplex:     name = complexW; break;
783
            default:            WINE_FIXME("Unsupported basic type %u\n", bt); return FALSE;
784 785 786 787 788 789 790 791 792 793
            }
            X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name) + 1) * sizeof(WCHAR));
            if (X(WCHAR*))
            {
                lstrcpyW(X(WCHAR*), name);
                ret = TRUE;
            }
        }
        return ret;
    }
794

795
    assert(type->id >= dbg_itype_first);
Alexandre Julliard's avatar
Alexandre Julliard committed
796

797
    switch (type->id)
Alexandre Julliard's avatar
Alexandre Julliard committed
798
    {
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
    case dbg_itype_unsigned_long_int:
        switch (ti)
        {
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = ADDRSIZE; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
        default: WINE_FIXME("unsupported %u for u-long int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_signed_long_int:
        switch (ti)
        {
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = ADDRSIZE; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
        default: WINE_FIXME("unsupported %u for s-long int\n", ti); return FALSE;
        }
        break;
817 818 819
    case dbg_itype_unsigned_int:
        switch (ti)
        {
820 821 822
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 4; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
823 824 825 826 827 828
        default: WINE_FIXME("unsupported %u for u-int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_signed_int:
        switch (ti)
        {
829 830 831
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 4; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
832 833 834 835 836 837
        default: WINE_FIXME("unsupported %u for s-int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_unsigned_short_int:
        switch (ti)
        {
838 839 840
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 2; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
841 842 843 844 845 846
        default: WINE_FIXME("unsupported %u for u-short int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_signed_short_int:
        switch (ti)
        {
847 848 849
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 2; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
850 851 852 853 854 855
        default: WINE_FIXME("unsupported %u for s-short int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_unsigned_char_int:
        switch (ti)
        {
856 857 858
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 1; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
859 860 861 862 863 864
        default: WINE_FIXME("unsupported %u for u-char int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_signed_char_int:
        switch (ti)
        {
865 866 867
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 1; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
868 869 870 871 872 873
        default: WINE_FIXME("unsupported %u for s-char int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_char:
        switch (ti)
        {
874 875 876
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 1; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btChar; break;
877 878 879 880 881 882
        default: WINE_FIXME("unsupported %u for char int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_astring:
        switch (ti)
        {
883
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagPointerType; break;
884
        case TI_GET_LENGTH:     X(DWORD64) = ADDRSIZE; break;
885
        case TI_GET_TYPE:       X(DWORD)   = dbg_itype_char; break;
886 887 888
        default: WINE_FIXME("unsupported %u for a string\n", ti); return FALSE;
        }
        break;
889 890 891 892 893 894 895 896 897
    case dbg_itype_segptr:
        switch (ti)
        {
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 4; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
        default: WINE_FIXME("unsupported %u for seg-ptr\n", ti); return FALSE;
        }
        break;
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
    case dbg_itype_short_real:
        switch (ti)
        {
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 4; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btFloat; break;
        default: WINE_FIXME("unsupported %u for short real\n", ti); return FALSE;
        }
        break;
    case dbg_itype_real:
        switch (ti)
        {
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 8; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btFloat; break;
        default: WINE_FIXME("unsupported %u for real\n", ti); return FALSE;
        }
        break;
    case dbg_itype_long_real:
        switch (ti)
        {
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 10; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btFloat; break;
        default: WINE_FIXME("unsupported %u for long real\n", ti); return FALSE;
        }
        break;
925 926 927 928 929 930 931 932 933
    case dbg_itype_m128a:
        switch (ti)
        {
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 16; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
        default: WINE_FIXME("unsupported %u for XMM register\n", ti); return FALSE;
        }
        break;
934
    default: WINE_FIXME("unsupported type id 0x%lx\n", type->id);
Alexandre Julliard's avatar
Alexandre Julliard committed
935 936
    }

937 938
#undef X
    return TRUE;
939
}