dwarf.c 76.4 KB
Newer Older
1 2 3 4
/*
 * File dwarf.c - read dwarf2 information from the ELF modules
 *
 * Copyright (C) 2005, Raphael Junqueira
5
 * Copyright (C) 2006, Eric Pouech
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * 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
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 21
 */

22 23
#define NONAMELESSUNION

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
#include "config.h"

#include <sys/types.h>
#include <fcntl.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdio.h>
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#endif
#include <assert.h>
#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
49 50 51
#include "winuser.h"
#include "ole2.h"
#include "oleauto.h"
52 53 54 55 56 57 58

#include "dbghelp_private.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_dwarf);

59 60 61 62
/* FIXME:
 * - Functions:
 *      o unspecified parameters
 *      o inlined functions
63
 *      o Debug{Start|End}Point
64
 *      o CFA
65
 * - Udt
66
 *      o proper types loading (nesting)
67
 */
68

69
#if 0
70 71
static void dump(const void* ptr, unsigned len)
{
72 73 74
    int         i, j;
    BYTE        msg[128];
    static const char hexof[] = "0123456789abcdef";
75
    const       BYTE* x = ptr;
76 77

    for (i = 0; i < len; i += 16)
78
    {
79 80 81 82 83 84 85 86 87 88 89 90 91
        sprintf(msg, "%08x: ", i);
        memset(msg + 10, ' ', 3 * 16 + 1 + 16);
        for (j = 0; j < min(16, len - i); j++)
        {
            msg[10 + 3 * j + 0] = hexof[x[i + j] >> 4];
            msg[10 + 3 * j + 1] = hexof[x[i + j] & 15];
            msg[10 + 3 * j + 2] = ' ';
            msg[10 + 3 * 16 + 1 + j] = (x[i + j] >= 0x20 && x[i + j] < 0x7f) ?
                x[i + j] : '.';
        }
        msg[10 + 3 * 16] = ' ';
        msg[10 + 3 * 16 + 1 + 16] = '\0';
        TRACE("%s\n", msg);
92 93
    }
}
94
#endif
95

96 97 98 99 100 101 102 103 104 105 106 107
/**
 *
 * Main Specs:
 *  http://www.eagercon.com/dwarf/dwarf3std.htm
 *  http://www.eagercon.com/dwarf/dwarf-2.0.0.pdf
 *
 * dwarf2.h: http://www.hakpetzna.com/b/binutils/dwarf2_8h-source.html
 *
 * example of projects who do dwarf2 parsing:
 *  http://www.x86-64.org/cgi-bin/cvsweb.cgi/binutils.dead/binutils/readelf.c?rev=1.1.1.2
 *  http://elis.ugent.be/diota/log/ltrace_elf.c
 */
108
#include "dwarf.h"
109

110 111 112 113
/**
 * Parsers
 */

114 115
typedef struct dwarf2_abbrev_entry_attr_s
{
Raphael Junqueira's avatar
Raphael Junqueira committed
116 117 118 119 120
  unsigned long attribute;
  unsigned long form;
  struct dwarf2_abbrev_entry_attr_s* next;
} dwarf2_abbrev_entry_attr_t;

121 122 123 124 125 126 127
typedef struct dwarf2_abbrev_entry_s
{
    unsigned long entry_code;
    unsigned long tag;
    unsigned char have_child;
    unsigned num_attr;
    dwarf2_abbrev_entry_attr_t* attrs;
Raphael Junqueira's avatar
Raphael Junqueira committed
128 129
} dwarf2_abbrev_entry_t;

130 131 132 133 134 135
struct dwarf2_block
{
    unsigned                    size;
    const unsigned char*        ptr;
};

136
struct attribute
137
{
138
    unsigned long               form;
139 140 141 142 143
    union
    {
        unsigned long                   uvalue;
        long                            svalue;
        const char*                     string;
144
        struct dwarf2_block             block;
145
    } u;
146 147 148 149 150 151
};

typedef struct dwarf2_debug_info_s
{
    const dwarf2_abbrev_entry_t*abbrev;
    struct symt*                symt;
152
    const unsigned char**       data;
153 154 155
    struct vector               children;
} dwarf2_debug_info_t;

156 157 158 159 160 161
typedef struct dwarf2_section_s
{
    const unsigned char*        address;
    unsigned                    size;
} dwarf2_section_t;

162
enum dwarf2_sections {section_debug, section_string, section_abbrev, section_line, section_max};
163 164 165 166 167 168 169 170 171

typedef struct dwarf2_traverse_context_s
{
    const unsigned char*        data;
    const unsigned char*        start_data;
    const unsigned char*        end_data;
    unsigned char               word_size;
} dwarf2_traverse_context_t;

172 173 174 175 176 177 178
/* symt_cache indexes */
#define sc_void 0
#define sc_int1 1
#define sc_int2 2
#define sc_int4 3
#define sc_num  4

179 180
typedef struct dwarf2_parse_context_s
{
181 182
    const dwarf2_section_t*     sections;
    unsigned                    section;
183 184
    struct pool                 pool;
    struct module*              module;
Eric Pouech's avatar
Eric Pouech committed
185
    const struct elf_thunk_area*thunks;
186 187
    struct sparse_array         abbrev_table;
    struct sparse_array         debug_info_table;
188
    unsigned long               load_offset;
189
    unsigned long               ref_offset;
190
    unsigned char               word_size;
191
    struct symt*                symt_cache[sc_num]; /* void, int1, int2, int4 */
192 193
} dwarf2_parse_context_t;

194 195 196 197 198 199
/* stored in the dbghelp's module internal structure for later reuse */
struct dwarf2_module_info_s
{
    dwarf2_section_t            debug_loc;
};

200 201 202
#define loc_dwarf2_location_list        (loc_user + 0)
#define loc_dwarf2_block                (loc_user + 1)

203
/* forward declarations */
Eric Pouech's avatar
Eric Pouech committed
204
static struct symt* dwarf2_parse_enumeration_type(dwarf2_parse_context_t* ctx, dwarf2_debug_info_t* entry);
205

206 207 208 209 210
static unsigned char dwarf2_get_byte(const unsigned char* ptr)
{
    return *ptr;
}

211
static unsigned char dwarf2_parse_byte(dwarf2_traverse_context_t* ctx)
212
{
213
    unsigned char uvalue = dwarf2_get_byte(ctx->data);
214 215
    ctx->data += 1;
    return uvalue;
216 217
}

218 219 220 221 222
static unsigned short dwarf2_get_u2(const unsigned char* ptr)
{
    return *(const unsigned short*)ptr;
}

223
static unsigned short dwarf2_parse_u2(dwarf2_traverse_context_t* ctx)
224
{
225
    unsigned short uvalue = dwarf2_get_u2(ctx->data);
226 227
    ctx->data += 2;
    return uvalue;
228 229
}

230 231 232 233 234
static unsigned long dwarf2_get_u4(const unsigned char* ptr)
{
    return *(const unsigned long*)ptr;
}

235
static unsigned long dwarf2_parse_u4(dwarf2_traverse_context_t* ctx)
236
{
237
    unsigned long uvalue = dwarf2_get_u4(ctx->data);
238 239
    ctx->data += 4;
    return uvalue;
240 241
}

242
static unsigned long dwarf2_get_leb128_as_unsigned(const unsigned char* ptr, const unsigned char** end)
243
{
244 245 246
    unsigned long ret = 0;
    unsigned char byte;
    unsigned shift = 0;
247

248
    do
249
    {
250
        byte = dwarf2_get_byte(ptr++);
251 252
        ret |= (byte & 0x7f) << shift;
        shift += 7;
253 254
    } while (byte & 0x80);

255
    if (end) *end = ptr;
256
    return ret;
257 258
}

259 260 261 262 263 264 265 266 267 268 269 270
static unsigned long dwarf2_leb128_as_unsigned(dwarf2_traverse_context_t* ctx)
{
    unsigned long ret;

    assert(ctx);

    ret = dwarf2_get_leb128_as_unsigned(ctx->data, &ctx->data);

    return ret;
}

static long dwarf2_get_leb128_as_signed(const unsigned char* ptr, const unsigned char** end)
271
{
272 273 274 275 276
    long ret = 0;
    unsigned char byte;
    unsigned shift = 0;
    const unsigned size = sizeof(int) * 8;

277
    do
278
    {
279
        byte = dwarf2_get_byte(ptr++);
280 281
        ret |= (byte & 0x7f) << shift;
        shift += 7;
282
    } while (byte & 0x80);
283
    if (end) *end = ptr;
284

285 286 287 288 289 290 291 292
    /* as spec: sign bit of byte is 2nd high order bit (80x40)
     *  -> 0x80 is used as flag.
     */
    if ((shift < size) && (byte & 0x40))
    {
        ret |= - (1 << shift);
    }
    return ret;
293 294
}

295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
static long dwarf2_leb128_as_signed(dwarf2_traverse_context_t* ctx)
{
    long ret = 0;

    assert(ctx);

    ret = dwarf2_get_leb128_as_signed(ctx->data, &ctx->data);
    return ret;
}

static unsigned dwarf2_leb128_length(const dwarf2_traverse_context_t* ctx)
{
    unsigned    ret;
    for (ret = 0; ctx->data[ret] & 0x80; ret++);
    return ret + 1;
}

static unsigned long dwarf2_get_addr(const unsigned char* ptr, unsigned word_size)
313 314 315
{
    unsigned long ret;

316
    switch (word_size)
317 318
    {
    case 4:
319
        ret = dwarf2_get_u4(ptr);
320 321
        break;
    default:
322
        FIXME("Unsupported Word Size %u\n", word_size);
323 324 325 326 327
        ret = 0;
    }
    return ret;
}

328 329 330 331 332 333 334
static unsigned long dwarf2_parse_addr(dwarf2_traverse_context_t* ctx)
{
    unsigned long ret = dwarf2_get_addr(ctx->data, ctx->word_size);
    ctx->data += ctx->word_size;
    return ret;
}

335 336
static const char* dwarf2_debug_traverse_ctx(const dwarf2_traverse_context_t* ctx) 
{
337
    return wine_dbg_sprintf("ctx(%p)", ctx->data); 
338 339
}

340
static const char* dwarf2_debug_ctx(const dwarf2_parse_context_t* ctx)
Raphael Junqueira's avatar
Raphael Junqueira committed
341
{
342 343
    return wine_dbg_sprintf("ctx(%p,%s)",
                            ctx, debugstr_w(ctx->module->module.ModuleName));
Raphael Junqueira's avatar
Raphael Junqueira committed
344
}
345

346
static const char* dwarf2_debug_di(const dwarf2_debug_info_t* di)
Eric Pouech's avatar
Eric Pouech committed
347
{
348 349
    return wine_dbg_sprintf("debug_info(abbrev:%p,symt:%p)",
                            di->abbrev, di->symt);
Raphael Junqueira's avatar
Raphael Junqueira committed
350
}
351

352
static dwarf2_abbrev_entry_t*
353
dwarf2_abbrev_table_find_entry(const struct sparse_array* abbrev_table,
354
                               unsigned long entry_code)
355
{
356 357
    assert( NULL != abbrev_table );
    return sparse_array_find(abbrev_table, entry_code);
358 359
}

360
static void dwarf2_parse_abbrev_set(dwarf2_traverse_context_t* abbrev_ctx, 
361 362
                                    struct sparse_array* abbrev_table,
                                    struct pool* pool)
