dwarf.c 76.7 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 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
 */

#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"
47 48 49
#include "winuser.h"
#include "ole2.h"
#include "oleauto.h"
50 51 52 53 54 55 56

#include "dbghelp_private.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_dwarf);

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

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

    for (i = 0; i < len; i += 16)
76
    {
77 78 79 80 81 82 83 84 85 86 87 88 89
        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);
90 91
    }
}
92
#endif
93

94 95 96 97 98 99 100 101 102 103 104 105
/**
 *
 * 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
 */
106
#include "dwarf.h"
107

108 109 110 111
/**
 * Parsers
 */

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

119 120 121 122 123 124 125
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
126 127
} dwarf2_abbrev_entry_t;

128 129 130 131 132 133
struct dwarf2_block
{
    unsigned                    size;
    const unsigned char*        ptr;
};

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

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

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

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

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;

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

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

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

198 199 200
#define loc_dwarf2_location_list        (loc_user + 0)
#define loc_dwarf2_block                (loc_user + 1)

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

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

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

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

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

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

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

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

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

253
    if (end) *end = ptr;
254
    return ret;
255 256
}

257 258 259 260 261 262 263 264 265 266 267 268
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)
269
{
270 271 272 273 274
    long ret = 0;
    unsigned char byte;
    unsigned shift = 0;
    const unsigned size = sizeof(int) * 8;

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

283 284 285 286 287 288 289 290
    /* 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;
291 292
}

293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
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)
311 312 313
{
    unsigned long ret;

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

326 327 328 329 330 331 332
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;
}

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

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

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

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

358
static void dwarf2_parse_abbrev_set(dwarf2_traverse_context_t* abbrev_ctx, 
359 360
                                    struct sparse_array* abbrev_table,
                                    struct pool* pool)
361
{
362 363 364 365 366 367
    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;
368

369
    assert( NULL != abbrev_ctx );
370

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

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

388 389 390 391 392
        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;
393

394 395 396
        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);
397

398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
        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++;
        }
416
    }
417
    TRACE("found %u entries\n", sparse_array_length(abbrev_table));
418 419
}

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

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

427 428
    switch (abbrev_attr->form)
    {
429
    case DW_FORM_ref_addr:
430
    case DW_FORM_addr:   step = ctx->word_size; break;
431 432
    case DW_FORM_flag:
    case DW_FORM_data1:
433
    case DW_FORM_ref1:   step = 1; break;
434
    case DW_FORM_data2:
435
    case DW_FORM_ref2:   step = 2; break;
436 437
    case DW_FORM_data4:
    case DW_FORM_ref4:
438 439 440
    case DW_FORM_strp:   step = 4; break;
    case DW_FORM_data8:
    case DW_FORM_ref8:   step = 8; break;
441 442
    case DW_FORM_sdata:
    case DW_FORM_ref_udata:
443 444 445 446 447 448
    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;
449 450
    default:
        FIXME("Unhandled attribute form %lx\n", abbrev_attr->form);
451
        return;
452
    }
453
    ctx->data += step;
454 455
}

456 457 458 459
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)
460
{
461 462
    attr->form = abbrev_attr->form;
    switch (attr->form)
463
    {
464 465 466 467 468
    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;
469

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

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

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

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

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

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

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

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

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

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

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

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

530 531 532 533 534 535 536 537 538 539 540
    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;
541

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

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

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

557 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
    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;
586
            }
587
        }
588 589 590 591 592
        /* 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");
593 594 595 596
    }
    return FALSE;
}

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

600
#define Wine_DW_no_register     0x7FFFFFFF
601

602
static unsigned dwarf2_map_register(int regno)
603
{
604 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
    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;
}

649 650
static enum location_error
compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
651
                 HANDLE hproc, const struct location* frame)
652 653
{
    unsigned long stack[64];
654
    unsigned stk;
655 656 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
    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:
687 688 689 690 691 692 693 694 695 696 697 698 699
            /* 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;
700 701 702 703 704 705 706 707 708 709 710 711
        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)
             */
712
            if (!piece_found)
713 714
            {
                if (loc->reg != Wine_DW_no_register)
715 716 717
                    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);
718
            }
719 720
            stack[++stk] = dwarf2_leb128_as_signed(ctx);
            loc->kind = loc_regrel;
721 722 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
            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);
749
                WARN("Not handling OP_piece (size=%d)\n", sz);
