types.c 29.1 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_deref
 *
 */
BOOL types_deref(const struct dbg_lvalue* lvalue, struct dbg_lvalue* result)
Alexandre Julliard's avatar
Alexandre Julliard committed
162
{
163 164
    struct dbg_type     type = lvalue->type;
    DWORD               tag;
165

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

    /*
     * Make sure that this really makes sense.
     */
173
    if (!types_get_real_type(&type, &tag) || tag != SymTagPointerType ||
174
        !memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset) ||
175
        !types_get_info(&type, TI_GET_TYPE, &result->type.id))
176
        return FALSE;
177
    result->type.module = type.module;
178 179 180 181 182 183 184 185 186 187 188 189 190 191
    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.
     */
192 193
    result->addr.Mode = AddrModeFlat;
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
194 195
}

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

208 209
    unsigned    mask;

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

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

232
        lvalue->cookie      = DLV_HOST;
233
        lvalue->addr.Offset = (ULONG_PTR)tmpbuf;
234 235 236 237 238 239

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

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

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

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

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

300 301 302 303 304 305 306
/******************************************************************
 *		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
307
{
308 309 310
    struct dbg_type     type = lvalue->type;
    DWORD               tag, count;
    DWORD64             length;
311

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

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

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

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

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

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

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

408 409
{
    struct type_find_t  f;
410 411
    struct dbg_type     ret;

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

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

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

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

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

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

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

555
leave:
Alexandre Julliard's avatar
Alexandre Julliard committed
556

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

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

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

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

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

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

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

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

            fcp->Start = 0;
            while (count)
642
            {
643
                fcp->Count = min(count, 256);
644
                if (types_get_info(type, TI_FINDCHILDREN, fcp))
645 646 647 648
                {
                    for (i = 0; i < min(fcp->Count, count); i++)
                    {
                        ptr = NULL;
649 650 651
                        type_elt.module = type->module;
                        type_elt.id = fcp->ChildId[i];
                        types_get_info(&type_elt, TI_GET_SYMNAME, &ptr);
652 653 654 655
                        if (!ptr) continue;
                        WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
                        HeapFree(GetProcessHeap(), 0, ptr);
                        dbg_printf("%s", tmp);
656
                        if (types_get_info(&type_elt, TI_GET_TYPE, &type_elt.id))
657 658
                        {
                            dbg_printf(":");
659
                            types_print_type(&type_elt, details);
660 661 662 663 664 665
                        }
                        if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
                    }
                }
                count -= min(count, 256);
                fcp->Start += 256;
666
            }
667
            dbg_printf("}");
668 669
        }
        break;
670
    case SymTagArrayType:
671 672 673
        types_get_info(type, TI_GET_TYPE, &subtype.id);
        subtype.module = type->module;
        types_print_type(&subtype, details);
674
        dbg_printf(" %s[]", name);
675
        break;
676 677
    case SymTagEnum:
        dbg_printf("enum %s", name);
678
        break;
679
    case SymTagFunctionType:
680
        types_get_info(type, TI_GET_TYPE, &subtype.id);
681 682 683 684 685 686 687 688 689 690
        /* 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>");
        }
691
        dbg_printf(" (*%s)(", name);
692
        if (types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
693 694 695 696 697 698 699 700 701
        {
            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);
702
                if (types_get_info(type, TI_FINDCHILDREN, fcp))
703 704 705
                {
                    for (i = 0; i < min(fcp->Count, count); i++)
                    {
706
                        subtype.id = fcp->ChildId[i];
707
                        types_get_info(&subtype, TI_GET_TYPE, &subtype.id);
708
                        types_print_type(&subtype, FALSE);
709 710 711 712 713 714 715 716
                        if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
                    }
                }
                count -= min(count, 256);
                fcp->Start += 256;
            }
        }
        dbg_printf(")");
717
        break;
718
    case SymTagTypedef:
719
        dbg_printf("%s", name);
720
        break;
721
    default:
722
        WINE_ERR("Unknown type %u for %s\n", tag, name);
723 724
        break;
    }
725
    
726
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
727 728
}

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

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

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

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

868 869
#undef X
    return TRUE;
870
}