363
{
364 365 366 367 368 369
    unsigned long entry_code;
    dwarf2_abbrev_entry_t* abbrev_entry;
    dwarf2_abbrev_entry_attr_t* new = NULL;
    dwarf2_abbrev_entry_attr_t* last = NULL;
    unsigned long attribute;
    unsigned long form;
370

371
    assert( NULL != abbrev_ctx );
372

373 374 375
    TRACE("%s, end at %p\n",
          dwarf2_debug_traverse_ctx(abbrev_ctx), abbrev_ctx->end_data); 

376 377 378
    sparse_array_init(abbrev_table, sizeof(dwarf2_abbrev_entry_t), 32);
    while (abbrev_ctx->data < abbrev_ctx->end_data)
    {
379
        TRACE("now at %s\n", dwarf2_debug_traverse_ctx(abbrev_ctx)); 
380 381 382 383
        entry_code = dwarf2_leb128_as_unsigned(abbrev_ctx);
        TRACE("found entry_code %lu\n", entry_code);
        if (!entry_code)
        {
384
            TRACE("NULL entry code at %s\n", dwarf2_debug_traverse_ctx(abbrev_ctx)); 
385 386 387 388
            break;
        }
        abbrev_entry = sparse_array_add(abbrev_table, entry_code, pool);
        assert( NULL != abbrev_entry );
389

390 391 392 393 394
        abbrev_entry->entry_code = entry_code;
        abbrev_entry->tag        = dwarf2_leb128_as_unsigned(abbrev_ctx);
        abbrev_entry->have_child = dwarf2_parse_byte(abbrev_ctx);
        abbrev_entry->attrs      = NULL;
        abbrev_entry->num_attr   = 0;
395

396 397 398
        TRACE("table:(%p,#%u) entry_code(%lu) tag(0x%lx) have_child(%u) -> %p\n",
              abbrev_table, sparse_array_length(abbrev_table),
              entry_code, abbrev_entry->tag, abbrev_entry->have_child, abbrev_entry);
399

400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
        last = NULL;
        while (1)
        {
            attribute = dwarf2_leb128_as_unsigned(abbrev_ctx);
            form = dwarf2_leb128_as_unsigned(abbrev_ctx);
            if (!attribute) break;

            new = pool_alloc(pool, sizeof(dwarf2_abbrev_entry_attr_t));
            assert(new);

            new->attribute = attribute;
            new->form      = form;
            new->next      = NULL;
            if (abbrev_entry->attrs)    last->next = new;
            else                        abbrev_entry->attrs = new;
            last = new;
            abbrev_entry->num_attr++;
        }
418
    }
419
    TRACE("found %u entries\n", sparse_array_length(abbrev_table));
420 421
}

422 423
static void dwarf2_swallow_attribute(dwarf2_traverse_context_t* ctx,
                                     const dwarf2_abbrev_entry_attr_t* abbrev_attr)
424
{
425 426
    unsigned    step;

427 428
    TRACE("(attr:0x%lx,form:0x%lx)\n", abbrev_attr->attribute, abbrev_attr->form);

429 430
    switch (abbrev_attr->form)
    {
431
    case DW_FORM_ref_addr:
432
    case DW_FORM_addr:   step = ctx->word_size; break;
433 434
    case DW_FORM_flag:
    case DW_FORM_data1:
435
    case DW_FORM_ref1:   step = 1; break;
436
    case DW_FORM_data2:
437
    case DW_FORM_ref2:   step = 2; break;
438 439
    case DW_FORM_data4:
    case DW_FORM_ref4:
440 441 442
    case DW_FORM_strp:   step = 4; break;
    case DW_FORM_data8:
    case DW_FORM_ref8:   step = 8; break;
443 444
    case DW_FORM_sdata:
    case DW_FORM_ref_udata:
445 446 447 448 449 450
    case DW_FORM_udata:  step = dwarf2_leb128_length(ctx); break;
    case DW_FORM_string: step = strlen((const char*)ctx->data) + 1; break;
    case DW_FORM_block:  step = dwarf2_leb128_as_unsigned(ctx); break;
    case DW_FORM_block1: step = dwarf2_parse_byte(ctx); break;
    case DW_FORM_block2: step = dwarf2_parse_u2(ctx); break;
    case DW_FORM_block4: step = dwarf2_parse_u4(ctx); break;
451 452
    default:
        FIXME("Unhandled attribute form %lx\n", abbrev_attr->form);
453
        return;
454
    }
455
    ctx->data += step;
456 457
}

458 459 460 461
static void dwarf2_fill_attr(const dwarf2_parse_context_t* ctx,
                             const dwarf2_abbrev_entry_attr_t* abbrev_attr,
                             const unsigned char* data,
                             struct attribute* attr)
462
{
463 464
    attr->form = abbrev_attr->form;
    switch (attr->form)
465
    {
466 467 468 469 470
    case DW_FORM_ref_addr:
    case DW_FORM_addr:
        attr->u.uvalue = dwarf2_get_addr(data, ctx->word_size);
        TRACE("addr<0x%lx>\n", attr->u.uvalue);
        break;
471

472 473 474 475
    case DW_FORM_flag:
        attr->u.uvalue = dwarf2_get_byte(data);
        TRACE("flag<0x%lx>\n", attr->u.uvalue);
        break;
476

477 478 479 480
    case DW_FORM_data1:
        attr->u.uvalue = dwarf2_get_byte(data);
        TRACE("data1<%lu>\n", attr->u.uvalue);
        break;
481

482 483 484 485
    case DW_FORM_data2:
        attr->u.uvalue = dwarf2_get_u2(data);
        TRACE("data2<%lu>\n", attr->u.uvalue);
        break;
486

487 488 489 490
    case DW_FORM_data4:
        attr->u.uvalue = dwarf2_get_u4(data);
        TRACE("data4<%lu>\n", attr->u.uvalue);
        break;
491

492 493 494
    case DW_FORM_data8:
        FIXME("Unhandled 64bits support\n");
        break;
495

496 497 498 499
    case DW_FORM_ref1:
        attr->u.uvalue = ctx->ref_offset + dwarf2_get_byte(data);
        TRACE("ref1<0x%lx>\n", attr->u.uvalue);
        break;
500

501 502 503 504
    case DW_FORM_ref2:
        attr->u.uvalue = ctx->ref_offset + dwarf2_get_u2(data);
        TRACE("ref2<0x%lx>\n", attr->u.uvalue);
        break;
505

506 507 508 509
    case DW_FORM_ref4:
        attr->u.uvalue = ctx->ref_offset + dwarf2_get_u4(data);
        TRACE("ref4<0x%lx>\n", attr->u.uvalue);
        break;
510
    
511 512 513
    case DW_FORM_ref8:
        FIXME("Unhandled 64 bit support\n");
        break;
514

515 516 517
    case DW_FORM_sdata:
        attr->u.svalue = dwarf2_get_leb128_as_signed(data, NULL);
        break;
518

519 520 521
    case DW_FORM_ref_udata:
        attr->u.uvalue = dwarf2_get_leb128_as_unsigned(data, NULL);
        break;
522

523 524 525
    case DW_FORM_udata:
        attr->u.uvalue = dwarf2_get_leb128_as_unsigned(data, NULL);
        break;
526

527 528 529 530
    case DW_FORM_string:
        attr->u.string = (const char *)data;
        TRACE("string<%s>\n", attr->u.string);
        break;
531

532 533 534 535 536 537 538 539 540 541 542
    case DW_FORM_strp:
    {
        unsigned long offset = dwarf2_get_u4(data);
        attr->u.string = (const char*)ctx->sections[section_string].address + offset;
    }
    TRACE("strp<%s>\n", attr->u.string);
    break;
        
    case DW_FORM_block:
        attr->u.block.size = dwarf2_get_leb128_as_unsigned(data, &attr->u.block.ptr);
        break;
543

544 545 546 547
    case DW_FORM_block1:
        attr->u.block.size = dwarf2_get_byte(data);
        attr->u.block.ptr  = data + 1;
        break;
548

549 550 551 552
    case DW_FORM_block2:
        attr->u.block.size = dwarf2_get_u2(data);
        attr->u.block.ptr  = data + 2;
        break;
553

554 555 556 557
    case DW_FORM_block4:
        attr->u.block.size = dwarf2_get_u4(data);
        attr->u.block.ptr  = data + 4;
        break;
558

559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
    default:
        FIXME("Unhandled attribute form %lx\n", abbrev_attr->form);
        break;
    }
}

static BOOL dwarf2_find_attribute(const dwarf2_parse_context_t* ctx,
                                  const dwarf2_debug_info_t* di,
                                  unsigned at, struct attribute* attr)
{
    unsigned                    i, ai = 0;
    dwarf2_abbrev_entry_attr_t* abbrev_attr;
    dwarf2_abbrev_entry_attr_t* abstract_abbrev_attr;

    while (di)
    {
        abstract_abbrev_attr = NULL;
        for (i = 0, abbrev_attr = di->abbrev->attrs; abbrev_attr; i++, abbrev_attr = abbrev_attr->next)
        {
            if (abbrev_attr->attribute == at)
            {
                dwarf2_fill_attr(ctx, abbrev_attr, di->data[i], attr);
                return TRUE;
            }
            if (abbrev_attr->attribute == DW_AT_abstract_origin &&
                at != DW_AT_sibling)
            {
                abstract_abbrev_attr = abbrev_attr;
                ai = i;
588
            }
589
        }
590 591 592 593 594
        /* do we have an abstract origin debug entry to look into ? */
        if (!abstract_abbrev_attr) break;
        dwarf2_fill_attr(ctx, abstract_abbrev_attr, di->data[ai], attr);
        if (!(di = sparse_array_find(&ctx->debug_info_table, attr->u.uvalue)))
            FIXME("Should have found the debug info entry\n");
595 596 597 598
    }
    return FALSE;
}

Eric Pouech's avatar
Eric Pouech committed
599 600 601
static void dwarf2_load_one_entry(dwarf2_parse_context_t*, dwarf2_debug_info_t*,
                                  struct symt_compiland*);

602
#define Wine_DW_no_register     0x7FFFFFFF
603

604
static unsigned dwarf2_map_register(int regno)
605
{
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
    unsigned    reg;

    switch (regno)
    {
    case Wine_DW_no_register: FIXME("What the heck map reg 0x%x\n",regno); reg = 0; break;
    case  0: reg = CV_REG_EAX; break;
    case  1: reg = CV_REG_ECX; break;
    case  2: reg = CV_REG_EDX; break;
    case  3: reg = CV_REG_EBX; break;
    case  4: reg = CV_REG_ESP; break;
    case  5: reg = CV_REG_EBP; break;
    case  6: reg = CV_REG_ESI; break;
    case  7: reg = CV_REG_EDI; break;
    case  8: reg = CV_REG_EIP; break;
    case  9: reg = CV_REG_EFLAGS; break;
    case 10: reg = CV_REG_CS;  break;
    case 11: reg = CV_REG_SS;  break;
    case 12: reg = CV_REG_DS;  break;
    case 13: reg = CV_REG_ES;  break;
    case 14: reg = CV_REG_FS;  break;
    case 15: reg = CV_REG_GS;  break;
    case 16: case 17: case 18: case 19:
    case 20: case 21: case 22: case 23:
        reg = CV_REG_ST0 + regno - 16; break;
    case 24: reg = CV_REG_CTRL; break;
    case 25: reg = CV_REG_STAT; break;
    case 26: reg = CV_REG_TAG; break;
/*
reg: fiseg 27
reg: fioff 28
reg: foseg 29
reg: fooff 30
reg: fop   31
*/
    case 32: case 33: case 34: case 35:
    case 36: case 37: case 38: case 39:
        reg = CV_REG_XMM0 + regno - 32; break;
    case 40: reg = CV_REG_MXCSR; break;
    default:
        FIXME("Don't know how to map register %d\n", regno);
        return 0;
    }
    return reg;
}

651 652
static enum location_error
compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
653
                 HANDLE hproc, const struct location* frame)