750 751 752
                piece_found = TRUE;
            }
            break;
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
        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))
                {
771
                    WARN("Couldn't read memory at %x\n", addr);
772 773 774 775 776 777 778 779 780
                    return loc_err_cant_read;
                }
                stack[++stk] = deref;
            }
            else
            {
               loc->kind = loc_dwarf2_block;
            }
            break;
781 782
        default:
            FIXME("Unhandled attr op: %x\n", op);
783
            return loc_err_internal;
784 785 786
        }
    }
    loc->offset = stack[stk];
787
    return 0;
788 789 790
}

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

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

800 801 802 803
    switch (xloc.form)
    {
    case DW_FORM_data1: case DW_FORM_data2:
    case DW_FORM_udata: case DW_FORM_sdata:
804 805 806 807 808 809 810 811
        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;
812 813
        return TRUE;
    }
814

815
    /* assume we have a block form */
816

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

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

826
        err = compute_location(&lctx, loc, NULL, frame);
827
        if (err < 0)
828 829
        {
            loc->kind = loc_error;
830
            loc->reg = err;
831 832 833 834 835 836 837 838 839
        }
        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;
        }
840
    }
841
    return TRUE;
842 843
}

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

849
    if (dwarf2_find_attribute(ctx, di, DW_AT_type, &attr))
Eric Pouech's avatar
Eric Pouech committed
850 851 852
    {
        dwarf2_debug_info_t*    type;
        
853 854
        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
855 856 857 858 859 860 861 862
        if (!type->symt)
        {
            /* load the debug info entity */
            dwarf2_load_one_entry(ctx, type, NULL);
        }
        return type->symt;
    }
    return NULL;
863 864
}

