types.c 29.7 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
LONGLONG types_extract_as_longlong(const struct dbg_lvalue* lvalue, unsigned* psize)
Alexandre Julliard's avatar
Alexandre Julliard committed
57
{
58
    LONGLONG            rtn;
59 60
    DWORD               tag, bt;
    DWORD64             size;
61
    struct dbg_type     type = lvalue->type;
Alexandre Julliard's avatar
Alexandre Julliard committed
62

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

66
    if (type.id == dbg_itype_segptr)
67 68 69 70
    {
        return (long int)memory_to_linear_addr(&lvalue->addr);
    }

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

125
    return rtn;
Alexandre Julliard's avatar
Alexandre Julliard committed
126 127
}

128 129 130 131 132 133 134 135
/******************************************************************
 *		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)
{
136
    return types_extract_as_longlong(lvalue, NULL);
137 138
}

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

157 158 159 160 161
/******************************************************************
 *		types_get_udt_element_lvalue
 *
 * Implement a structure derefencement
 */
162 163
static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, 
                                         const struct dbg_type* type, long int* tmpbuf)
164
{
165
    DWORD       offset, bitoffset;
166
    DWORD       bt;
167 168
    DWORD64     length;

169 170
    unsigned    mask;

171 172
    types_get_info(type, TI_GET_TYPE, &lvalue->type.id);
    lvalue->type.module = type->module;
Eric Pouech's avatar
Eric Pouech committed
173 174
    if (!types_get_info(type, TI_GET_OFFSET, &offset)) return FALSE;
    lvalue->addr.Offset += offset;
175

176
    if (types_get_info(type, TI_GET_BITPOSITION, &bitoffset))
177
    {
Eric Pouech's avatar
Eric Pouech committed
178 179 180 181 182 183
        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;
184 185 186 187 188
        /*
         * 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;
189
        mask = 0xffffffff << (DWORD)length;
190 191 192
        *tmpbuf >>= bitoffset & 7;
        *tmpbuf &= ~mask;

193
        lvalue->cookie      = DLV_HOST;
194
        lvalue->addr.Offset = (ULONG_PTR)tmpbuf;
195 196 197 198 199 200

        /*
         * 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.
         */
201
        if (types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt) && 
202
            bt == btInt && (*tmpbuf & (1 << ((DWORD)length - 1))))
203 204 205 206
        {
            *tmpbuf |= mask;
        }
    }
Eric Pouech's avatar
Eric Pouech committed
207
    else
208
    {
Eric Pouech's avatar
Eric Pouech committed
209
        if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE;
210
    }
Eric Pouech's avatar
Eric Pouech committed
211
    return TRUE;
212 213
}

214 215 216 217 218
/******************************************************************
 *		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
219
{
220 221 222 223 224
    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];
225
    struct dbg_type             type;
Alexandre Julliard's avatar
Alexandre Julliard committed
226

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

230
    if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
Alexandre Julliard's avatar
Alexandre Julliard committed
231
    {
232 233 234 235
        fcp->Start = 0;
        while (count)
        {
            fcp->Count = min(count, 256);
236
            if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
237
            {
238
                unsigned i;
239
                type.module = lvalue->type.module;
240 241 242
                for (i = 0; i < min(fcp->Count, count); i++)
                {
                    ptr = NULL;
243 244
                    type.id = fcp->ChildId[i];
                    types_get_info(&type, TI_GET_SYMNAME, &ptr);
245 246 247 248 249
                    if (!ptr) continue;
                    WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
                    HeapFree(GetProcessHeap(), 0, ptr);
                    if (strcmp(tmp, name)) continue;

250
                    return types_get_udt_element_lvalue(lvalue, &type, tmpbuf);
251 252 253 254 255
                }
            }
            count -= min(count, 256);
            fcp->Start += 256;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
256
    }
257
    return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
258 259
}

260 261 262 263 264
/******************************************************************
 *		types_array_index
 *
 * Grab an element from an array
 */