654 655
{
    unsigned long stack[64];
656
    unsigned stk;
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
    unsigned char op;
    BOOL piece_found = FALSE;

    stack[stk = 0] = 0;

    loc->kind = loc_absolute;
    loc->reg = Wine_DW_no_register;

    while (ctx->data < ctx->end_data)
    {
        op = dwarf2_parse_byte(ctx);
        switch (op)
        {
        case DW_OP_addr:    stack[++stk] = dwarf2_parse_addr(ctx); break;
        case DW_OP_const1u: stack[++stk] = dwarf2_parse_byte(ctx); break;
        case DW_OP_const1s: stack[++stk] = (long)(signed char)dwarf2_parse_byte(ctx); break;
        case DW_OP_const2u: stack[++stk] = dwarf2_parse_u2(ctx); break;
        case DW_OP_const2s: stack[++stk] = (long)(short)dwarf2_parse_u2(ctx); break;
        case DW_OP_const4u: stack[++stk] = dwarf2_parse_u4(ctx); break;
        case DW_OP_const4s: stack[++stk] = dwarf2_parse_u4(ctx); break;
        case DW_OP_constu:  stack[++stk] = dwarf2_leb128_as_unsigned(ctx); break;
        case DW_OP_consts:  stack[++stk] = dwarf2_leb128_as_signed(ctx); break;
        case DW_OP_plus_uconst:
            stack[stk] += dwarf2_leb128_as_unsigned(ctx); break;
        case DW_OP_reg0:  case DW_OP_reg1:  case DW_OP_reg2:  case DW_OP_reg3:
        case DW_OP_reg4:  case DW_OP_reg5:  case DW_OP_reg6:  case DW_OP_reg7:
        case DW_OP_reg8:  case DW_OP_reg9:  case DW_OP_reg10: case DW_OP_reg11:
        case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: case DW_OP_reg15:
        case DW_OP_reg16: case DW_OP_reg17: case DW_OP_reg18: case DW_OP_reg19:
        case DW_OP_reg20: case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23:
        case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: case DW_OP_reg27:
        case DW_OP_reg28: case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31:
689 690 691 692 693 694 695 696 697 698 699 700 701
            /* dbghelp APIs don't know how to cope with this anyway
             * (for example 'long long' stored in two registers)
             * FIXME: We should tell winedbg how to deal with it (sigh)
             */
            if (!piece_found)
            {
                if (loc->reg != Wine_DW_no_register)
                    FIXME("Only supporting one reg (%d -> %d)\n",
                          loc->reg, dwarf2_map_register(op - DW_OP_reg0));
                loc->reg = dwarf2_map_register(op - DW_OP_reg0);
            }
            loc->kind = loc_register;
            break;
702 703 704 705 706 707 708 709 710 711 712 713
        case DW_OP_breg0:  case DW_OP_breg1:  case DW_OP_breg2:  case DW_OP_breg3:
        case DW_OP_breg4:  case DW_OP_breg5:  case DW_OP_breg6:  case DW_OP_breg7:
        case DW_OP_breg8:  case DW_OP_breg9:  case DW_OP_breg10: case DW_OP_breg11:
        case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15:
        case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19:
        case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23:
        case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27:
        case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31:
            /* dbghelp APIs don't know how to cope with this anyway
             * (for example 'long long' stored in two registers)
             * FIXME: We should tell winedbg how to deal with it (sigh)
             */
714
            if (!piece_found)
715 716
            {
                if (loc->reg != Wine_DW_no_register)
717 718 719
                    FIXME("Only supporting one reg (%d -> %d)\n",
                          loc->reg, dwarf2_map_register(op - DW_OP_breg0));
                loc->reg = dwarf2_map_register(op - DW_OP_breg0);
720
            }
721 722
            stack[++stk] = dwarf2_leb128_as_signed(ctx);
            loc->kind = loc_regrel;
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
            break;
        case DW_OP_fbreg:
            if (loc->reg != Wine_DW_no_register)
                FIXME("Only supporting one reg (%d -> -2)\n", loc->reg);
            if (frame && frame->kind == loc_register)
            {
                loc->kind = loc_regrel;
                loc->reg = frame->reg;
                stack[++stk] = dwarf2_leb128_as_signed(ctx);
            }
            else if (frame && frame->kind == loc_regrel)
            {
                loc->kind = loc_regrel;
                loc->reg = frame->reg;
                stack[++stk] = dwarf2_leb128_as_signed(ctx) + frame->offset;
            }
            else
            {
                /* FIXME: this could be later optimized by not recomputing
                 * this very location expression
                 */
                loc->kind = loc_dwarf2_block;
                stack[++stk] = dwarf2_leb128_as_signed(ctx);
            }
            break;
        case DW_OP_piece:
            {
                unsigned sz = dwarf2_leb128_as_unsigned(ctx);
751
                WARN("Not handling OP_piece (size=%d)\n", sz);
752 753 754
                piece_found = TRUE;
            }
            break;
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
        case DW_OP_deref:
            if (!stk)
            {
                FIXME("Unexpected empty stack\n");
                return loc_err_internal;
            }
            if (loc->reg != Wine_DW_no_register)
            {
                WARN("Too complex expression for deref\n");
                return loc_err_too_complex;
            }
            if (hproc)
            {
                DWORD   addr = stack[stk--];
                DWORD   deref;

                if (!ReadProcessMemory(hproc, (void*)addr, &deref, sizeof(deref), NULL))
                {
773
                    WARN("Couldn't read memory at %x\n", addr);
774 775 776 777 778 779 780 781 782
                    return loc_err_cant_read;
                }
                stack[++stk] = deref;
            }
            else
            {
               loc->kind = loc_dwarf2_block;
            }
            break;
783 784
        default:
            FIXME("Unhandled attr op: %x\n", op);
785
            return loc_err_internal;
786 787 788
        }
    }
    loc->offset = stack[stk];
789
    return 0;
790 791 792
}

static BOOL dwarf2_compute_location_attr(dwarf2_parse_context_t* ctx,
793
                                         const dwarf2_debug_info_t* di,
794 795 796 797
                                         unsigned long dw,
                                         struct location* loc,
                                         const struct location* frame)
{
798 799 800
    struct attribute xloc;

    if (!dwarf2_find_attribute(ctx, di, dw, &xloc)) return FALSE;
801

802 803 804 805
    switch (xloc.form)
    {
    case DW_FORM_data1: case DW_FORM_data2:
    case DW_FORM_udata: case DW_FORM_sdata:
806 807 808 809 810 811 812 813
        loc->kind = loc_absolute;
        loc->reg = 0;
        loc->offset = xloc.u.uvalue;
        return TRUE;
    case DW_FORM_data4: case DW_FORM_data8:
        loc->kind = loc_dwarf2_location_list;
        loc->reg = Wine_DW_no_register;
        loc->offset = xloc.u.uvalue;
814 815
        return TRUE;
    }
816

817
    /* assume we have a block form */
818

819
    if (xloc.u.block.size)
820
    {
821 822
        dwarf2_traverse_context_t       lctx;
        enum location_error             err;
823

824 825
        lctx.data = xloc.u.block.ptr;
        lctx.end_data = xloc.u.block.ptr + xloc.u.block.size;
826 827
        lctx.word_size = ctx->word_size;

828
        err = compute_location(&lctx, loc, NULL, frame);
829
        if (err < 0)
830 831
        {
            loc->kind = loc_error;
832
            loc->reg = err;
833 834 835 836 837 838 839 840 841
        }
        else if (loc->kind == loc_dwarf2_block)
        {
            unsigned*   ptr = pool_alloc(&ctx->module->pool,
                                         sizeof(unsigned) + xloc.u.block.size);
            *ptr = xloc.u.block.size;
            memcpy(ptr + 1, xloc.u.block.ptr, xloc.u.block.size);
            loc->offset = (unsigned long)ptr;
        }
842
    }
843
    return TRUE;
844 845
}

Eric Pouech's avatar
Eric Pouech committed
846 847
static struct symt* dwarf2_lookup_type(dwarf2_parse_context_t* ctx,
                                       const dwarf2_debug_info_t* di)
848
{
849
    struct attribute    attr;
Eric Pouech's avatar
Eric Pouech committed
850

851
    if (dwarf2_find_attribute(ctx, di, DW_AT_type, &attr))
Eric Pouech's avatar
Eric Pouech committed
852 853 854
    {
        dwarf2_debug_info_t*    type;
        
855 856
        type = sparse_array_find(&ctx->debug_info_table, attr.u.uvalue);
        if (!type) FIXME("Unable to find back reference to type %lx\n", attr.u.uvalue);
Eric Pouech's avatar
Eric Pouech committed
857 858 859 860 861 862 863 864
        if (!type->symt)
        {
            /* load the debug info entity */
            dwarf2_load_one_entry(ctx, type, NULL);
        }
        return type->symt;
    }
    return NULL;
865 866
}

867 868 869 870 871 872
/******************************************************************
 *		dwarf2_read_one_debug_info
 *
 * Loads into memory one debug info entry, and recursively its children (if any)
 */
static BOOL dwarf2_read_one_debug_info(dwarf2_parse_context_t* ctx,
873
                                       dwarf2_traverse_context_t* traverse,
874 875 876 877 878 879 880 881 882 883
                                       dwarf2_debug_info_t** pdi)
{
    const dwarf2_abbrev_entry_t*abbrev;
    unsigned long               entry_code;
    unsigned long               offset;
    dwarf2_debug_info_t*        di;
    dwarf2_debug_info_t*        child;
    dwarf2_debug_info_t**       where;
    dwarf2_abbrev_entry_attr_t* attr;
    unsigned                    i;
884
    struct attribute            sibling;
885

886
    offset = traverse->data - ctx->sections[ctx->section].address;
887
    entry_code = dwarf2_leb128_as_unsigned(traverse);
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
    TRACE("found entry_code %lu at 0x%lx\n", entry_code, offset);
    if (!entry_code)
    {
        *pdi = NULL;
        return TRUE;
    }
    abbrev = dwarf2_abbrev_table_find_entry(&ctx->abbrev_table, entry_code);
    if (!abbrev)
    {
	WARN("Cannot find abbrev entry for %lu at 0x%lx\n", entry_code, offset);
	return FALSE;
    }
    di = sparse_array_add(&ctx->debug_info_table, offset, &ctx->pool);
    if (!di) return FALSE;
    di->abbrev = abbrev;
    di->symt   = NULL;

    if (abbrev->num_attr)
    {
907
        di->data = pool_alloc(&ctx->pool, abbrev->num_attr * sizeof(const char*));
908 909
        for (i = 0, attr = abbrev->attrs; attr; i++, attr = attr->next)
        {
910 911
            di->data[i] = traverse->data;
            dwarf2_swallow_attribute(traverse, attr);
912 913
        }
    }
914
    else di->data = NULL;
915 916 917
    if (abbrev->have_child)
    {
        vector_init(&di->children, sizeof(dwarf2_debug_info_t*), 16);
918
        while (traverse->data < traverse->end_data)
919
        {
920
            if (!dwarf2_read_one_debug_info(ctx, traverse, &child)) return FALSE;
921 922 923 924 925 926
            if (!child) break;
            where = vector_add(&di->children, &ctx->pool);
            if (!where) return FALSE;
            *where = child;
        }
    }
927 928
    if (dwarf2_find_attribute(ctx, di, DW_AT_sibling, &sibling) &&
        traverse->data != ctx->sections[ctx->section].address + sibling.u.uvalue)
Eric Pouech's avatar
Eric Pouech committed
929 930
    {
        WARN("setting cursor for %s to next sibling <0x%lx>\n",
931
             dwarf2_debug_traverse_ctx(traverse), sibling.u.uvalue);
932
        traverse->data = ctx->sections[ctx->section].address + sibling.u.uvalue;
Eric Pouech's avatar
Eric Pouech committed
933
    }
934 935 936 937
    *pdi = di;
    return TRUE;
}

Eric Pouech's avatar
Eric Pouech committed
938 939
static struct symt* dwarf2_parse_base_type(dwarf2_parse_context_t* ctx,
                                           dwarf2_debug_info_t* di)
940
{
941 942 943
    struct attribute name;
    struct attribute size;
    struct attribute encoding;
Eric Pouech's avatar
Eric Pouech committed
944
    enum BasicType bt;
945
    int cache_idx = -1;
Eric Pouech's avatar
Eric Pouech committed
946
    if (di->symt) return di->symt;
947

Eric Pouech's avatar
Eric Pouech committed
948
    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); 
949

950 951
    if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name))
        name.u.string = NULL;