865 866 867 868 869 870
/******************************************************************
 *		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,
871
                                       dwarf2_traverse_context_t* traverse,
872 873 874 875 876 877 878 879 880 881
                                       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;
882
    struct attribute            sibling;
883

884
    offset = traverse->data - ctx->sections[ctx->section].address;
885
    entry_code = dwarf2_leb128_as_unsigned(traverse);
886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904
    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)
    {
905
        di->data = pool_alloc(&ctx->pool, abbrev->num_attr * sizeof(const char*));
906 907
        for (i = 0, attr = abbrev->attrs; attr; i++, attr = attr->next)
        {
908 909
            di->data[i] = traverse->data;
            dwarf2_swallow_attribute(traverse, attr);
910 911
        }
    }
912
    else di->data = NULL;
913 914 915
    if (abbrev->have_child)
    {
        vector_init(&di->children, sizeof(dwarf2_debug_info_t*), 16);
916
        while (traverse->data < traverse->end_data)
917
        {
918
            if (!dwarf2_read_one_debug_info(ctx, traverse, &child)) return FALSE;
919 920 921 922 923 924
            if (!child) break;
            where = vector_add(&di->children, &ctx->pool);
            if (!where) return FALSE;
            *where = child;
        }
    }
925 926
    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
927 928
    {
        WARN("setting cursor for %s to next sibling <0x%lx>\n",
929
             dwarf2_debug_traverse_ctx(traverse), sibling.u.uvalue);
930
        traverse->data = ctx->sections[ctx->section].address + sibling.u.uvalue;
Eric Pouech's avatar
Eric Pouech committed
931
    }
932 933 934 935
    *pdi = di;
    return TRUE;
}

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

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

948 949
    if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name))
        name.u.string = NULL;
950 951
    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
952

953
    switch (encoding.u.uvalue)
Eric Pouech's avatar
Eric Pouech committed
954 955 956 957 958 959 960 961 962 963 964 965
    {
    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;
    }
966
    di->symt = &symt_new_basic(ctx->module, bt, name.u.string, size.u.uvalue)->symt;
967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985
    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;
    }
    if (!ctx->symt_cache[cache_idx])
        ctx->symt_cache[cache_idx] = di->symt;

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

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

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

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

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

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

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

Eric Pouech's avatar
Eric Pouech committed
1015
    if (di->symt) return di->symt;
1016

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

1019
    if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &size)) size.u.uvalue = 0;
1020
    if (!(ref_type = dwarf2_lookup_type(ctx, di)))
1021 1022 1023 1024
    {
        ref_type = ctx->symt_cache[sc_void];
        assert(ref_type);
    }
Eric Pouech's avatar
Eric Pouech committed
1025 1026 1027 1028 1029 1030 1031
    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)
1032
{
Eric Pouech's avatar
Eric Pouech committed
1033 1034
    struct symt* ref_type;
    struct symt* idx_type = NULL;
1035
    struct attribute min, max, cnt;
Eric Pouech's avatar
Eric Pouech committed
1036
    dwarf2_debug_info_t* child;
1037
    int    i;
Raphael Junqueira's avatar
Raphael Junqueira committed
1038

Eric Pouech's avatar
Eric Pouech committed
1039 1040 1041
    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
1042

Eric Pouech's avatar
Eric Pouech committed
1043 1044 1045 1046 1047 1048
    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
1049

1050
    for (i=0; i<vector_length(&di->children); i++)
Eric Pouech's avatar
Eric Pouech committed
1051
    {
1052
        child = *(dwarf2_debug_info_t**)vector_at(&di->children, i);
Eric Pouech's avatar
Eric Pouech committed
1053 1054 1055 1056
        switch (child->abbrev->tag)
        {
        case DW_TAG_subrange_type:
            idx_type = dwarf2_lookup_type(ctx, child);
1057
            if (!dwarf2_find_attribute(ctx, child, DW_AT_lower_bound, &min))
1058
                min.u.uvalue = 0;
1059
            if (!dwarf2_find_attribute(ctx, child, DW_AT_upper_bound, &max))
1060
                max.u.uvalue = 0;
1061
            if (dwarf2_find_attribute(ctx, child, DW_AT_count, &cnt))
1062
                max.u.uvalue = min.u.uvalue + cnt.u.uvalue;
Eric Pouech's avatar
Eric Pouech committed
1063 1064 1065 1066 1067 1068 1069
            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;
        }
    }
1070
    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
1071
    return di->symt;
1072 1073
}

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

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

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

Eric Pouech's avatar
Eric Pouech committed
1083 1084 1085
    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
1086

Eric Pouech's avatar
Eric Pouech committed
1087
    return ref_type;
1088 1089
}

1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
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
1106 1107
static struct symt* dwarf2_parse_reference_type(dwarf2_parse_context_t* ctx,
                                                dwarf2_debug_info_t* di)
1108
{
Eric Pouech's avatar
Eric Pouech committed
1109
    struct symt* ref_type = NULL;
Raphael Junqueira's avatar
Raphael Junqueira committed
1110

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

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

Eric Pouech's avatar
Eric Pouech committed
1115 1116 1117
    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
1118

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

    return di->symt;
Raphael Junqueira's avatar
Raphael Junqueira committed
1122 1123
}

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

    assert(parent);

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

1138
    if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) name.u.string = NULL;
Eric Pouech's avatar
Eric Pouech committed
1139
    elt_type = dwarf2_lookup_type(ctx, di);
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
    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;
1153 1154
    if (!dwarf2_find_attribute(ctx, di, DW_AT_bit_size, &bit_size))
        bit_size.u.uvalue = 0;
1155
    if (dwarf2_find_attribute(ctx, di, DW_AT_bit_offset, &bit_offset))
1156 1157 1158 1159
    {
        /* FIXME: we should only do this when implementation is LSB (which is
         * the case on i386 processors)
         */
1160
        struct attribute nbytes;
1161
        if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &nbytes))
1162 1163
        {
            DWORD64     size;
1164
            nbytes.u.uvalue = symt_get_info(elt_type, TI_GET_LENGTH, &size) ? (unsigned long)size : 0;
1165
        }
1166
        bit_offset.u.uvalue = nbytes.u.uvalue * 8 - bit_offset.u.uvalue - bit_size.u.uvalue;
1167
    }
1168 1169
    else bit_offset.u.uvalue = 0;
    symt_add_udt_element(ctx->module, parent, name.u.string, elt_type,    
1170 1171
                         (loc.offset << 3) + bit_offset.u.uvalue,
                         bit_size.u.uvalue);
1172

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

Eric Pouech's avatar
Eric Pouech committed
1176 1177 1178
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
1179
{
1180 1181
    struct attribute    name;
    struct attribute    size;
Eric Pouech's avatar
Eric Pouech committed
1182 1183 1184 1185 1186

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

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

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

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

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

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

            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;
1210 1211 1212
            case DW_TAG_structure_type:
            case DW_TAG_class_type:
            case DW_TAG_union_type:
1213
            case DW_TAG_typedef:
1214 1215
                /* FIXME: we need to handle nested udt definitions */
                break;
Eric Pouech's avatar
Eric Pouech committed
1216 1217 1218 1219 1220 1221
            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
1222
    }