265
BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, struct dbg_lvalue* result)
Alexandre Julliard's avatar
Alexandre Julliard committed
266
{
267 268
    struct dbg_type     type = lvalue->type;
    DWORD               tag, count;
269 270 271 272

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

274
    if (!types_get_real_type(&type, &tag)) return FALSE;
275 276 277
    switch (tag)
    {
    case SymTagArrayType:
278
        if (!types_get_info(&type, TI_GET_COUNT, &count)) return FALSE;
279
        if (index < 0 || index >= count) return FALSE;
280
        result->addr = lvalue->addr;
281
        break;
282
    case SymTagPointerType:
283 284 285 286 287 288 289 290
        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);
        }
291 292 293
        break;
    default:
        assert(FALSE);
Alexandre Julliard's avatar
Alexandre Julliard committed
294
    }
295 296 297
    /*
     * Get the base type, so we know how much to index by.
     */
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
    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).
     * There is no way to tell were the deref:ed value is...
     * 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;
320 321
    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
322

323 324
struct type_find_t
{
325
    unsigned long       result; /* out: the found type */
326 327
    enum SymTagEnum     tag;    /* in: the tag to look for */
    union
Alexandre Julliard's avatar
Alexandre Julliard committed
328
    {
329 330
        unsigned long           typeid; /* when tag is SymTagUDT */
        const char*             name;   /* when tag is SymTagPointerType */
331 332
    } u;
};
Alexandre Julliard's avatar
Alexandre Julliard committed
333

