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

123
    return rtn;
Alexandre Julliard's avatar
Alexandre Julliard committed
124 125
}

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

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

155 156 157 158 159
/******************************************************************
 *		types_deref
 *
 */
BOOL types_deref(const struct dbg_lvalue* lvalue, struct dbg_lvalue* result)
Alexandre Julliard's avatar
Alexandre Julliard committed
160
{
161 162
    struct dbg_type     type = lvalue->type;
    DWORD               tag;
163

164
    memset(result, 0, sizeof(*result));
165 166
    result->type.id = dbg_itype_none;
    result->type.module = 0;
167 168 169 170

    /*
     * Make sure that this really makes sense.
     */
171
    if (!types_get_real_type(&type, &tag) || tag != SymTagPointerType ||
172
        !memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset) ||
173
        !types_get_info(&type, TI_GET_TYPE, &result->type.id))
174
        return FALSE;
175
    result->type.module = type.module;
176 177 178 179 180 181 182 183 184 185 186 187 188 189
    result->cookie = DLV_TARGET;
    /* FIXME: this is currently buggy.
     * 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 force debuggee address space, because dereferencing pointers to
     * internal variables is very unlikely. A correct fix would be
     * rather large.
     */
190 191
    result->addr.Mode = AddrModeFlat;
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
192 193
}

194 195 196 197 198
/******************************************************************
 *		types_get_udt_element_lvalue
 *
 * Implement a structure derefencement
 */
199 200
static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, 
                                         const struct dbg_type* type, long int* tmpbuf)
201
{
202
    DWORD       offset, bitoffset;
203
    DWORD       bt;
204 205
    DWORD64     length;

206 207
    unsigned    mask;

208 209
    types_get_info(type, TI_GET_TYPE, &lvalue->type.id);
    lvalue->type.module = type->module;
Eric Pouech's avatar
Eric Pouech committed
210 211
    if (!types_get_info(type, TI_GET_OFFSET, &offset)) return FALSE;
    lvalue->addr.Offset += offset;
212

213
    if (types_get_info(type, TI_GET_BITPOSITION, &bitoffset))
214
    {
Eric Pouech's avatar
Eric Pouech committed
215 216 217 218 219 220
        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;
221 222 223 224 225
        /*
         * 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;
226
        mask = 0xffffffff << (DWORD)length;
227 228 229
        *tmpbuf >>= bitoffset & 7;
        *tmpbuf &= ~mask;

230
        lvalue->cookie      = DLV_HOST;
231 232 233 234 235 236 237
        lvalue->addr.Offset = (DWORD)tmpbuf;

        /*
         * 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.
         */
238
        if (types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt) && 
239
            bt == btInt && (*tmpbuf & (1 << ((DWORD)length - 1))))
240 241 242 243
        {
            *tmpbuf |= mask;
        }
    }
Eric Pouech's avatar
Eric Pouech committed
244
    else
245
    {
Eric Pouech's avatar
Eric Pouech committed
246
        if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE;
247
    }
Eric Pouech's avatar
Eric Pouech committed
248
    return TRUE;
249 250
}

251 252 253 254 255
/******************************************************************
 *		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
256
{
257 258 259 260 261
    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];
262
    struct dbg_type             type;
Alexandre Julliard's avatar
Alexandre Julliard committed
263

264
    if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag) ||
265 266
        tag != SymTagUDT)
        return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
267

268
    if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
Alexandre Julliard's avatar
Alexandre Julliard committed
269
    {
270 271 272 273
        fcp->Start = 0;
        while (count)
        {
            fcp->Count = min(count, 256);
274
            if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
275
            {
276
                unsigned i;
277
                type.module = lvalue->type.module;
278 279 280
                for (i = 0; i < min(fcp->Count, count); i++)
                {
                    ptr = NULL;
281 282
                    type.id = fcp->ChildId[i];
                    types_get_info(&type, TI_GET_SYMNAME, &ptr);
283 284 285 286 287
                    if (!ptr) continue;
                    WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
                    HeapFree(GetProcessHeap(), 0, ptr);
                    if (strcmp(tmp, name)) continue;

288
                    return types_get_udt_element_lvalue(lvalue, &type, tmpbuf);
289 290 291 292 293
                }
            }
            count -= min(count, 256);
            fcp->Start += 256;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
294
    }
295
    return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
296 297
}

298 299 300 301 302 303 304
/******************************************************************
 *		types_array_index
 *
 * Grab an element from an array
 */
BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, 
                       struct dbg_lvalue* result)