Eric Pouech's avatar
Eric Pouech committed
1223 1224

    return di->symt;
Raphael Junqueira's avatar
Raphael Junqueira committed
1225 1226
}

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

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

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

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

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

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

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

1254
    if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) name.u.string = NULL;
1255 1256 1257 1258 1259 1260 1261 1262 1263
    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
1264

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

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

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

            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
1289 1290
}

1291 1292 1293 1294 1295 1296
/* 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;
1297
    BOOL                        non_computed_variable;
1298
    struct location             frame;
1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
} 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
1309
{
1310 1311 1312 1313
    struct symt*        param_type;
    struct attribute    name, value;
    struct location     loc;
    BOOL                is_pmt;
1314

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

1317
    is_pmt = !block && di->abbrev->tag == DW_TAG_formal_parameter;
1318
    param_type = dwarf2_lookup_type(subpgm->ctx, di);
1319
        
1320 1321 1322 1323
    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;
    }
1324 1325
    if (dwarf2_compute_location_attr(subpgm->ctx, di, DW_AT_location,
                                     &loc, &subpgm->frame))
1326
    {
1327
        struct attribute ext;
1328

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

1333
        switch (loc.kind)
1334
        {
1335
        case loc_absolute:
1336
            /* it's a global variable */
1337
            /* FIXME: we don't handle its scope yet */
1338
            if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_external, &ext))
1339
                ext.u.uvalue = 0;
1340
            symt_new_global_variable(subpgm->ctx->module, subpgm->compiland,
1341
                                     name.u.string, !ext.u.uvalue,
1342
                                     subpgm->ctx->load_offset + loc.offset,
1343 1344
                                     0, param_type);
            break;
1345
        default:
1346
            subpgm->non_computed_variable = TRUE;
1347
            /* fall through */
1348 1349
        case loc_register:
        case loc_regrel:
1350 1351 1352
            /* either a pmt/variable relative to frame pointer or
             * pmt/variable in a register
             */
1353
            assert(subpgm->func);
1354 1355
            symt_add_func_local(subpgm->ctx->module, subpgm->func, 
                                is_pmt ? DataIsParam : DataIsLocal,
1356
                                &loc, block, param_type, name.u.string);
1357 1358
            break;
        }
1359
    }
1360
    else if (dwarf2_find_attribute(subpgm->ctx, di, DW_AT_const_value, &value))
1361
    {
1362
        VARIANT v;
1363
        if (subpgm->func) WARN("Unsupported constant %s in function\n", name.u.string);
1364 1365 1366 1367 1368 1369 1370
        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:
1371
        case DW_FORM_addr:
1372 1373 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
            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;
1403
    }
1404 1405 1406
    if (is_pmt && subpgm->func && subpgm->func->type)
        symt_add_function_signature_parameter(subpgm->ctx->module,
                                              (struct symt_function_signature*)subpgm->func->type,
1407 1408
                                              param_type);

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

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

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

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

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

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

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

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

1445 1446 1447 1448
    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,
1449
                                 subpgm->ctx->load_offset + low_pc.u.uvalue - subpgm->func->address,
1450
                                 high_pc.u.uvalue - low_pc.u.uvalue);
1451

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

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

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

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

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

1496 1497 1498 1499
    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;
1500 1501

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

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

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

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

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

Eric Pouech's avatar
Eric Pouech committed
1555 1556 1557
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
1558
{
1559 1560 1561 1562 1563
    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
1564 1565
    struct symt* ret_type;
    struct symt_function_signature* sig_type;
1566
    dwarf2_subprogram_t subpgm;
Eric Pouech's avatar
Eric Pouech committed
1567 1568 1569 1570 1571

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

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

1572
    if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) name.u.string = NULL;
1573 1574 1575 1576 1577 1578
    /* 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",
1579
              name.u.string ? name.u.string : "(null)", inline_flags.u.uvalue);
1580 1581 1582
        return NULL;
    }

1583 1584
    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
1585 1586 1587 1588
    /* 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
     */