952 953
    if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &size)) size.u.uvalue = 0;
    if (!dwarf2_find_attribute(ctx, di, DW_AT_encoding, &encoding)) encoding.u.uvalue = DW_ATE_void;
Eric Pouech's avatar
Eric Pouech committed
954

955
    switch (encoding.u.uvalue)
Eric Pouech's avatar
Eric Pouech committed
956 957 958 959 960 961 962 963 964 965 966 967
    {
    case DW_ATE_void:           bt = btVoid; break;
    case DW_ATE_address:        bt = btULong; break;
    case DW_ATE_boolean:        bt = btBool; break;
    case DW_ATE_complex_float:  bt = btComplex; break;
    case DW_ATE_float:          bt = btFloat; break;
    case DW_ATE_signed:         bt = btInt; break;
    case DW_ATE_unsigned:       bt = btUInt; break;
    case DW_ATE_signed_char:    bt = btChar; break;
    case DW_ATE_unsigned_char:  bt = btChar; break;
    default:                    bt = btNoType; break;
    }
968
    di->symt = &symt_new_basic(ctx->module, bt, name.u.string, size.u.uvalue)->symt;
969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984
    switch (bt)
    {
    case btVoid:
        assert(size.u.uvalue == 0);
        cache_idx = sc_void;
        break;
    case btInt:
        switch (size.u.uvalue)
        {
        case 1: cache_idx = sc_int1; break;
        case 2: cache_idx = sc_int2; break;
        case 4: cache_idx = sc_int4; break;
        }
        break;
    default: break;
    }
985
    if (cache_idx != -1 && !ctx->symt_cache[cache_idx])
986 987
        ctx->symt_cache[cache_idx] = di->symt;

Eric Pouech's avatar
Eric Pouech committed
988 989
    if (di->abbrev->have_child) FIXME("Unsupported children\n");
    return di->symt;
990 991
}

Eric Pouech's avatar
Eric Pouech committed
992 993
static struct symt* dwarf2_parse_typedef(dwarf2_parse_context_t* ctx,
                                         dwarf2_debug_info_t* di)
994
{
995 996
    struct symt*        ref_type;
    struct attribute    name;
997

Eric Pouech's avatar
Eric Pouech committed
998 999 1000 1001
    if (di->symt) return di->symt;

    TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), di->abbrev->entry_code); 

1002
    if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) name.u.string = NULL;
Eric Pouech's avatar
Eric Pouech committed
1003 1004
    ref_type = dwarf2_lookup_type(ctx, di);

1005 1006
    if (name.u.string)
        di->symt = &symt_new_typedef(ctx->module, ref_type, name.u.string)->symt;
Eric Pouech's avatar
Eric Pouech committed
1007 1008
    if (di->abbrev->have_child) FIXME("Unsupported children\n");
    return di->symt;
1009 1010
}

Eric Pouech's avatar
Eric Pouech committed
1011 1012
static struct symt* dwarf2_parse_pointer_type(dwarf2_parse_context_t* ctx,
                                              dwarf2_debug_info_t* di)
1013
{
1014 1015
    struct symt*        ref_type;
    struct attribute    size;
Raphael Junqueira's avatar
Raphael Junqueira committed
1016

Eric Pouech's avatar
Eric Pouech committed
1017
    if (di->symt) return di->symt;
1018

Eric Pouech's avatar
Eric Pouech committed
1019
    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); 
1020

1021
    if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &size)) size.u.uvalue = 0;
1022
    if (!(ref_type = dwarf2_lookup_type(ctx, di)))
1023 1024 1025 1026
    {
        ref_type = ctx->symt_cache[sc_void];
        assert(ref_type);
    }
Eric Pouech's avatar
Eric Pouech committed
1027 1028 1029 1030 1031 1032 1033
    di->symt = &symt_new_pointer(ctx->module, ref_type)->symt;
    if (di->abbrev->have_child) FIXME("Unsupported children\n");
    return di->symt;
}

static struct symt* dwarf2_parse_array_type(dwarf2_parse_context_t* ctx,
                                            dwarf2_debug_info_t* di)
1034
{
Eric Pouech's avatar
Eric Pouech committed
1035 1036
    struct symt* ref_type;
    struct symt* idx_type = NULL;
1037
    struct attribute min, max, cnt;
Eric Pouech's avatar
Eric Pouech committed
1038
    dwarf2_debug_info_t* child;
1039
    unsigned int    i;
Raphael Junqueira's avatar
Raphael Junqueira committed
1040

Eric Pouech's avatar
Eric Pouech committed
1041 1042 1043
    if (di->symt) return di->symt;

    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
Raphael Junqueira's avatar
Raphael Junqueira committed
1044

Eric Pouech's avatar
Eric Pouech committed
1045 1046 1047 1048 1049 1050
    if (!di->abbrev->have_child)
    {
        FIXME("array without range information\n");
        return NULL;
    }
    ref_type = dwarf2_lookup_type(ctx, di);
Raphael Junqueira's avatar
Raphael Junqueira committed
1051

1052
    for (i=0; i<vector_length(&di->children); i++)
Eric Pouech's avatar
Eric Pouech committed
1053
    {
1054
        child = *(dwarf2_debug_info_t**)vector_at(&di->children, i);
Eric Pouech's avatar
Eric Pouech committed
1055 1056 1057 1058
        switch (child->abbrev->tag)
        {
        case DW_TAG_subrange_type:
            idx_type = dwarf2_lookup_type(ctx, child);
1059
            if (!dwarf2_find_attribute(ctx, child, DW_AT_lower_bound, &min))
1060
                min.u.uvalue = 0;
1061
            if (!dwarf2_find_attribute(ctx, child, DW_AT_upper_bound, &max))
1062
                max.u.uvalue = 0;
1063
            if (dwarf2_find_attribute(ctx, child, DW_AT_count, &cnt))
1064
                max.u.uvalue = min.u.uvalue + cnt.u.uvalue;
Eric Pouech's avatar
Eric Pouech committed
1065 1066 1067 1068 1069 1070 1071
            break;
        default:
            FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
                  child->abbrev->tag, dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
            break;
        }
    }
1072
    di->symt = &symt_new_array(ctx->module, min.u.uvalue, max.u.uvalue, ref_type, idx_type)->symt;
Eric Pouech's avatar
Eric Pouech committed
1073
    return di->symt;
1074 1075
}

Eric Pouech's avatar
Eric Pouech committed
1076 1077
static struct symt* dwarf2_parse_const_type(dwarf2_parse_context_t* ctx,
                                            dwarf2_debug_info_t* di)
1078
{
Eric Pouech's avatar
Eric Pouech committed
1079
    struct symt* ref_type;
Raphael Junqueira's avatar
Raphael Junqueira committed
1080

Eric Pouech's avatar
Eric Pouech committed
1081 1082 1083
    if (di->symt) return di->symt;

    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); 
1084

Eric Pouech's avatar
Eric Pouech committed
1085 1086 1087
    ref_type = dwarf2_lookup_type(ctx, di);
    if (di->abbrev->have_child) FIXME("Unsupported children\n");
    di->symt = ref_type;
Raphael Junqueira's avatar
Raphael Junqueira committed
1088

Eric Pouech's avatar
Eric Pouech committed
1089
    return ref_type;
1090 1091
}

1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
static struct symt* dwarf2_parse_volatile_type(dwarf2_parse_context_t* ctx,
                                               dwarf2_debug_info_t* di)
{
    struct symt* ref_type;

    if (di->symt) return di->symt;

    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); 

    ref_type = dwarf2_lookup_type(ctx, di);
    if (di->abbrev->have_child) FIXME("Unsupported children\n");
    di->symt = ref_type;

    return ref_type;
}

Eric Pouech's avatar
Eric Pouech committed
1108 1109
static struct symt* dwarf2_parse_reference_type(dwarf2_parse_context_t* ctx,
                                                dwarf2_debug_info_t* di)
1110
{
Eric Pouech's avatar
Eric Pouech committed
1111
    struct symt* ref_type = NULL;
Raphael Junqueira's avatar
Raphael Junqueira committed
1112

Eric Pouech's avatar
Eric Pouech committed
1113 1114 1115
    if (di->symt) return di->symt;

    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
1116

Eric Pouech's avatar
Eric Pouech committed
1117 1118 1119
    ref_type = dwarf2_lookup_type(ctx, di);
    /* FIXME: for now, we hard-wire C++ references to pointers */
    di->symt = &symt_new_pointer(ctx->module, ref_type)->symt;
Raphael Junqueira's avatar
Raphael Junqueira committed
1120

Eric Pouech's avatar
Eric Pouech committed
1121 1122 1123
    if (di->abbrev->have_child) FIXME("Unsupported children\n");

    return di->symt;
Raphael Junqueira's avatar
Raphael Junqueira committed
1124 1125
}

Eric Pouech's avatar
Eric Pouech committed
1126
static void dwarf2_parse_udt_member(dwarf2_parse_context_t* ctx,
1127
                                    const dwarf2_debug_info_t* di,
Eric Pouech's avatar
Eric Pouech committed
1128
                                    struct symt_udt* parent)
Raphael Junqueira's avatar
Raphael Junqueira committed
1129
{
Eric Pouech's avatar
Eric Pouech committed
1130
    struct symt* elt_type;
1131 1132 1133
    struct attribute name;
    struct attribute bit_size;
    struct attribute bit_offset;
1134
    struct location  loc;
Eric Pouech's avatar
Eric Pouech committed
1135 1136 1137 1138 1139

    assert(parent);

    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));

1140
    if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) name.u.string = NULL;
Eric Pouech's avatar
Eric Pouech committed
1141
    elt_type = dwarf2_lookup_type(ctx, di);
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
    if (dwarf2_compute_location_attr(ctx, di, DW_AT_data_member_location, &loc, NULL))
    {
        if (loc.kind != loc_absolute)
        {
           FIXME("Found register, while not expecting it\n");
           loc.offset = 0;
        }
        else
            TRACE("found member_location at %s -> %lu\n",
                  dwarf2_debug_ctx(ctx), loc.offset);
    }
    else
        loc.offset = 0;
1155 1156
    if (!dwarf2_find_attribute(ctx, di, DW_AT_bit_size, &bit_size))
        bit_size.u.uvalue = 0;
1157
    if (dwarf2_find_attribute(ctx, di, DW_AT_bit_offset, &bit_offset))
1158 1159 1160 1161
    {
        /* FIXME: we should only do this when implementation is LSB (which is
         * the case on i386 processors)
         */
1162
        struct attribute nbytes;
1163
        if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &nbytes))
1164 1165
        {
            DWORD64     size;
1166
            nbytes.u.uvalue = symt_get_info(elt_type, TI_GET_LENGTH, &size) ? (unsigned long)size : 0;
1167
        }
1168
        bit_offset.u.uvalue = nbytes.u.uvalue * 8 - bit_offset.u.uvalue - bit_size.u.uvalue;
1169
    }
1170 1171
    else bit_offset.u.uvalue = 0;
    symt_add_udt_element(ctx->module, parent, name.u.string, elt_type,    
1172 1173
                         (loc.offset << 3) + bit_offset.u.uvalue,
                         bit_size.u.uvalue);
1174

Eric Pouech's avatar
Eric Pouech committed
1175
    if (di->abbrev->have_child) FIXME("Unsupported children\n");
1176 1177
}

Eric Pouech's avatar
Eric Pouech committed
1178 1179 1180
static struct symt* dwarf2_parse_udt_type(dwarf2_parse_context_t* ctx,
                                          dwarf2_debug_info_t* di,
                                          enum UdtKind udt)
Raphael Junqueira's avatar
Raphael Junqueira committed
1181
{
1182 1183
    struct attribute    name;
    struct attribute    size;
Eric Pouech's avatar
Eric Pouech committed
1184 1185 1186 1187 1188

    if (di->symt) return di->symt;

    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); 

1189
    if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) name.u.string = NULL;
1190
    if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &size)) size.u.uvalue = 0;
Eric Pouech's avatar
Eric Pouech committed
1191

