types.c 30.4 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 (!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 (!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 (!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 (!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 (!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 171 172 173 174 175 176 177 178
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)
    {
        dbg_printf("Unsufficient size\n");
        return FALSE;
    }
    /* FIXME: should support floats as well */
    val = types_extract_as_longlong(lvalue_from, NULL, &is_signed);
    return be_cpu->store_integer(lvalue_to, size, is_signed, val);
}

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 307 308 309 310 311 312
        if (!memory_read_value(lvalue, be_cpu->pointer_size, &result->addr.Offset)) return FALSE;
        result->addr.Mode = AddrModeFlat;
        switch (be_cpu->pointer_size)
        {
        case 4: result->addr.Offset = (DWORD)result->addr.Offset; break;
        case 8: break;
        default: assert(0);
        }
313 314 315
        break;
    default:
        assert(FALSE);
Alexandre Julliard's avatar
Alexandre Julliard committed
316
    }
317 318 319
    /*
     * Get the base type, so we know how much to index by.
     */
320 321 322 323 324 325 326 327 328
    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).
329
     * There is no way to tell where the deref:ed value is...
330 331 332 333 334 335 336 337 338 339 340 341
     * 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;
342 343
    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
344

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

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

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

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

400 401
    f.result = dbg_itype_none;
    f.tag = SymTagPointerType;
402 403 404 405 406
    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
407 408
}

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

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

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

430 431 432 433 434 435
/***********************************************************************
 *           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
436
{
437
    struct dbg_type     type = lvalue->type;
438 439 440 441
    struct dbg_lvalue   lvalue_field;
    int		        i;
    DWORD               tag;
    DWORD               count;
442
    DWORD64             size;
Alexandre Julliard's avatar
Alexandre Julliard committed
443

444 445 446 447 448 449 450
    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
451
    {
452 453 454
        /* No type, just print the addr value */
        print_bare_address(&lvalue->addr);
        goto leave;
Alexandre Julliard's avatar
Alexandre Julliard committed
455 456
    }

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

463
    switch (tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
464
    {
465 466 467
    case SymTagBaseType:
    case SymTagEnum:
    case SymTagPointerType:
468 469 470
        /* FIXME: this in not 100% optimal (as we're going through the typedef handling
         * stuff again
         */
471
        print_basic(lvalue, format);
472 473
        break;
    case SymTagUDT:
474
        if (types_get_info(&type, TI_GET_CHILDRENCOUNT, &count))
475 476 477 478 479 480
        {
            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;
481
            struct dbg_type             sub_type;
482 483 484 485 486 487

            dbg_printf("{");
            fcp->Start = 0;
            while (count)
            {
                fcp->Count = min(count, 256);
488
                if (types_get_info(&type, TI_FINDCHILDREN, fcp))
489 490 491 492
                {
                    for (i = 0; i < min(fcp->Count, count); i++)
                    {
                        ptr = NULL;
493 494 495
                        sub_type.module = type.module;
                        sub_type.id = fcp->ChildId[i];
                        types_get_info(&sub_type, TI_GET_SYMNAME, &ptr);
496 497 498 499 500
                        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;
501
                        if (types_get_udt_element_lvalue(&lvalue_field, &sub_type, &tmpbuf))
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
                        {
                            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;
519 520
        types_get_info(&type, TI_GET_COUNT, &count);
        types_get_info(&type, TI_GET_LENGTH, &size);
521 522

        if (size == count)
Alexandre Julliard's avatar
Alexandre Julliard committed
523
	{
524 525 526 527 528 529 530
            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));
531
            memory_get_string(dbg_curr_process,
532
                              memory_to_linear_addr(&lvalue->addr),
533
                              lvalue->cookie == DLV_TARGET, TRUE, buffer, len);
534 535 536 537
            dbg_printf("\"%s%s\"", buffer, (len < count) ? "..." : "");
            break;
        }
        lvalue_field = *lvalue;
538
        types_get_info(&type, TI_GET_TYPE, &lvalue_field.type.id);
539 540
        dbg_printf("{");
        for (i = 0; i < count; i++)
Alexandre Julliard's avatar
Alexandre Julliard committed
541
	{
542 543 544
            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
545
	}
546 547 548 549 550
        break;
    case SymTagFunctionType:
        dbg_printf("Function ");
        print_bare_address(&lvalue->addr);
        dbg_printf(": ");
551
        types_print_type(&type, FALSE);
552
        break;
553 554 555 556 557
    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
558
    default:
559
        WINE_FIXME("Unknown tag (%u)\n", tag);
560 561
        RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
562 563
    }

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

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

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

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

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

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

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

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

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

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

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

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

746
BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
Alexandre Julliard's avatar
Alexandre Julliard committed
747
{
748 749
    if (type->id == dbg_itype_none) return FALSE;
    if (type->module != 0)
750 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
    {
        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;
782
            default:            WINE_FIXME("Unsupported basic type %u\n", bt); return FALSE;
783 784 785 786 787 788 789 790 791 792
            }
            X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name) + 1) * sizeof(WCHAR));
            if (X(WCHAR*))
            {
                lstrcpyW(X(WCHAR*), name);
                ret = TRUE;
            }
        }
        return ret;
    }
793

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

796
    switch (type->id)
Alexandre Julliard's avatar
Alexandre Julliard committed
797
    {
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
    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;
816 817 818
    case dbg_itype_unsigned_int:
        switch (ti)
        {
819 820 821
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 4; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
822 823 824 825 826 827
        default: WINE_FIXME("unsupported %u for u-int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_signed_int:
        switch (ti)
        {
828 829 830
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 4; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
831 832 833 834 835 836
        default: WINE_FIXME("unsupported %u for s-int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_unsigned_short_int:
        switch (ti)
        {
837 838 839
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 2; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
840 841 842 843 844 845
        default: WINE_FIXME("unsupported %u for u-short int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_signed_short_int:
        switch (ti)
        {
846 847 848
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 2; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
849 850 851 852 853 854
        default: WINE_FIXME("unsupported %u for s-short int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_unsigned_char_int:
        switch (ti)
        {
855 856 857
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 1; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
858 859 860 861 862 863
        default: WINE_FIXME("unsupported %u for u-char int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_signed_char_int:
        switch (ti)
        {
864 865 866
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 1; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
867 868 869 870 871 872
        default: WINE_FIXME("unsupported %u for s-char int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_char:
        switch (ti)
        {
873 874 875
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 1; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btChar; break;
876 877 878 879 880 881
        default: WINE_FIXME("unsupported %u for char int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_astring:
        switch (ti)
        {
882
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagPointerType; break;
883
        case TI_GET_LENGTH:     X(DWORD64) = ADDRSIZE; break;
884
        case TI_GET_TYPE:       X(DWORD)   = dbg_itype_char; break;
885 886 887
        default: WINE_FIXME("unsupported %u for a string\n", ti); return FALSE;
        }
        break;
888 889 890 891 892 893 894 895 896
    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;
897
    default: WINE_FIXME("unsupported type id 0x%lx\n", type->id);
Alexandre Julliard's avatar
Alexandre Julliard committed
898 899
    }

900 901
#undef X
    return TRUE;
902
}