1589
    if (elf_is_in_thunk_area(ctx->load_offset + low_pc.u.uvalue,
Eric Pouech's avatar
Eric Pouech committed
1590 1591
                             ctx->thunks) >= 0)
        return NULL;
1592 1593 1594
    if (!dwarf2_find_attribute(ctx, di, DW_AT_declaration, &is_decl))
        is_decl.u.uvalue = 0;
        
1595
    if (!(ret_type = dwarf2_lookup_type(ctx, di)))
1596 1597 1598 1599
    {
        ret_type = ctx->symt_cache[sc_void];
        assert(ret_type);
    }
Eric Pouech's avatar
Eric Pouech committed
1600 1601 1602

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

    subpgm.ctx = ctx;
    subpgm.compiland = compiland;
1615 1616
    if (!dwarf2_compute_location_attr(ctx, di, DW_AT_frame_base,
                                      &subpgm.frame, NULL))
1617
    {
1618 1619 1620 1621
        /* on stack !! */
        subpgm.frame.kind = loc_regrel;
        subpgm.frame.reg = 0;
        subpgm.frame.offset = 0;
1622
    }
1623
    subpgm.non_computed_variable = FALSE;
1624

Eric Pouech's avatar
Eric Pouech committed
1625 1626 1627
    if (di->abbrev->have_child) /** any interest to not have child ? */
    {
        dwarf2_debug_info_t*    child;
1628
        int    i;
Eric Pouech's avatar
Eric Pouech committed
1629

1630
        for (i=0; i<vector_length(&di->children); i++)
Eric Pouech's avatar
Eric Pouech committed
1631
        {
1632
            child = *(dwarf2_debug_info_t**)vector_at(&di->children, i);
Eric Pouech's avatar
Eric Pouech committed
1633 1634 1635

            switch (child->abbrev->tag)
            {
1636
            case DW_TAG_variable:
Eric Pouech's avatar
Eric Pouech committed
1637
            case DW_TAG_formal_parameter:
1638
                dwarf2_parse_variable(&subpgm, NULL, child);
Eric Pouech's avatar
Eric Pouech committed
1639 1640
                break;
            case DW_TAG_lexical_block:
1641
                dwarf2_parse_subprogram_block(&subpgm, NULL, child);
Eric Pouech's avatar
Eric Pouech committed
1642
                break;
1643
            case DW_TAG_inlined_subroutine:
1644
                dwarf2_parse_inlined_subroutine(&subpgm, NULL, child);
1645 1646 1647 1648 1649 1650
                break;
            case DW_TAG_subprogram:
                /* FIXME: likely a declaration (to be checked)
                 * skip it for now
                 */
                break;
1651
            case DW_TAG_label:
1652
                dwarf2_parse_subprogram_label(&subpgm, child);
1653
                break;
1654 1655 1656 1657 1658 1659 1660 1661 1662 1663
            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
1664 1665 1666 1667
            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
1668 1669
	}
    }
Eric Pouech's avatar
Eric Pouech committed
1670

1671 1672 1673 1674 1675
    if (subpgm.non_computed_variable || subpgm.frame.kind >= loc_user)
    {
        symt_add_function_point(ctx->module, subpgm.func, SymTagCustom,
                                &subpgm.frame, NULL);
    }
1676
    symt_normalize_function(subpgm.ctx->module, subpgm.func);
Eric Pouech's avatar
Eric Pouech committed
1677 1678

    return di->symt;
Raphael Junqueira's avatar
Raphael Junqueira committed
1679 1680
}

1681 1682 1683 1684 1685 1686 1687 1688 1689 1690
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));

1691
    if (!(ret_type = dwarf2_lookup_type(ctx, di)))
1692 1693 1694 1695
    {
        ret_type = ctx->symt_cache[sc_void];
        assert(ret_type);
    }