334
static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
Alexandre Julliard's avatar
Alexandre Julliard committed
335
{
336
    struct type_find_t* user = _user;
337
    BOOL                ret = TRUE;
338
    struct dbg_type     type;
339
    DWORD               type_id;
Alexandre Julliard's avatar
Alexandre Julliard committed
340

341
    if (sym->Tag == user->tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
342
    {
343 344 345 346 347 348 349 350 351 352
        switch (user->tag)
        {
        case SymTagUDT:
            if (!strcmp(user->u.name, sym->Name))
            {
                user->result = sym->TypeIndex;
                ret = FALSE;
            }
            break;
        case SymTagPointerType:
353 354
            type.module = sym->ModBase;
            type.id = sym->TypeIndex;
355
            if (types_get_info(&type, TI_GET_TYPE, &type_id) && type_id == user->u.typeid)
356 357 358 359
            {
                user->result = sym->TypeIndex;
                ret = FALSE;
            }
360
            break;
361 362
        default: break;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
363
    }
364
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
365 366
}

367 368 369 370 371 372
/******************************************************************
 *		types_find_pointer
 *
 * Should look up in module based at linear whether (typeid*) exists
 * Otherwise, we could create it locally
 */
373
struct dbg_type types_find_pointer(const struct dbg_type* type)
Alexandre Julliard's avatar
Alexandre Julliard committed
374
{
375
    struct type_find_t  f;
376 377
    struct dbg_type     ret;

378 379
    f.result = dbg_itype_none;
    f.tag = SymTagPointerType;
380 381 382 383 384
    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
385 386
}

387 388 389 390 391 392
/******************************************************************
 *		types_find_type
 *
 * Should look up in the module based at linear address whether a type
 * named 'name' and with the correct tag exists
 */
393
struct dbg_type types_find_type(unsigned long linear, const char* name, enum SymTagEnum tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
394

395 396
{
    struct type_find_t  f;
397 398
    struct dbg_type     ret;

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

408 409 410 411 412 413
/***********************************************************************
 *           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
414
{
415
    struct dbg_type     type = lvalue->type;
416 417 418 419
    struct dbg_lvalue   lvalue_field;
    int		        i;
    DWORD               tag;
    DWORD               count;
420
    DWORD64             size;
Alexandre Julliard's avatar
Alexandre Julliard committed
421

422 423 424 425 426 427 428
    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
429
    {
430 431 432
        /* No type, just print the addr value */
        print_bare_address(&lvalue->addr);
        goto leave;
Alexandre Julliard's avatar
Alexandre Julliard committed
433 434
    }

435
    if (format == 'i' || format == 's' || format == 'w' || format == 'b' || format == 'g')
Alexandre Julliard's avatar
Alexandre Julliard committed
436
    {
437 438
        dbg_printf("Format specifier '%c' is meaningless in 'print' command\n", format);
        format = '\0';
Alexandre Julliard's avatar
Alexandre Julliard committed
439 440
    }

441
    switch (tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
442
    {
443 444 445
    case SymTagBaseType:
    case SymTagEnum:
    case SymTagPointerType:
446 447 448
        /* FIXME: this in not 100% optimal (as we're going through the typedef handling
         * stuff again
         */
449
        print_basic(lvalue, format);
450 451
        break;
    case SymTagUDT:
452
        if (types_get_info(&type, TI_GET_CHILDRENCOUNT, &count))
453 454 455 456 457 458
        {
            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;
459
            struct dbg_type             sub_type;
460 461 462 463 464 465

            dbg_printf("{");
            fcp->Start = 0;
            while (count)
            {
                fcp->Count = min(count, 256);
466
                if (types_get_info(&type, TI_FINDCHILDREN, fcp))
467 468 469 470
                {
                    for (i = 0; i < min(fcp->Count, count); i++)
                    {
                        ptr = NULL;
471 472 473
                        sub_type.module = type.module;
                        sub_type.id = fcp->ChildId[i];
                        types_get_info(&sub_type, TI_GET_SYMNAME, &ptr);
474 475 476 477 478
                        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;
479
                        if (types_get_udt_element_lvalue(&lvalue_field, &sub_type, &tmpbuf))
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
                        {
                            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;
497 498
        types_get_info(&type, TI_GET_COUNT, &count);
        types_get_info(&type, TI_GET_LENGTH, &size);
499 500

        if (size == count)
Alexandre Julliard's avatar
Alexandre Julliard committed
501
	{
502 503 504 505 506 507 508
            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));
509
            memory_get_string(dbg_curr_process,
510
                              memory_to_linear_addr(&lvalue->addr),
511
                              lvalue->cookie == DLV_TARGET, TRUE, buffer, len);
512 513 514 515
            dbg_printf("\"%s%s\"", buffer, (len < count) ? "..." : "");
            break;
        }
        lvalue_field = *lvalue;
516
        types_get_info(&type, TI_GET_TYPE, &lvalue_field.type.id);
517 518
        dbg_printf("{");
        for (i = 0; i < count; i++)
Alexandre Julliard's avatar
Alexandre Julliard committed
519
	{
520 521 522
            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
523
	}
524 525 526 527 528
        break;
    case SymTagFunctionType:
        dbg_printf("Function ");
        print_bare_address(&lvalue->addr);
        dbg_printf(": ");
529
        types_print_type(&type, FALSE);
530
        break;
531 532 533 534 535
    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
536
    default:
537
        WINE_FIXME("Unknown tag (%u)\n", tag);
538 539
        RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
540 541
    }

542
leave:
Alexandre Julliard's avatar
Alexandre Julliard committed
543

544
    if (level == 0) dbg_printf("\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
545 546
}

547
static BOOL CALLBACK print_types_cb(PSYMBOL_INFO sym, ULONG size, void* ctx)
Alexandre Julliard's avatar
Alexandre Julliard committed
548
{
549 550 551
    struct dbg_type     type;
    type.module = sym->ModBase;
    type.id = sym->TypeIndex;
552
    dbg_printf("Mod: %08lx ID: %08lx\n", type.module, type.id);
553
    types_print_type(&type, TRUE);
554 555
    dbg_printf("\n");
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
556 557
}

558
static BOOL CALLBACK print_types_mod_cb(PCSTR mod_name, DWORD64 base, PVOID ctx)
Alexandre Julliard's avatar
Alexandre Julliard committed
559
{
560
    return SymEnumTypes(dbg_curr_process->handle, base, print_types_cb, ctx);
Alexandre Julliard's avatar
Alexandre Julliard committed
561 562
}

563
int print_types(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
564
{
565 566 567 568 569
    if (!dbg_curr_process)
    {
        dbg_printf("No known process, cannot print types\n");
        return 0;
    }
570
    SymEnumerateModules64(dbg_curr_process->handle, print_types_mod_cb, NULL);
571
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
572 573
}

574
int types_print_type(const struct dbg_type* type, BOOL details)
Alexandre Julliard's avatar
Alexandre Julliard committed
575
{
576 577 578
    WCHAR*              ptr;
    char                tmp[256];
    const char*         name;
579 580
    DWORD               tag, udt, count;
    struct dbg_type     subtype;
Alexandre Julliard's avatar
Alexandre Julliard committed
581

582
    if (type->id == dbg_itype_none || !types_get_info(type, TI_GET_SYMTAG, &tag))
Alexandre Julliard's avatar
Alexandre Julliard committed
583
    {
584
        dbg_printf("--invalid--<%lxh>--", type->id);
585
        return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
586 587
    }

588
    if (types_get_info(type, TI_GET_SYMNAME, &ptr) && ptr)
Alexandre Julliard's avatar
Alexandre Julliard committed
589
    {
590 591 592
        WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
        name = tmp;
        HeapFree(GetProcessHeap(), 0, ptr);
Alexandre Julliard's avatar
Alexandre Julliard committed
593
    }
594
    else name = "--none--";
Alexandre Julliard's avatar
Alexandre Julliard committed
595

596
    switch (tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
597
    {
598 599
    case SymTagBaseType:
        if (details) dbg_printf("Basic<%s>", name); else dbg_printf("%s", name);
600
        break;
601
    case SymTagPointerType:
602 603 604
        types_get_info(type, TI_GET_TYPE, &subtype.id);
        subtype.module = type->module;
        types_print_type(&subtype, FALSE);
605
        dbg_printf("*");
606
        break;
607
    case SymTagUDT:
608 609
        types_get_info(type, TI_GET_UDTKIND, &udt);
        switch (udt)
610 611 612 613
        {
        case UdtStruct: dbg_printf("struct %s", name); break;
        case UdtUnion:  dbg_printf("union %s", name); break;
        case UdtClass:  dbg_printf("class %s", name); break;
614
        default:        WINE_ERR("Unsupported UDT type (%d) for %s\n", udt, name); break;
615 616
        }
        if (details &&
617
            types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
618
        {
619 620 621 622 623
            char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
            TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
            WCHAR*                      ptr;
            char                        tmp[256];
            int                         i;
624
            struct dbg_type             type_elt;
625 626 627 628
            dbg_printf(" {");

            fcp->Start = 0;
            while (count)
629
            {
630
                fcp->Count = min(count, 256);
631
                if (types_get_info(type, TI_FINDCHILDREN, fcp))
632 633 634 635
                {
                    for (i = 0; i < min(fcp->Count, count); i++)
                    {
                        ptr = NULL;
636 637 638
                        type_elt.module = type->module;
                        type_elt.id = fcp->ChildId[i];
                        types_get_info(&type_elt, TI_GET_SYMNAME, &ptr);
639 640 641 642
                        if (!ptr) continue;
                        WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
                        HeapFree(GetProcessHeap(), 0, ptr);
                        dbg_printf("%s", tmp);
643
                        if (types_get_info(&type_elt, TI_GET_TYPE, &type_elt.id))
644 645
                        {
                            dbg_printf(":");
646
                            types_print_type(&type_elt, details);
647 648 649 650 651 652
                        }
                        if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
                    }
                }
                count -= min(count, 256);
                fcp->Start += 256;
653
            }
654
            dbg_printf("}");
655 656
        }
        break;
657
    case SymTagArrayType:
658 659 660
        types_get_info(type, TI_GET_TYPE, &subtype.id);
        subtype.module = type->module;
        types_print_type(&subtype, details);
661 662 663 664
        if (types_get_info(type, TI_GET_COUNT, &count))
            dbg_printf(" %s[%d]", name, count);
        else
            dbg_printf(" %s[]", name);
665
        break;
666 667
    case SymTagEnum:
        dbg_printf("enum %s", name);
668
        break;
669
    case SymTagFunctionType:
670
        types_get_info(type, TI_GET_TYPE, &subtype.id);
671 672 673 674 675 676 677 678 679 680
        /* 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
        {
            dbg_printf("<ret_type=self>");
        }
681
        dbg_printf(" (*%s)(", name);
682
        if (types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
683 684 685 686 687 688
        {
            char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
            TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
            int                         i;

            fcp->Start = 0;
689 690
            if (!count) dbg_printf("void");
            else while (count)
691 692
            {
                fcp->Count = min(count, 256);
693
                if (types_get_info(type, TI_FINDCHILDREN, fcp))
694 695 696
                {
                    for (i = 0; i < min(fcp->Count, count); i++)
                    {
697
                        subtype.id = fcp->ChildId[i];
698
                        types_get_info(&subtype, TI_GET_TYPE, &subtype.id);
699
                        types_print_type(&subtype, FALSE);
700 701 702 703 704 705 706 707
                        if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
                    }
                }
                count -= min(count, 256);
                fcp->Start += 256;
            }
        }
        dbg_printf(")");
708
        break;
709
    case SymTagTypedef:
710
        dbg_printf("%s", name);
711
        break;
712
    default:
713
        WINE_ERR("Unknown type %u for %s\n", tag, name);
714 715
        break;
    }
716
    
717
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
718 719
}

720 721 722
/* helper to typecast pInfo to its expected type (_t) */
#define X(_t) (*((_t*)pInfo))

723
BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
Alexandre Julliard's avatar
Alexandre Julliard committed
724
{
725 726
    if (type->id == dbg_itype_none) return FALSE;
    if (type->module != 0)
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758
    {
        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;
759
            default:            WINE_FIXME("Unsupported basic type %u\n", bt); return FALSE;
760 761 762 763 764 765 766 767 768 769
            }
            X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name) + 1) * sizeof(WCHAR));
            if (X(WCHAR*))
            {
                lstrcpyW(X(WCHAR*), name);
                ret = TRUE;
            }
        }
        return ret;
    }
770

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

773
    switch (type->id)
Alexandre Julliard's avatar
Alexandre Julliard committed
774
    {
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792
    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;
793 794 795
    case dbg_itype_unsigned_int:
        switch (ti)
        {
796 797 798
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 4; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
799 800 801 802 803 804
        default: WINE_FIXME("unsupported %u for u-int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_signed_int:
        switch (ti)
        {
805 806 807
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 4; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
808 809 810 811 812 813
        default: WINE_FIXME("unsupported %u for s-int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_unsigned_short_int:
        switch (ti)
        {
814 815 816
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 2; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
817 818 819 820 821 822
        default: WINE_FIXME("unsupported %u for u-short int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_signed_short_int:
        switch (ti)
        {
823 824 825
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 2; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
826 827 828 829 830 831
        default: WINE_FIXME("unsupported %u for s-short int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_unsigned_char_int:
        switch (ti)
        {
832 833 834
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 1; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btUInt; break;
835 836 837 838 839 840
        default: WINE_FIXME("unsupported %u for u-char int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_signed_char_int:
        switch (ti)
        {
841 842 843
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 1; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btInt; break;
844 845 846 847 848 849
        default: WINE_FIXME("unsupported %u for s-char int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_char:
        switch (ti)
        {
850 851 852
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagBaseType; break;
        case TI_GET_LENGTH:     X(DWORD64) = 1; break;
        case TI_GET_BASETYPE:   X(DWORD)   = btChar; break;
853 854 855 856 857 858
        default: WINE_FIXME("unsupported %u for char int\n", ti); return FALSE;
        }
        break;
    case dbg_itype_astring:
        switch (ti)
        {
859
        case TI_GET_SYMTAG:     X(DWORD)   = SymTagPointerType; break;
860
        case TI_GET_LENGTH:     X(DWORD64) = ADDRSIZE; break;
861
        case TI_GET_TYPE:       X(DWORD)   = dbg_itype_char; break;
862 863 864
        default: WINE_FIXME("unsupported %u for a string\n", ti); return FALSE;
        }
        break;
865 866 867 868 869 870 871 872 873
    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;
874
    default: WINE_FIXME("unsupported type id 0x%lx\n", type->id);
Alexandre Julliard's avatar
Alexandre Julliard committed
875 876
    }

877 878
#undef X
    return TRUE;
879
}