1192
    di->symt = &symt_new_udt(ctx->module, name.u.string, size.u.uvalue, udt)->symt;
Eric Pouech's avatar
Eric Pouech committed
1193 1194 1195 1196

    if (di->abbrev->have_child) /** any interest to not have child ? */
    {
        dwarf2_debug_info_t*    child;
1197
        unsigned int    i;
Eric Pouech's avatar
Eric Pouech committed
1198

1199
        for (i=0; i<vector_length(&di->children); i++)
Eric Pouech's avatar
Eric Pouech committed
1200
        {
1201
            child = *(dwarf2_debug_info_t**)vector_at(&di->children, i);
Eric Pouech's avatar
Eric Pouech committed
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211

            switch (child->abbrev->tag)
            {
            case DW_TAG_member:
                /* FIXME: should I follow the sibling stuff ?? */
                dwarf2_parse_udt_member(ctx, child, (struct symt_udt*)di->symt);
                break;
            case DW_TAG_enumeration_type:
                dwarf2_parse_enumeration_type(ctx, child);
                break;
1212 1213 1214
            case DW_TAG_structure_type:
            case DW_TAG_class_type:
            case DW_TAG_union_type:
1215
            case DW_TAG_typedef:
1216 1217
                /* FIXME: we need to handle nested udt definitions */
                break;
Eric Pouech's avatar
Eric Pouech committed
1218 1219 1220 1221 1222 1223
            default:
                FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
                      child->abbrev->tag, dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
                break;
            }
        }
Raphael Junqueira's avatar
Raphael Junqueira committed
1224
    }
Eric Pouech's avatar
Eric Pouech committed
1225 1226

    return di->symt;
Raphael Junqueira's avatar
Raphael Junqueira committed
1227 1228
}

Eric Pouech's avatar
Eric Pouech committed
1229
static void dwarf2_parse_enumerator(dwarf2_parse_context_t* ctx,
1230
                                    const dwarf2_debug_info_t* di,
Eric Pouech's avatar
Eric Pouech committed
1231
                                    struct symt_enum* parent)
Raphael Junqueira's avatar
Raphael Junqueira committed
1232
{
1233 1234
    struct attribute    name;
    struct attribute    value;
Raphael Junqueira's avatar
Raphael Junqueira committed
1235

Eric Pouech's avatar
Eric Pouech committed
1236
    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); 
Raphael Junqueira's avatar
Raphael Junqueira committed
1237

1238
    if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) return;
1239
    if (!dwarf2_find_attribute(ctx, di, DW_AT_const_value, &value)) value.u.svalue = 0;
1240
    symt_add_enum_element(ctx->module, parent, name.u.string, value.u.svalue);
Eric Pouech's avatar
Eric Pouech committed
1241 1242

    if (di->abbrev->have_child) FIXME("Unsupported children\n");
Raphael Junqueira's avatar
Raphael Junqueira committed
1243 1244
}

Eric Pouech's avatar
Eric Pouech committed
1245 1246
static struct symt* dwarf2_parse_enumeration_type(dwarf2_parse_context_t* ctx,
                                                  dwarf2_debug_info_t* di)
Raphael Junqueira's avatar
Raphael Junqueira committed
1247
{
1248 1249
    struct attribute    name;
    struct attribute    size;
1250
    struct symt_basic*  basetype;
1251

Eric Pouech's avatar
Eric Pouech committed
1252
    if (di->symt) return di->symt;
Raphael Junqueira's avatar
Raphael Junqueira committed
1253

Eric Pouech's avatar
Eric Pouech committed
1254
    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); 
Raphael Junqueira's avatar
Raphael Junqueira committed
1255

1256
    if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) name.u.string = NULL;
1257 1258 1259 1260 1261 1262 1263 1264 1265
    if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &size)) size.u.uvalue = 4;

    switch (size.u.uvalue) /* FIXME: that's wrong */
    {
    case 1: basetype = symt_new_basic(ctx->module, btInt, "char", 1); break;
    case 2: basetype = symt_new_basic(ctx->module, btInt, "short", 2); break;
    default:
    case 4: basetype = symt_new_basic(ctx->module, btInt, "int", 4); break;
    }
Eric Pouech's avatar
Eric Pouech committed
1266

1267
    di->symt = &symt_new_enum(ctx->module, name.u.string, &basetype->symt)->symt;
Eric Pouech's avatar
Eric Pouech committed
1268 1269 1270 1271

    if (di->abbrev->have_child) /* any interest to not have child ? */
    {
        dwarf2_debug_info_t*    child;
1272
        unsigned int    i;
Raphael Junqueira's avatar
Raphael Junqueira committed
1273

Eric Pouech's avatar
Eric Pouech committed
1274
        /* FIXME: should we use the sibling stuff ?? */
1275
        for (i=0; i<vector_length(&di->children); i++)
Eric Pouech's avatar
Eric Pouech committed
1276
        {
1277
            child = *(dwarf2_debug_info_t**)vector_at(&di->children, i);
Eric Pouech's avatar
Eric Pouech committed
1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290

            switch (child->abbrev->tag)
            {
            case DW_TAG_enumerator:
                dwarf2_parse_enumerator(ctx, child, (struct symt_enum*)di->symt);
                break;
            default:
                FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
                      di->abbrev->tag, dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
            }
	}
    }
    return di->symt;
Raphael Junqueira's avatar
Raphael Junqueira committed
1291 1292
}

1293 1294 1295 1296 1297 1298
/* structure used to pass information around when parsing a subprogram */
typedef struct dwarf2_subprogram_s
{
    dwarf2_parse_context_t*     ctx;
    struct symt_compiland*      compiland;
    struct symt_function*       func;
1299
    BOOL                        non_computed_variable;
1300
    struct location             frame;
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310
} dwarf2_subprogram_t;

/******************************************************************
 *		dwarf2_parse_variable
 *
 * Parses any variable (parameter, local/global variable)
 */
static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm,
                                  struct symt_block* block,
                                  dwarf2_debug_info_t* di)
Raphael Junqueira's avatar
Raphael Junqueira committed
1311
{
1312 1313 1314 1315
    struct symt*        param_type;
    struct attribute    name, value;
    struct location     loc;
    BOOL                is_pmt;
1316

1317
    TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
1318

1319
    is_pmt = !block && di->abbrev->tag == DW_TAG_formal_parameter;
1320
    param_type = dwarf2_lookup_type(subpgm->ctx, di);
1321
        
1322 1323 1324 1325
    if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_name, &name)) {
	/* cannot do much without the name, the functions below won't like it. */
        return;
    }
1326 1327
    if (dwarf2_compute_location_attr(subpgm->ctx, di, DW_AT_location,
                                     &loc, &subpgm->frame))
1328
    {
1329
        struct attribute ext;
1330

1331 1332
	TRACE("found parameter %s (kind=%d, offset=%ld, reg=%d) at %s\n",
              name.u.string, loc.kind, loc.offset, loc.reg,
1333
              dwarf2_debug_ctx(subpgm->ctx));
1334

1335
        switch (loc.kind)
1336
        {
1337
        case loc_absolute:
1338
            /* it's a global variable */
1339
            /* FIXME: we don't handle its scope yet */
1340
            if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_external, &ext))
1341
                ext.u.uvalue = 0;
1342
            symt_new_global_variable(subpgm->ctx->module, subpgm->compiland,
1343
                                     name.u.string, !ext.u.uvalue,
1344
                                     subpgm->ctx->load_offset + loc.offset,
1345 1346
                                     0, param_type);
            break;
1347
        default:
1348
            subpgm->non_computed_variable = TRUE;
1349
            /* fall through */
1350 1351
        case loc_register:
        case loc_regrel:
1352 1353 1354
            /* either a pmt/variable relative to frame pointer or
             * pmt/variable in a register
             */
1355
            assert(subpgm->func);
1356 1357
            symt_add_func_local(subpgm->ctx->module, subpgm->func, 
                                is_pmt ? DataIsParam : DataIsLocal,
1358
                                &loc, block, param_type, name.u.string);
1359 1360
            break;
        }
1361
    }
1362
    else if (dwarf2_find_attribute(subpgm->ctx, di, DW_AT_const_value, &value))
1363
    {
1364
        VARIANT v;
1365
        if (subpgm->func) WARN("Unsupported constant %s in function\n", name.u.string);
1366 1367 1368 1369 1370 1371 1372
        if (is_pmt)       FIXME("Unsupported constant (parameter) %s in function\n", name.u.string);
        switch (value.form)
        {
        case DW_FORM_data1:
        case DW_FORM_data2:
        case DW_FORM_data4:
        case DW_FORM_udata:
1373
        case DW_FORM_addr:
1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404
            v.n1.n2.vt = VT_UI4;
            v.n1.n2.n3.lVal = value.u.uvalue;
            break;

        case DW_FORM_sdata:
            v.n1.n2.vt = VT_I4;
            v.n1.n2.n3.lVal = value.u.svalue;
            break;

        case DW_FORM_strp:
        case DW_FORM_string:
            /* FIXME: native doesn't report const strings from here !!
             * however, the value of the string is in the code somewhere
             */
            v.n1.n2.vt = VT_I1 | VT_BYREF;
            v.n1.n2.n3.byref = pool_strdup(&subpgm->ctx->module->pool, value.u.string);
            break;

        case DW_FORM_data8:
        case DW_FORM_block:
        case DW_FORM_block1:
        case DW_FORM_block2:
        case DW_FORM_block4:

        default:
            FIXME("Unsupported form for const value %s (%lx)\n",
                  name.u.string, value.form);
            v.n1.n2.vt = VT_EMPTY;
        }
        di->symt = &symt_new_constant(subpgm->ctx->module, subpgm->compiland,
                                      name.u.string, param_type, &v)->symt;
1405
    }
1406 1407 1408
    if (is_pmt && subpgm->func && subpgm->func->type)
        symt_add_function_signature_parameter(subpgm->ctx->module,
                                              (struct symt_function_signature*)subpgm->func->type,
1409 1410
                                              param_type);

Eric Pouech's avatar
Eric Pouech committed
1411
    if (di->abbrev->have_child) FIXME("Unsupported children\n");
1412 1413
}

1414
static void dwarf2_parse_subprogram_label(dwarf2_subprogram_t* subpgm,
1415
                                          const dwarf2_debug_info_t* di)
1416
{
1417 1418
    struct attribute    name;
    struct attribute    low_pc;
1419
    struct location     loc;
1420

1421
    TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
1422

1423
    if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0;
1424 1425
    if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_name, &name))
        name.u.string = NULL;
1426

1427
    loc.kind = loc_absolute;
1428
    loc.offset = subpgm->ctx->load_offset + low_pc.u.uvalue;
1429
    symt_add_function_point(subpgm->ctx->module, subpgm->func, SymTagLabel,
1430
                            &loc, name.u.string);
1431 1432
}

1433
static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
1434
                                          struct symt_block* parent_block,
1435
					  const dwarf2_debug_info_t* di);
1436

1437
static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm,
1438
                                            struct symt_block* parent_block,
1439
                                            const dwarf2_debug_info_t* di)
1440
{
1441 1442 1443 1444
    struct symt_block*  block;
    struct attribute    low_pc;
    struct attribute    high_pc;

1445
    TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
1446

1447 1448 1449 1450
    if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0;
    if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_high_pc, &high_pc)) high_pc.u.uvalue = 0;

    block = symt_open_func_block(subpgm->ctx->module, subpgm->func, parent_block,
1451
                                 subpgm->ctx->load_offset + low_pc.u.uvalue - subpgm->func->address,
1452
                                 high_pc.u.uvalue - low_pc.u.uvalue);
1453