Alexandre Julliard's avatar
Alexandre Julliard committed
305
{
306 307 308
    struct dbg_type     type = lvalue->type;
    DWORD               tag, count;
    DWORD64             length;
309

310
    if (!types_get_real_type(&type, &tag)) return FALSE;
311 312 313
    switch (tag)
    {
    case SymTagArrayType:
314
        types_get_info(&type, TI_GET_COUNT, &count);
315 316 317
        if (index < 0 || index >= count) return FALSE;
        /* fall through */
    case SymTagPointerType:
Eric Pouech's avatar
Eric Pouech committed
318 319
        /* Contents of array share same data (addr mode, module...) */
        *result = *lvalue;
320 321 322
        /*
         * Get the base type, so we know how much to index by.
         */
323
        types_get_info(&type, TI_GET_TYPE, &result->type.id);
324
        types_get_info(&result->type, TI_GET_LENGTH, &length);
325
        memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset);
326
        result->addr.Offset += index * (DWORD)length;
327 328 329
        break;
    default:
        assert(FALSE);
Alexandre Julliard's avatar
Alexandre Julliard committed
330
    }
331 332
    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
333

334 335
struct type_find_t
{
336
    unsigned long       result; /* out: the found type */
337 338
    enum SymTagEnum     tag;    /* in: the tag to look for */
    union
Alexandre Julliard's avatar
Alexandre Julliard committed
339
    {
340 341
        unsigned long           typeid; /* when tag is SymTagUDT */
        const char*             name;   /* when tag is SymTagPointerType */
342 343
    } u;
};
Alexandre Julliard's avatar
Alexandre Julliard committed
344