1696 1697 1698 1699 1700 1701 1702

    /* 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;
1703
        int    i;
1704

1705
        for (i=0; i<vector_length(&di->children); i++)
1706
        {
1707
            child = *(dwarf2_debug_info_t**)vector_at(&di->children, i);
1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724

            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
1725 1726 1727
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
1728
{
Eric Pouech's avatar
Eric Pouech committed
1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754
    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;
1755 1756 1757
    case DW_TAG_volatile_type:
        dwarf2_parse_volatile_type(ctx, di);
        break;
Eric Pouech's avatar
Eric Pouech committed
1758 1759 1760 1761 1762 1763 1764 1765 1766
    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;
1767 1768 1769 1770 1771 1772 1773 1774 1775 1776
    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;
1777 1778 1779
            subpgm.frame.kind = loc_absolute;
            subpgm.frame.offset = 0;
            subpgm.frame.reg = Wine_DW_no_register;
1780 1781 1782
            dwarf2_parse_variable(&subpgm, NULL, di);
        }
        break;
Raphael Junqueira's avatar
Raphael Junqueira committed
1783
    default:
1784 1785
        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
1786 1787 1788
    }
}

1789
static void dwarf2_set_line_number(struct module* module, unsigned long address,
1790
                                   const struct vector* v, unsigned file, unsigned line)
1791 1792
{
    struct symt_function*       func;
1793
    struct symt_ht*             symt;
1794 1795 1796 1797
    unsigned*                   psrc;

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

1798 1799
    TRACE("%s %lx %s %u\n",
          debugstr_w(module->module.ModuleName), address, source_get(module, *psrc), line);
1800 1801 1802
    if (!(symt = symt_find_nearest(module, address)) ||
        symt->symt.tag != SymTagFunction) return;
    func = (struct symt_function*)symt;
1803 1804 1805
    symt_add_func_line(module, func, *psrc, line, address - func->address);
}

1806
static BOOL dwarf2_parse_line_numbers(const dwarf2_section_t* sections,
1807
                                      dwarf2_parse_context_t* ctx,
1808
                                      const char* compile_dir,
1809 1810 1811 1812 1813 1814 1815 1816
                                      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;
1817 1818 1819
    struct vector               dirs;
    struct vector               files;
    const char**                p;
1820

1821
    /* section with line numbers stripped */
1822
    if (sections[section_line].address == ELF_NO_MAP)
1823
        return FALSE;
1824

1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836
    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);
1837
    line_base = (signed char)dwarf2_parse_byte(&traverse);
1838 1839 1840 1841
    line_range = dwarf2_parse_byte(&traverse);
    opcode_base = dwarf2_parse_byte(&traverse);

    opcode_len = traverse.data;
1842
    traverse.data += opcode_base - 1;
1843

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

        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;
        }

1868 1869
    }
    traverse.data++;
1870 1871

    vector_init(&files, sizeof(unsigned), 16);
1872 1873
    while (*traverse.data)
    {
1874 1875 1876 1877
        unsigned int    dir_index, mod_time, length;
        const char*     name;
        const char*     dir;
        unsigned*       psrc;
1878 1879 1880 1881 1882 1883

        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);
1884 1885 1886 1887
        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);
1888 1889 1890 1891 1892
    }
    traverse.data++;

    while (traverse.data < traverse.end_data)
    {
1893
        unsigned long address = 0;
1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911
        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;
1912
                dwarf2_set_line_number(ctx->module, address, &files, file, line);
1913 1914 1915 1916 1917 1918 1919
            }
            else
            {
                switch (opcode)
                {
                case DW_LNS_copy:
                    basic_block = FALSE;
1920
                    dwarf2_set_line_number(ctx->module, address, &files, file, line);
1921 1922 1923 1924 1925
                    break;
                case DW_LNS_advance_pc:
                    address += insn_size * dwarf2_leb128_as_unsigned(&traverse);
                    break;
                case DW_LNS_advance_line:
1926
                    line += dwarf2_leb128_as_signed(&traverse);
1927 1928
                    break;
                case DW_LNS_set_file:
1929
                    file = dwarf2_leb128_as_unsigned(&traverse);
1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951
                    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:
1952
                        dwarf2_set_line_number(ctx->module, address, &files, file, line);
1953 1954 1955
                        end_sequence = TRUE;
                        break;
                    case DW_LNE_set_address:
1956
                        address = ctx->load_offset + dwarf2_parse_addr(&traverse);
1957 1958
                        break;
                    case DW_LNE_define_file:
1959
                        FIXME("not handled %s\n", traverse.data);
1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978
                        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;
                }
            }
        }
    }
1979
    return TRUE;
1980 1981
}

1982 1983 1984
static BOOL dwarf2_parse_compilation_unit(const dwarf2_section_t* sections,
                                          const dwarf2_comp_unit_t* comp_unit,
                                          struct module* module,
Eric Pouech's avatar
Eric Pouech committed
1985
                                          const struct elf_thunk_area* thunks,
1986 1987
                                          const unsigned char* comp_unit_cursor,
                                          unsigned long load_offset)