Eric Pouech's avatar
Eric Pouech committed
1454 1455 1456
    if (di->abbrev->have_child) /** any interest to not have child ? */
    {
        dwarf2_debug_info_t*    child;
1457
        unsigned int    i;
Raphael Junqueira's avatar
Raphael Junqueira committed
1458

1459
        for (i=0; i<vector_length(&di->children); i++)
Eric Pouech's avatar
Eric Pouech committed
1460
        {
1461
            child = *(dwarf2_debug_info_t**)vector_at(&di->children, i);
Eric Pouech's avatar
Eric Pouech committed
1462 1463 1464 1465 1466

            switch (child->abbrev->tag)
            {
            case DW_TAG_formal_parameter:
            case DW_TAG_variable:
1467
                dwarf2_parse_variable(subpgm, block, child);
Eric Pouech's avatar
Eric Pouech committed
1468
                break;
1469
            case DW_TAG_lexical_block:
1470
                dwarf2_parse_subprogram_block(subpgm, block, child);
1471 1472
                break;
            case DW_TAG_inlined_subroutine:
1473
                dwarf2_parse_inlined_subroutine(subpgm, block, child);
1474
                break;
1475
            case DW_TAG_label:
1476
                dwarf2_parse_subprogram_label(subpgm, child);
1477
                break;
Eric Pouech's avatar
Eric Pouech committed
1478 1479
            default:
                FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
1480 1481
                      child->abbrev->tag, dwarf2_debug_ctx(subpgm->ctx),
                      dwarf2_debug_di(di));
Eric Pouech's avatar
Eric Pouech committed
1482 1483 1484
            }
        }
    }
1485
    symt_close_func_block(subpgm->ctx->module, subpgm->func, block, 0);
Eric Pouech's avatar
Eric Pouech committed
1486
}
1487

1488 1489
static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm, 
                                          struct symt_block* parent_block,
1490
					  const dwarf2_debug_info_t* di)
Raphael Junqueira's avatar
Raphael Junqueira committed
1491
{
1492
    struct symt_block*  block;
1493 1494
    struct attribute    low_pc;
    struct attribute    high_pc;
1495

1496 1497
    TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));

1498 1499 1500 1501
    if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_low_pc, &low_pc))
        low_pc.u.uvalue = 0;
    if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_high_pc, &high_pc))
        high_pc.u.uvalue = 0;
1502 1503

    block = symt_open_func_block(subpgm->ctx->module, subpgm->func, parent_block,
1504
                                 subpgm->ctx->load_offset + low_pc.u.uvalue - subpgm->func->address,
1505
                                 high_pc.u.uvalue - low_pc.u.uvalue);
Raphael Junqueira's avatar
Raphael Junqueira committed
1506

Eric Pouech's avatar
Eric Pouech committed
1507 1508 1509
    if (di->abbrev->have_child) /** any interest to not have child ? */
    {
        dwarf2_debug_info_t*    child;
1510
        unsigned int    i;
Raphael Junqueira's avatar
Raphael Junqueira committed
1511

1512
        for (i=0; i<vector_length(&di->children); i++)
1513
        {
1514
            child = *(dwarf2_debug_info_t**)vector_at(&di->children, i);
Eric Pouech's avatar
Eric Pouech committed
1515 1516 1517 1518

            switch (child->abbrev->tag)
            {
            case DW_TAG_inlined_subroutine:
1519
                dwarf2_parse_inlined_subroutine(subpgm, block, child);
Eric Pouech's avatar
Eric Pouech committed
1520 1521
                break;
            case DW_TAG_variable:
1522
                dwarf2_parse_variable(subpgm, block, child);
Eric Pouech's avatar
Eric Pouech committed
1523
                break;
1524
            case DW_TAG_lexical_block:
1525
                dwarf2_parse_subprogram_block(subpgm, block, child);
1526 1527 1528 1529 1530 1531
                break;
            case DW_TAG_subprogram:
                /* FIXME: likely a declaration (to be checked)
                 * skip it for now
                 */
                break;
1532 1533 1534 1535 1536
            case DW_TAG_formal_parameter:
                /* FIXME: likely elements for exception handling (GCC flavor)
                 * Skip it for now
                 */
                break;
1537 1538 1539
            case DW_TAG_label:
                dwarf2_parse_subprogram_label(subpgm, child);
                break;
1540 1541 1542 1543
            case DW_TAG_class_type:
            case DW_TAG_structure_type:
            case DW_TAG_union_type:
            case DW_TAG_enumeration_type:
1544
            case DW_TAG_typedef:
1545 1546
                /* the type referred to will be loaded when we need it, so skip it */
                break;
Eric Pouech's avatar
Eric Pouech committed
1547 1548
            default:
                FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
1549
                      child->abbrev->tag, dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
Eric Pouech's avatar
Eric Pouech committed
1550
            }
1551
        }
Raphael Junqueira's avatar
Raphael Junqueira committed
1552
    }
1553 1554

    symt_close_func_block(subpgm->ctx->module, subpgm->func, block, 0);
Raphael Junqueira's avatar
Raphael Junqueira committed
1555 1556
}

Eric Pouech's avatar
Eric Pouech committed
1557 1558 1559
static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
                                            dwarf2_debug_info_t* di,
                                            struct symt_compiland* compiland)
Raphael Junqueira's avatar
Raphael Junqueira committed
1560
{
1561 1562 1563 1564 1565
    struct attribute name;
    struct attribute low_pc;
    struct attribute high_pc;
    struct attribute is_decl;
    struct attribute inline_flags;
Eric Pouech's avatar
Eric Pouech committed
1566 1567
    struct symt* ret_type;
    struct symt_function_signature* sig_type;
1568
    dwarf2_subprogram_t subpgm;
Eric Pouech's avatar
Eric Pouech committed
1569 1570 1571 1572 1573

    if (di->symt) return di->symt;

    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));

1574 1575 1576 1577 1578
    if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name))
    {
        WARN("No name for function... dropping function\n");
        return NULL;
    }
1579 1580 1581 1582 1583 1584
    /* if it's an abstract representation of an inline function, there should be
     * a concrete object that we'll handle
     */
    if (dwarf2_find_attribute(ctx, di, DW_AT_inline, &inline_flags))
    {
        TRACE("Function %s declared as inlined (%ld)... skipping\n",
1585
              name.u.string ? name.u.string : "(null)", inline_flags.u.uvalue);
1586 1587 1588
        return NULL;
    }

1589 1590
    if (!dwarf2_find_attribute(ctx, di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0;
    if (!dwarf2_find_attribute(ctx, di, DW_AT_high_pc, &high_pc)) high_pc.u.uvalue = 0;
Eric Pouech's avatar
Eric Pouech committed
1591 1592 1593 1594
    /* As functions (defined as inline assembly) get debug info with dwarf
     * (not the case for stabs), we just drop Wine's thunks here...
     * Actual thunks will be created in elf_module from the symbol table
     */
1595
    if (elf_is_in_thunk_area(ctx->load_offset + low_pc.u.uvalue,
Eric Pouech's avatar
Eric Pouech committed
1596 1597
                             ctx->thunks) >= 0)
        return NULL;
1598 1599 1600
    if (!dwarf2_find_attribute(ctx, di, DW_AT_declaration, &is_decl))
        is_decl.u.uvalue = 0;
        
1601
    if (!(ret_type = dwarf2_lookup_type(ctx, di)))
1602 1603 1604 1605
    {
        ret_type = ctx->symt_cache[sc_void];
        assert(ret_type);
    }
Eric Pouech's avatar
Eric Pouech committed
1606 1607 1608

    /* FIXME: assuming C source code */
    sig_type = symt_new_function_signature(ctx->module, ret_type, CV_CALL_FAR_C);
1609
    if (!is_decl.u.uvalue)
Eric Pouech's avatar
Eric Pouech committed
1610
    {
1611
        subpgm.func = symt_new_function(ctx->module, compiland, name.u.string,
1612
                                        ctx->load_offset + low_pc.u.uvalue,
1613
                                        high_pc.u.uvalue - low_pc.u.uvalue,
1614 1615 1616 1617 1618 1619 1620
                                        &sig_type->symt);
        di->symt = &subpgm.func->symt;
    }
    else subpgm.func = NULL;

    subpgm.ctx = ctx;
    subpgm.compiland = compiland;
1621 1622
    if (!dwarf2_compute_location_attr(ctx, di, DW_AT_frame_base,
                                      &subpgm.frame, NULL))
1623
    {
1624 1625 1626 1627
        /* on stack !! */
        subpgm.frame.kind = loc_regrel;
        subpgm.frame.reg = 0;
        subpgm.frame.offset = 0;
1628
    }
1629
    subpgm.non_computed_variable = FALSE;
1630

Eric Pouech's avatar
Eric Pouech committed
1631 1632 1633
    if (di->abbrev->have_child) /** any interest to not have child ? */
    {
        dwarf2_debug_info_t*    child;
1634
        unsigned int    i;
Eric Pouech's avatar
Eric Pouech committed
1635

1636
        for (i=0; i<vector_length(&di->children); i++)
Eric Pouech's avatar
Eric Pouech committed
1637
        {
1638
            child = *(dwarf2_debug_info_t**)vector_at(&di->children, i);
Eric Pouech's avatar
Eric Pouech committed
1639 1640 1641

            switch (child->abbrev->tag)
            {
1642
            case DW_TAG_variable:
Eric Pouech's avatar
Eric Pouech committed
1643
            case DW_TAG_formal_parameter:
1644
                dwarf2_parse_variable(&subpgm, NULL, child);
Eric Pouech's avatar
Eric Pouech committed
1645 1646
                break;
            case DW_TAG_lexical_block:
1647
                dwarf2_parse_subprogram_block(&subpgm, NULL, child);
Eric Pouech's avatar
Eric Pouech committed
1648
                break;
1649
            case DW_TAG_inlined_subroutine:
1650
                dwarf2_parse_inlined_subroutine(&subpgm, NULL, child);
1651 1652 1653 1654 1655 1656
                break;
            case DW_TAG_subprogram:
                /* FIXME: likely a declaration (to be checked)
                 * skip it for now
                 */
                break;
1657
            case DW_TAG_label:
1658
                dwarf2_parse_subprogram_label(&subpgm, child);
1659
                break;
1660 1661 1662 1663 1664 1665 1666 1667 1668 1669
            case DW_TAG_class_type:
            case DW_TAG_structure_type:
            case DW_TAG_union_type:
            case DW_TAG_enumeration_type:
            case DW_TAG_typedef:
                /* the type referred to will be loaded when we need it, so skip it */
                break;
            case DW_TAG_unspecified_parameters:
                /* FIXME: no support in dbghelp's internals so far */
                break;
Eric Pouech's avatar
Eric Pouech committed
1670 1671 1672 1673
            default:
                FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
                      child->abbrev->tag, dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
            }
Raphael Junqueira's avatar
Raphael Junqueira committed
1674 1675
	}
    }
Eric Pouech's avatar
Eric Pouech committed
1676

1677 1678 1679 1680 1681
    if (subpgm.non_computed_variable || subpgm.frame.kind >= loc_user)
    {
        symt_add_function_point(ctx->module, subpgm.func, SymTagCustom,
                                &subpgm.frame, NULL);
    }
1682
    if (subpgm.func) symt_normalize_function(subpgm.ctx->module, subpgm.func);
Eric Pouech's avatar
Eric Pouech committed
1683 1684

    return di->symt;
Raphael Junqueira's avatar
Raphael Junqueira committed
1685 1686
}

1687 1688 1689 1690 1691 1692 1693 1694 1695 1696
static struct symt* dwarf2_parse_subroutine_type(dwarf2_parse_context_t* ctx,
                                                 dwarf2_debug_info_t* di)
{
    struct symt* ret_type;
    struct symt_function_signature* sig_type;

    if (di->symt) return di->symt;

    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));

1697
    if (!(ret_type = dwarf2_lookup_type(ctx, di)))
1698 1699 1700 1701
    {
        ret_type = ctx->symt_cache[sc_void];
        assert(ret_type);
    }