345
static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
Alexandre Julliard's avatar
Alexandre Julliard committed
346
{
347 348
    struct type_find_t* user = (struct type_find_t*)_user;
    BOOL                ret = TRUE;
349
    struct dbg_type     type;
350
    DWORD               type_id;
Alexandre Julliard's avatar
Alexandre Julliard committed
351

352
    if (sym->Tag == user->tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
353
    {
354 355 356 357 358 359 360 361 362 363
        switch (user->tag)
        {
        case SymTagUDT:
            if (!strcmp(user->u.name, sym->Name))
            {
                user->result = sym->TypeIndex;
                ret = FALSE;
            }
            break;
        case SymTagPointerType:
364 365
            type.module = sym->ModBase;
            type.id = sym->TypeIndex;
366
            if (types_get_info(&type, TI_GET_TYPE, &type_id) && type_id == user->u.typeid)
367 368 369 370
            {
                user->result = sym->TypeIndex;
                ret = FALSE;
            }
371
            break;
372 373
        default: break;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
374
    }
375
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
376 377
}

378 379 380 381 382 383
/******************************************************************
 *		types_find_pointer
 *
 * Should look up in module based at linear whether (typeid*) exists
 * Otherwise, we could create it locally
 */
384
struct dbg_type types_find_pointer(const struct dbg_type* type)
Alexandre Julliard's avatar
Alexandre Julliard committed
385
{
386
    struct type_find_t  f;
387 388
    struct dbg_type     ret;

389 390
    f.result = dbg_itype_none;
    f.tag = SymTagPointerType;
391 392 393 394 395
    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
396 397
}

398 399 400 401 402 403
/******************************************************************
 *		types_find_type
 *
 * Should look up in the module based at linear address whether a type
 * named 'name' and with the correct tag exists
 */
404
struct dbg_type types_find_type(unsigned long linear, const char* name, enum SymTagEnum tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
405

406 407
{
    struct type_find_t  f;
408 409
    struct dbg_type     ret;

410 411 412 413
    f.result = dbg_itype_none;
    f.tag = tag;
    f.u.name = name;
    SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f);
414 415 416
    ret.module = linear;
    ret.id = f.result;
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
417 418
}

419 420 421 422 423 424
/***********************************************************************
 *           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
425
{
426
    struct dbg_type     type = lvalue->type;
427 428 429 430
    struct dbg_lvalue   lvalue_field;
    int		        i;
    DWORD               tag;
    DWORD               count;
431
    DWORD64             size;
Alexandre Julliard's avatar
Alexandre Julliard committed
432

433 434 435 436 437 438 439
    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
440
    {
441 442 443
        /* No type, just print the addr value */
        print_bare_address(&lvalue->addr);
        goto leave;
Alexandre Julliard's avatar
Alexandre Julliard committed
444 445
    }

446
    if (format == 'i' || format == 's' || format == 'w' || format == 'b' || format == 'g')
Alexandre Julliard's avatar
Alexandre Julliard committed
447
    {
448 449
        dbg_printf("Format specifier '%c' is meaningless in 'print' command\n", format);
        format = '\0';
Alexandre Julliard's avatar
Alexandre Julliard committed
450 451
    }

452
    switch (tag)
Alexandre Julliard's avatar
Alexandre Julliard committed
453
    {
454 455 456
    case SymTagBaseType:
    case SymTagEnum:
    case SymTagPointerType:
457 458 459
        /* FIXME: this in not 100% optimal (as we're going through the typedef handling
         * stuff again
         */
460 461 462
        print_basic(lvalue, 1, format);
        break;
    case SymTagUDT:
463
        if (types_get_info(&type, TI_GET_CHILDRENCOUNT, &count))
464 465 466 467 468 469
        {
            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;
470
            struct dbg_type             sub_type;
471 472 473 474 475 476

            dbg_printf("{");
            fcp->Start = 0;
            while (count)
            {
                fcp->Count = min(count, 256);
477
                if (types_get_info(&type, TI_FINDCHILDREN, fcp))
478 479 480 481
                {
                    for (i = 0; i < min(fcp->Count, count); i++)
                    {
                        ptr = NULL;
482 483 484
                        sub_type.module = type.module;
                        sub_type.id = fcp->ChildId[i];
                        types_get_info(&sub_type, TI_GET_SYMNAME, &ptr);
485 486 487 488 489
                        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;
490
                        if (types_get_udt_element_lvalue(&lvalue_field, &sub_type, &tmpbuf))
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
                        {
                            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;
508 509
        types_get_info(&type, TI_GET_COUNT, &count);
        types_get_info(&type, TI_GET_LENGTH, &size);
510 511

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

553
leave:
Alexandre Julliard's avatar
Alexandre Julliard committed
554

555
    if (level == 0) dbg_printf("\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
556 557
}

558
static BOOL CALLBACK print_types_cb(PSYMBOL_INFO sym, ULONG size, void* ctx)
Alexandre Julliard's avatar
Alexandre Julliard committed
559
{
560 561 562
    struct dbg_type     type;
    type.module = sym->ModBase;
    type.id = sym->TypeIndex;
563
    dbg_printf("Mod: %08x ID: %08lx \n", type.module, type.id);
564
    types_print_type(&type, TRUE);
565 566
    dbg_printf("\n");
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
567 568
}

569
static BOOL CALLBACK print_types_mod_cb(PCSTR mod_name, ULONG base, PVOID ctx)
Alexandre Julliard's avatar
Alexandre Julliard committed
570
{
571
    return SymEnumTypes(dbg_curr_process->handle, base, print_types_cb, ctx);
Alexandre Julliard's avatar
Alexandre Julliard committed
572 573
}

574
int print_types(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
575
{
576 577 578 579 580
    if (!dbg_curr_process)
    {
        dbg_printf("No known process, cannot print types\n");
        return 0;
    }
581 582
    SymEnumerateModules(dbg_curr_process->handle, print_types_mod_cb, NULL);
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
583 584
}

585
int types_print_type(const struct dbg_type* type, BOOL details)
Alexandre Julliard's avatar
Alexandre Julliard committed
586
{
587 588 589
    WCHAR*              ptr;
    char                tmp[256];
    const char*         name;
590 591
    DWORD               tag, udt, count;
    struct dbg_type     subtype;
Alexandre Julliard's avatar
Alexandre Julliard committed
592

593
    if (type->id == dbg_itype_none || !types_get_info(type, TI_GET_SYMTAG, &tag))
Alexandre Julliard's avatar
Alexandre Julliard committed
594
    {
595
        dbg_printf("--invalid--<%lxh>--", type->id);
596
        return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
597 598
    }

599
    if (types_get_info(type, TI_GET_SYMNAME, &ptr) && ptr)
Alexandre Julliard's avatar
Alexandre Julliard committed
600
    {
601 602 603
        WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
        name = tmp;
        HeapFree(GetProcessHeap(), 0, ptr);
Alexandre Julliard's avatar
Alexandre Julliard committed
604
    }
605
    else name = "--none--";
Alexandre Julliard's avatar
Alexandre Julliard committed
606

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

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

            fcp->Start = 0;
            while (count)
            {
                fcp->Count = min(count, 256);
700
                if (types_get_info(type, TI_FINDCHILDREN, fcp))
701 702 703
                {
                    for (i = 0; i < min(fcp->Count, count); i++)
                    {
704
                        subtype.id = fcp->ChildId[i];
705
                        types_get_info(&subtype, TI_GET_TYPE, &subtype.id);
706
                        types_print_type(&subtype, FALSE);
707 708 709 710 711 712 713 714
                        if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
                    }
                }
                count -= min(count, 256);
                fcp->Start += 256;
            }
        }
        dbg_printf(")");
715
        break;
716 717 718
    case SymTagTypedef:
        dbg_printf(name);
        break;
719
    default:
720
        WINE_ERR("Unknown type %u for %s\n", tag, name);
721 722
        break;
    }
723
    
724
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
725 726
}

727 728 729
/* helper to typecast pInfo to its expected type (_t) */
#define X(_t) (*((_t*)pInfo))

730
BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
Alexandre Julliard's avatar
Alexandre Julliard committed
731
{
732 733
    if (type->id == dbg_itype_none) return FALSE;
    if (type->module != 0)
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 759 760 761 762 763 764 765
    {
        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;
766
            default:            WINE_FIXME("Unsupported basic type %u\n", bt); return FALSE;
767 768 769 770 771 772 773 774 775 776
            }
            X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name) + 1) * sizeof(WCHAR));
            if (X(WCHAR*))
            {
                lstrcpyW(X(WCHAR*), name);
                ret = TRUE;
            }
        }
        return ret;
    }
777

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

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

866 867
#undef X
    return TRUE;
868
}