1988 1989
{
    dwarf2_parse_context_t ctx;
1990 1991
    dwarf2_traverse_context_t traverse;
    dwarf2_traverse_context_t abbrev_ctx;
1992
    dwarf2_debug_info_t* di;
1993
    BOOL ret = FALSE;
1994

1995 1996 1997 1998 1999 2000
    TRACE("Compilation Unit Header found at 0x%x:\n",
          comp_unit_cursor - sections[section_debug].address);
    TRACE("- length:        %lu\n", comp_unit->length);
    TRACE("- version:       %u\n",  comp_unit->version);
    TRACE("- abbrev_offset: %lu\n", comp_unit->abbrev_offset);
    TRACE("- word_size:     %u\n",  comp_unit->word_size);
2001

2002 2003 2004 2005 2006 2007
    if (comp_unit->version != 2)
    {
        WARN("%u DWARF version unsupported. Wine dbghelp only support DWARF 2.\n",
             comp_unit->version);
        return FALSE;
    }
2008

2009
    pool_init(&ctx.pool, 65536);
2010 2011
    ctx.sections = sections;
    ctx.section = section_debug;
2012
    ctx.module = module;
2013
    ctx.word_size = comp_unit->word_size;
Eric Pouech's avatar
Eric Pouech committed
2014
    ctx.thunks = thunks;
2015
    ctx.load_offset = load_offset;
2016
    ctx.ref_offset = comp_unit_cursor - sections[section_debug].address;
2017 2018
    memset(ctx.symt_cache, 0, sizeof(ctx.symt_cache));
    ctx.symt_cache[sc_void] = &symt_new_basic(module, btVoid, "void", 0)->symt;
2019 2020 2021 2022 2023 2024 2025 2026 2027 2028

    traverse.start_data = comp_unit_cursor + sizeof(dwarf2_comp_unit_stream_t);
    traverse.data = traverse.start_data;
    traverse.word_size = comp_unit->word_size;
    traverse.end_data = comp_unit_cursor + comp_unit->length + sizeof(unsigned);

    abbrev_ctx.start_data = sections[section_abbrev].address + comp_unit->abbrev_offset;
    abbrev_ctx.data = abbrev_ctx.start_data;
    abbrev_ctx.end_data = sections[section_abbrev].address + sections[section_abbrev].size;
    abbrev_ctx.word_size = comp_unit->word_size;
2029
    dwarf2_parse_abbrev_set(&abbrev_ctx, &ctx.abbrev_table, &ctx.pool);
Raphael Junqueira's avatar
Raphael Junqueira committed
2030

2031
    sparse_array_init(&ctx.debug_info_table, sizeof(dwarf2_debug_info_t), 128);
2032
    dwarf2_read_one_debug_info(&ctx, &traverse, &di);
2033

Eric Pouech's avatar
Eric Pouech committed
2034 2035
    if (di->abbrev->tag == DW_TAG_compile_unit)
    {
2036
        struct attribute            name;
Eric Pouech's avatar
Eric Pouech committed
2037
        dwarf2_debug_info_t**       pdi = NULL;
2038
        struct attribute            stmt_list, low_pc;
2039
        struct attribute            comp_dir;
Eric Pouech's avatar
Eric Pouech committed
2040

2041 2042
        if (!dwarf2_find_attribute(&ctx, di, DW_AT_name, &name))
            name.u.string = NULL;
2043 2044 2045 2046 2047

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

2048 2049 2050
        if (!dwarf2_find_attribute(&ctx, di, DW_AT_low_pc, &low_pc))
            low_pc.u.uvalue = 0;
        di->symt = &symt_new_compiland(module, 
2051
                                       ctx.load_offset + low_pc.u.uvalue,
2052
                                       source_new(module, comp_dir.u.string, name.u.string))->symt;
Eric Pouech's avatar
Eric Pouech committed
2053 2054 2055

        if (di->abbrev->have_child)
        {
2056 2057
            int    i;
            for (i=0; i<vector_length(&di->children); i++)
Eric Pouech's avatar
Eric Pouech committed
2058
            {
2059
                pdi = vector_at(&di->children, i);
Eric Pouech's avatar
Eric Pouech committed
2060 2061 2062
                dwarf2_load_one_entry(&ctx, *pdi, (struct symt_compiland*)di->symt);
            }
        }
2063
        if (dwarf2_find_attribute(&ctx, di, DW_AT_stmt_list, &stmt_list))
2064
        {
2065 2066
            if (dwarf2_parse_line_numbers(sections, &ctx, comp_dir.u.string, stmt_list.u.uvalue))
                module->module.LineNumbers = TRUE;
2067
        }
2068
        ret = TRUE;
2069
    }
Eric Pouech's avatar
Eric Pouech committed
2070
    else FIXME("Should have a compilation unit here\n");
2071
    pool_destroy(&ctx.pool);
2072 2073 2074
    return ret;
}