1702 1703 1704 1705 1706 1707 1708

    /* FIXME: assuming C source code */
    sig_type = symt_new_function_signature(ctx->module, ret_type, CV_CALL_FAR_C);

    if (di->abbrev->have_child) /** any interest to not have child ? */
    {
        dwarf2_debug_info_t*    child;
1709
        unsigned int    i;
1710

1711
        for (i=0; i<vector_length(&di->children); i++)
1712
        {
1713
            child = *(dwarf2_debug_info_t**)vector_at(&di->children, i);
1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730

            switch (child->abbrev->tag)
            {
            case DW_TAG_formal_parameter:
                symt_add_function_signature_parameter(ctx->module, sig_type,
                                                      dwarf2_lookup_type(ctx, child));
                break;
            case DW_TAG_unspecified_parameters:
                WARN("Unsupported unspecified parameters\n");
                break;
            }
	}
    }

    return di->symt = &sig_type->symt;
}

Eric Pouech's avatar
Eric Pouech committed
1731 1732 1733
static void dwarf2_load_one_entry(dwarf2_parse_context_t* ctx,
                                  dwarf2_debug_info_t* di,
                                  struct symt_compiland* compiland)
Raphael Junqueira's avatar
Raphael Junqueira committed
1734
{
Eric Pouech's avatar
Eric Pouech committed
1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760
    switch (di->abbrev->tag)
    {
    case DW_TAG_typedef:
        dwarf2_parse_typedef(ctx, di);
        break;
    case DW_TAG_base_type:
        dwarf2_parse_base_type(ctx, di);
        break;
    case DW_TAG_pointer_type:
        dwarf2_parse_pointer_type(ctx, di);
        break;
    case DW_TAG_class_type:
        dwarf2_parse_udt_type(ctx, di, UdtClass);
        break;
    case DW_TAG_structure_type:
        dwarf2_parse_udt_type(ctx, di, UdtStruct);
        break;
    case DW_TAG_union_type:
        dwarf2_parse_udt_type(ctx, di, UdtUnion);
        break;
    case DW_TAG_array_type:
        dwarf2_parse_array_type(ctx, di);
        break;
    case DW_TAG_const_type:
        dwarf2_parse_const_type(ctx, di);
        break;
1761 1762 1763
    case DW_TAG_volatile_type:
        dwarf2_parse_volatile_type(ctx, di);
        break;
Eric Pouech's avatar
Eric Pouech committed
1764 1765 1766 1767 1768 1769 1770 1771 1772
    case DW_TAG_reference_type:
        dwarf2_parse_reference_type(ctx, di);
        break;
    case DW_TAG_enumeration_type:
        dwarf2_parse_enumeration_type(ctx, di);
        break;
    case DW_TAG_subprogram:
        dwarf2_parse_subprogram(ctx, di, compiland);
        break;
1773 1774 1775 1776 1777 1778 1779 1780 1781 1782
    case DW_TAG_subroutine_type:
        dwarf2_parse_subroutine_type(ctx, di);
        break;
    case DW_TAG_variable:
        {
            dwarf2_subprogram_t subpgm;

            subpgm.ctx = ctx;
            subpgm.compiland = compiland;
            subpgm.func = NULL;
1783 1784 1785
            subpgm.frame.kind = loc_absolute;
            subpgm.frame.offset = 0;
            subpgm.frame.reg = Wine_DW_no_register;
1786 1787 1788
            dwarf2_parse_variable(&subpgm, NULL, di);
        }
        break;
Raphael Junqueira's avatar
Raphael Junqueira committed
1789
    default:
1790 1791
        FIXME("Unhandled Tag type 0x%lx at %s, for %lu\n",
              di->abbrev->tag, dwarf2_debug_ctx(ctx), di->abbrev->entry_code); 
Raphael Junqueira's avatar
Raphael Junqueira committed
1792 1793 1794
    }
}

1795
static void dwarf2_set_line_number(struct module* module, unsigned long address,
1796
                                   const struct vector* v, unsigned file, unsigned line)
1797 1798
{
    struct symt_function*       func;
1799
    struct symt_ht*             symt;
1800 1801 1802 1803
    unsigned*                   psrc;

    if (!file || !(psrc = vector_at(v, file - 1))) return;

1804 1805
    TRACE("%s %lx %s %u\n",
          debugstr_w(module->module.ModuleName), address, source_get(module, *psrc), line);
1806 1807 1808
    if (!(symt = symt_find_nearest(module, address)) ||
        symt->symt.tag != SymTagFunction) return;
    func = (struct symt_function*)symt;
1809 1810 1811
    symt_add_func_line(module, func, *psrc, line, address - func->address);
}

1812
static BOOL dwarf2_parse_line_numbers(const dwarf2_section_t* sections,
1813
                                      dwarf2_parse_context_t* ctx,
1814
                                      const char* compile_dir,
1815 1816 1817 1818 1819 1820 1821 1822
                                      unsigned long offset)
{
    dwarf2_traverse_context_t   traverse;
    unsigned long               length;
    unsigned                    version, header_len, insn_size, default_stmt;
    unsigned                    line_range, opcode_base;
    int                         line_base;
    const unsigned char*        opcode_len;
1823 1824 1825
    struct vector               dirs;
    struct vector               files;
    const char**                p;
1826

1827
    /* section with line numbers stripped */
1828
    if (sections[section_line].address == ELF_NO_MAP)
1829
        return FALSE;
1830

1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842
    traverse.data = sections[section_line].address + offset;
    traverse.start_data = traverse.data;
    traverse.end_data = traverse.data + 4;
    traverse.word_size = ctx->word_size;

    length = dwarf2_parse_u4(&traverse);
    traverse.end_data = traverse.start_data + length;

    version = dwarf2_parse_u2(&traverse);
    header_len = dwarf2_parse_u4(&traverse);
    insn_size = dwarf2_parse_byte(&traverse);
    default_stmt = dwarf2_parse_byte(&traverse);
1843
    line_base = (signed char)dwarf2_parse_byte(&traverse);
1844 1845 1846 1847
    line_range = dwarf2_parse_byte(&traverse);
    opcode_base = dwarf2_parse_byte(&traverse);

    opcode_len = traverse.data;
1848
    traverse.data += opcode_base - 1;
1849

1850 1851
    vector_init(&dirs, sizeof(const char*), 4);
    p = vector_add(&dirs, &ctx->pool);
1852
    *p = compile_dir ? compile_dir : ".";
1853 1854
    while (*traverse.data)
    {
1855 1856 1857 1858
        const char*  rel = (const char*)traverse.data;
        unsigned     rellen = strlen(rel);
        TRACE("Got include %s\n", rel);
        traverse.data += rellen + 1;
1859
        p = vector_add(&dirs, &ctx->pool);
1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873

        if (*rel == '/' || !compile_dir)
            *p = rel;
        else
        {
           /* include directory relative to compile directory */
           unsigned  baselen = strlen(compile_dir);
           char*     tmp = pool_alloc(&ctx->pool, baselen + 1 + rellen + 1);
           strcpy(tmp, compile_dir);
           if (tmp[baselen - 1] != '/') tmp[baselen++] = '/';
           strcpy(&tmp[baselen], rel);
           *p = tmp;
        }

1874 1875
    }
    traverse.data++;
1876 1877

    vector_init(&files, sizeof(unsigned), 16);
1878 1879
    while (*traverse.data)
    {
1880 1881 1882 1883
        unsigned int    dir_index, mod_time, length;
        const char*     name;
        const char*     dir;
        unsigned*       psrc;
1884 1885 1886 1887 1888 1889

        name = (const char*)traverse.data;
        traverse.data += strlen(name) + 1;
        dir_index = dwarf2_leb128_as_unsigned(&traverse);
        mod_time = dwarf2_leb128_as_unsigned(&traverse);
        length = dwarf2_leb128_as_unsigned(&traverse);
1890 1891 1892 1893
        dir = *(const char**)vector_at(&dirs, dir_index);
        TRACE("Got file %s/%s (%u,%u)\n", dir, name, mod_time, length);
        psrc = vector_add(&files, &ctx->pool);
        *psrc = source_new(ctx->module, dir, name);
1894 1895 1896 1897 1898
    }
    traverse.data++;

    while (traverse.data < traverse.end_data)
    {
1899
        unsigned long address = 0;
1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917
        unsigned file = 1;
        unsigned line = 1;
        unsigned is_stmt = default_stmt;
        BOOL basic_block = FALSE, end_sequence = FALSE;
        unsigned opcode, extopcode, i;

        while (!end_sequence)
        {
            opcode = dwarf2_parse_byte(&traverse);
            TRACE("Got opcode %x\n", opcode);

            if (opcode >= opcode_base)
            {
                unsigned delta = opcode - opcode_base;

                address += (delta / line_range) * insn_size;
                line += line_base + (delta % line_range);
                basic_block = TRUE;
1918
                dwarf2_set_line_number(ctx->module, address, &files, file, line);
1919 1920 1921 1922 1923 1924 1925
            }
            else
            {
                switch (opcode)
                {
                case DW_LNS_copy:
                    basic_block = FALSE;
1926
                    dwarf2_set_line_number(ctx->module, address, &files, file, line);
1927 1928 1929 1930 1931
                    break;
                case DW_LNS_advance_pc:
                    address += insn_size * dwarf2_leb128_as_unsigned(&traverse);
                    break;
                case DW_LNS_advance_line:
1932
                    line += dwarf2_leb128_as_signed(&traverse);
1933 1934
                    break;
                case DW_LNS_set_file:
1935
                    file = dwarf2_leb128_as_unsigned(&traverse);
1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957
                    break;
                case DW_LNS_set_column:
                    dwarf2_leb128_as_unsigned(&traverse);
                    break;
                case DW_LNS_negate_stmt:
                    is_stmt = !is_stmt;
                    break;
                case DW_LNS_set_basic_block:
                    basic_block = 1;
                    break;
                case DW_LNS_const_add_pc:
                    address += ((255 - opcode_base) / line_range) * insn_size;
                    break;
                case DW_LNS_fixed_advance_pc:
                    address += dwarf2_parse_u2(&traverse);
                    break;
                case DW_LNS_extended_op:
                    dwarf2_leb128_as_unsigned(&traverse);
                    extopcode = dwarf2_parse_byte(&traverse);
                    switch (extopcode)
                    {
                    case DW_LNE_end_sequence:
1958
                        dwarf2_set_line_number(ctx->module, address, &files, file, line);
1959 1960 1961
                        end_sequence = TRUE;
                        break;
                    case DW_LNE_set_address:
1962
                        address = ctx->load_offset + dwarf2_parse_addr(&traverse);
1963 1964
                        break;
                    case DW_LNE_define_file:
1965
                        FIXME("not handled %s\n", traverse.data);
1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984
                        traverse.data += strlen((const char *)traverse.data) + 1;
                        dwarf2_leb128_as_unsigned(&traverse);
                        dwarf2_leb128_as_unsigned(&traverse);
                        dwarf2_leb128_as_unsigned(&traverse);
                        break;
                    default:
                        FIXME("Unsupported extended opcode %x\n", extopcode);
                        break;
                    }
                    break;
                default:
                    WARN("Unsupported opcode %x\n", opcode);
                    for (i = 0; i < opcode_len[opcode]; i++)
                        dwarf2_leb128_as_unsigned(&traverse);
                    break;
                }
            }
        }
    }
1985
    return TRUE;
1986 1987
}

1988 1989
static BOOL dwarf2_parse_compilation_unit(const dwarf2_section_t* sections,
                                          struct module* module,
Eric Pouech's avatar
Eric Pouech committed
1990
                                          const struct elf_thunk_area* thunks,
1991
                                          dwarf2_traverse_context_t* mod_ctx,
1992
                                          unsigned long load_offset)
1993 1994
{
    dwarf2_parse_context_t ctx;
1995
    dwarf2_traverse_context_t abbrev_ctx;
1996
    dwarf2_debug_info_t* di;
1997 1998 1999 2000 2001
    dwarf2_traverse_context_t cu_ctx;
    const unsigned char* comp_unit_start = mod_ctx->data;
    unsigned long cu_length;
    unsigned short cu_version;
    unsigned long cu_abbrev_offset;
2002
    BOOL ret = FALSE;
2003

2004 2005 2006 2007 2008 2009 2010 2011
    cu_length = dwarf2_parse_u4(mod_ctx);
    cu_ctx.data = cu_ctx.start_data = mod_ctx->data;
    cu_ctx.end_data = mod_ctx->data + cu_length;
    mod_ctx->data += cu_length;
    cu_version = dwarf2_parse_u2(&cu_ctx);
    cu_abbrev_offset = dwarf2_parse_u4(&cu_ctx);
    cu_ctx.word_size = dwarf2_parse_byte(&cu_ctx);

2012
    TRACE("Compilation Unit Header found at 0x%x:\n",
2013 2014 2015 2016 2017
          comp_unit_start - sections[section_debug].address);
    TRACE("- length:        %lu\n", cu_length);
    TRACE("- version:       %u\n",  cu_version);
    TRACE("- abbrev_offset: %lu\n", cu_abbrev_offset);
    TRACE("- word_size:     %u\n",  cu_ctx.word_size);
2018

2019
    if (cu_version != 2)
2020 2021
    {
        WARN("%u DWARF version unsupported. Wine dbghelp only support DWARF 2.\n",
2022
             cu_version);
2023 2024
        return FALSE;
    }
2025

2026
    pool_init(&ctx.pool, 65536);
2027 2028
    ctx.sections = sections;
    ctx.section = section_debug;
2029
    ctx.module = module;
2030
    ctx.word_size = cu_ctx.word_size;
Eric Pouech's avatar
Eric Pouech committed
2031
    ctx.thunks = thunks;
2032
    ctx.load_offset = load_offset;
2033
    ctx.ref_offset = comp_unit_start - sections[section_debug].address;
2034 2035
    memset(ctx.symt_cache, 0, sizeof(ctx.symt_cache));
    ctx.symt_cache[sc_void] = &symt_new_basic(module, btVoid, "void", 0)->symt;
2036

2037
    abbrev_ctx.start_data = sections[section_abbrev].address + cu_abbrev_offset;
2038 2039
    abbrev_ctx.data = abbrev_ctx.start_data;
    abbrev_ctx.end_data = sections[section_abbrev].address + sections[section_abbrev].size;
2040
    abbrev_ctx.word_size = cu_ctx.word_size;
2041
    dwarf2_parse_abbrev_set(&abbrev_ctx, &ctx.abbrev_table, &ctx.pool);
Raphael Junqueira's avatar
Raphael Junqueira committed
2042

2043
    sparse_array_init(&ctx.debug_info_table, sizeof(dwarf2_debug_info_t), 128);
2044
    dwarf2_read_one_debug_info(&ctx, &cu_ctx, &di);
2045

Eric Pouech's avatar
Eric Pouech committed
2046 2047
    if (di->abbrev->tag == DW_TAG_compile_unit)
    {
2048
        struct attribute            name;
Eric Pouech's avatar
Eric Pouech committed
2049
        dwarf2_debug_info_t**       pdi = NULL;
2050
        struct attribute            stmt_list, low_pc;
2051
        struct attribute            comp_dir;
Eric Pouech's avatar
Eric Pouech committed
2052

2053 2054
        if (!dwarf2_find_attribute(&ctx, di, DW_AT_name, &name))
            name.u.string = NULL;
2055 2056 2057 2058 2059

        /* get working directory of current compilation unit */
        if (!dwarf2_find_attribute(&ctx, di, DW_AT_comp_dir, &comp_dir))
            comp_dir.u.string = NULL;

2060 2061 2062
        if (!dwarf2_find_attribute(&ctx, di, DW_AT_low_pc, &low_pc))
            low_pc.u.uvalue = 0;
        di->symt = &symt_new_compiland(module, 
2063
                                       ctx.load_offset + low_pc.u.uvalue,
2064
                                       source_new(module, comp_dir.u.string, name.u.string))->symt;
Eric Pouech's avatar
Eric Pouech committed
2065 2066 2067

        if (di->abbrev->have_child)
        {
2068
            unsigned int    i;
2069
            for (i=0; i<vector_length(&di->children); i++)
Eric Pouech's avatar
Eric Pouech committed
2070
            {
2071
                pdi = vector_at(&di->children, i);
Eric Pouech's avatar
Eric Pouech committed
2072 2073 2074
                dwarf2_load_one_entry(&ctx, *pdi, (struct symt_compiland*)di->symt);
            }
        }
2075
        if (dwarf2_find_attribute(&ctx, di, DW_AT_stmt_list, &stmt_list))
2076
        {
2077 2078
            if (dwarf2_parse_line_numbers(sections, &ctx, comp_dir.u.string, stmt_list.u.uvalue))
                module->module.LineNumbers = TRUE;
2079
        }
2080
        ret = TRUE;
2081
    }
Eric Pouech's avatar
Eric Pouech committed
2082
    else FIXME("Should have a compilation unit here\n");
2083
    pool_destroy(&ctx.pool);
2084 2085 2086
    return ret;
}

2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114
static BOOL dwarf2_lookup_loclist(const struct module* module, const BYTE* start,
                                  unsigned long ip,
                                  dwarf2_traverse_context_t*  lctx)
{
    DWORD                       beg, end;
    const BYTE*                 ptr = start;
    DWORD                       len;

    while (ptr < module->dwarf2_info->debug_loc.address + module->dwarf2_info->debug_loc.size)
    {
        beg = dwarf2_get_u4(ptr); ptr += 4;
        end = dwarf2_get_u4(ptr); ptr += 4;
        if (!beg && !end) break;
        len = dwarf2_get_u2(ptr); ptr += 2;

        if (beg <= ip && ip < end)
        {
            lctx->data = ptr;
            lctx->end_data = ptr + len;
            lctx->word_size = 4; /* FIXME word size !!! */
            return TRUE;
        }
        ptr += len;
    }
    WARN("Couldn't find ip in location list\n");
    return FALSE;
}

2115 2116
static enum location_error loc_compute_frame(struct process* pcs,
                                             const struct module* module,
2117 2118 2119 2120 2121 2122 2123
                                             const struct symt_function* func,
                                             DWORD ip, struct location* frame)
{
    struct symt**               psym = NULL;
    struct location*            pframe;
    dwarf2_traverse_context_t   lctx;
    enum location_error         err;
2124
    unsigned int                i;
2125

2126
    for (i=0; i<vector_length(&func->vchildren); i++)
2127
    {
2128
        psym = vector_at(&func->vchildren, i);
2129 2130
        if ((*psym)->tag == SymTagCustom)
        {
2131
            pframe = &((struct symt_hierarchy_point*)*psym)->loc;
2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145

            /* First, recompute the frame information, if needed */
            switch (pframe->kind)
            {
            case loc_regrel:
            case loc_register:
                *frame = *pframe;
                break;
            case loc_dwarf2_location_list:
                WARN("Searching loclist for %s\n", func->hash_elt.name);
                if (!dwarf2_lookup_loclist(module, 
                                           module->dwarf2_info->debug_loc.address + pframe->offset,
                                           ip, &lctx))
                    return loc_err_out_of_scope;
2146
                if ((err = compute_location(&lctx, frame, pcs->handle, NULL)) < 0) return err;
2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163
                if (frame->kind >= loc_user)
                {
                    WARN("Couldn't compute runtime frame location\n");
                    return loc_err_too_complex;
                }
                break;
            default:
                WARN("Unsupported frame kind %d\n", pframe->kind);
                return loc_err_internal;
            }
            return 0;
        }
    }
    WARN("Couldn't find Custom function point, whilst location list offset is searched\n");
    return loc_err_internal;
}

2164 2165 2166 2167 2168
static void dwarf2_location_compute(struct process* pcs,
                                    const struct module* module,
                                    const struct symt_function* func,
                                    struct location* loc)
{
2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183
    struct location             frame;
    DWORD                       ip;
    int                         err;
    dwarf2_traverse_context_t   lctx;

    if (!func->container || func->container->tag != SymTagCompiland)
    {
        WARN("We'd expect function %s's container to exist and be a compiland\n", func->hash_elt.name);
        err = loc_err_internal;
    }
    else
    {
        /* instruction pointer relative to compiland's start */
        ip = pcs->ctx_frame.InstructionOffset - ((struct symt_compiland*)func->container)->address;

2184
        if ((err = loc_compute_frame(pcs, module, func, ip, &frame)) == 0)
2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206
        {
            switch (loc->kind)
            {
            case loc_dwarf2_location_list:
                /* Then, if the variable has a location list, find it !! */
                if (dwarf2_lookup_loclist(module, 
                                          module->dwarf2_info->debug_loc.address + loc->offset,
                                          ip, &lctx))
                    goto do_compute;
                err = loc_err_out_of_scope;
                break;
            case loc_dwarf2_block:
                /* or if we have a copy of an existing block, get ready for it */
                {
                    unsigned*   ptr = (unsigned*)loc->offset;

                    lctx.data = (const BYTE*)(ptr + 1);
                    lctx.end_data = lctx.data + *ptr;
                    lctx.word_size = 4; /* FIXME !! */
                }
            do_compute:
                /* now get the variable */
2207
                err = compute_location(&lctx, loc, pcs->handle, &frame);
2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223
                break;
            case loc_register:
            case loc_regrel:
                /* nothing to do */
                break;
            default:
                WARN("Unsupported local kind %d\n", loc->kind);
                err = loc_err_internal;
            }
        }
    }
    if (err < 0)
    {
        loc->kind = loc_register;
        loc->reg = err;
    }
2224 2225
}

2226
BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
Eric Pouech's avatar
Eric Pouech committed
2227
                  const struct elf_thunk_area* thunks,
2228 2229
		  const unsigned char* debug, unsigned int debug_size,
		  const unsigned char* abbrev, unsigned int abbrev_size,
2230
		  const unsigned char* str, unsigned int str_size,
2231 2232
		  const unsigned char* line, unsigned int line_size,
		  const unsigned char* loclist, unsigned int loclist_size)
2233 2234
{
    dwarf2_section_t    section[section_max];
2235
    unsigned char*      ptr;
2236 2237 2238 2239
    dwarf2_traverse_context_t   mod_ctx;

    mod_ctx.start_data = mod_ctx.data = debug;
    mod_ctx.end_data = debug + debug_size;
2240

2241 2242
    module->loc_compute = dwarf2_location_compute;

2243 2244 2245 2246 2247 2248
    section[section_debug].address = debug;
    section[section_debug].size = debug_size;
    section[section_abbrev].address = abbrev;
    section[section_abbrev].size = abbrev_size;
    section[section_string].address = str;
    section[section_string].size = str_size;
2249 2250
    section[section_line].address = line;
    section[section_line].size = line_size;
2251

2252 2253 2254 2255 2256 2257 2258 2259
    if (loclist_size)
    {
        /* initialize the dwarf2 specific info block for this module.
         * As we'll need later on the .debug_loc section content, we copy it in
         * the module structure for later reuse
         */
        module->dwarf2_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*module->dwarf2_info) + loclist_size);
        if (!module->dwarf2_info) return FALSE;
2260
        ptr = (unsigned char*)(module->dwarf2_info + 1);
2261 2262 2263 2264 2265
        memcpy(ptr, loclist, loclist_size);
        module->dwarf2_info->debug_loc.address = ptr;
        module->dwarf2_info->debug_loc.size    = loclist_size;
    }

2266
    while (mod_ctx.data < mod_ctx.end_data)
2267
    {
2268
        dwarf2_parse_compilation_unit(section, module, thunks, &mod_ctx, load_offset);
2269 2270
    }
    module->module.SymType = SymDia;
Eric Pouech's avatar
Eric Pouech committed
2271 2272 2273 2274 2275 2276
    module->module.CVSig = 'D' | ('W' << 8) | ('A' << 16) | ('R' << 24);
    /* FIXME: we could have a finer grain here */
    module->module.GlobalSymbols = TRUE;
    module->module.TypeInfo = TRUE;
    module->module.SourceIndexed = TRUE;
    module->module.Publics = TRUE;
2277
    return TRUE;
2278
}