2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102
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;
}

2103 2104
static enum location_error loc_compute_frame(struct process* pcs,
                                             const struct module* module,
2105 2106 2107 2108 2109 2110 2111
                                             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;
2112
    int                         i;
2113

2114
    for (i=0; i<vector_length(&func->vchildren); i++)
2115
    {
2116
        psym = vector_at(&func->vchildren, i);
2117 2118
        if ((*psym)->tag == SymTagCustom)
        {
2119
            pframe = &((struct symt_hierarchy_point*)*psym)->loc;
2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133

            /* 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;
2134
                if ((err = compute_location(&lctx, frame, pcs->handle, NULL)) < 0) return err;
2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151
                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;
}

2152 2153 2154 2155 2156
static void dwarf2_location_compute(struct process* pcs,
                                    const struct module* module,
                                    const struct symt_function* func,
                                    struct location* loc)
{
2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171
    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;

2172
        if ((err = loc_compute_frame(pcs, module, func, ip, &frame)) == 0)
2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194
        {
            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 */
2195
                err = compute_location(&lctx, loc, pcs->handle, &frame);
2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211
                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;
    }
2212 2213
}

2214
BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
Eric Pouech's avatar
Eric Pouech committed
2215
                  const struct elf_thunk_area* thunks,
2216 2217
		  const unsigned char* debug, unsigned int debug_size,
		  const unsigned char* abbrev, unsigned int abbrev_size,
2218
		  const unsigned char* str, unsigned int str_size,
2219 2220
		  const unsigned char* line, unsigned int line_size,
		  const unsigned char* loclist, unsigned int loclist_size)
2221 2222
{
    dwarf2_section_t    section[section_max];
2223
    unsigned char*      ptr;
2224 2225 2226
    const unsigned char*comp_unit_cursor = debug;
    const unsigned char*end_debug = debug + debug_size;

2227 2228
    module->loc_compute = dwarf2_location_compute;

2229 2230 2231 2232 2233 2234
    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;
2235 2236
    section[section_line].address = line;
    section[section_line].size = line_size;
2237

2238 2239 2240 2241 2242 2243 2244 2245
    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;
2246
        ptr = (unsigned char*)(module->dwarf2_info + 1);
2247 2248 2249 2250 2251
        memcpy(ptr, loclist, loclist_size);
        module->dwarf2_info->debug_loc.address = ptr;
        module->dwarf2_info->debug_loc.size    = loclist_size;
    }

2252 2253 2254 2255 2256 2257
    while (comp_unit_cursor < end_debug)
    {
        const dwarf2_comp_unit_stream_t* comp_unit_stream;
        dwarf2_comp_unit_t comp_unit;
    
        comp_unit_stream = (const dwarf2_comp_unit_stream_t*) comp_unit_cursor;
2258 2259 2260 2261
        comp_unit.length = *(const unsigned long*)  comp_unit_stream->length;
        comp_unit.version = *(const unsigned short*) comp_unit_stream->version;
        comp_unit.abbrev_offset = *(const unsigned long*) comp_unit_stream->abbrev_offset;
        comp_unit.word_size = *(const unsigned char*) comp_unit_stream->word_size;
2262

Eric Pouech's avatar
Eric Pouech committed
2263
        dwarf2_parse_compilation_unit(section, &comp_unit, module,
2264
                                      thunks, comp_unit_cursor, load_offset);
2265 2266 2267
        comp_unit_cursor += comp_unit.length + sizeof(unsigned);
    }
    module->module.SymType = SymDia;
Eric Pouech's avatar
Eric Pouech committed
2268 2269 2270 2271 2272 2273
    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;
2274
    return TRUE;
2275
}