ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dwarf.c
Go to the documentation of this file.
00001 /*
00002  * File dwarf.c - read dwarf2 information from the ELF modules
00003  *
00004  * Copyright (C) 2005, Raphael Junqueira
00005  * Copyright (C) 2006-2011, Eric Pouech
00006  * Copyright (C) 2010, Alexandre Julliard
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00021  */
00022 
00023 #define NONAMELESSUNION
00024 
00025 #include "config.h"
00026 
00027 #include <sys/types.h>
00028 #include <fcntl.h>
00029 #ifdef HAVE_SYS_STAT_H
00030 # include <sys/stat.h>
00031 #endif
00032 #ifdef HAVE_SYS_MMAN_H
00033 #include <sys/mman.h>
00034 #endif
00035 #include <limits.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #ifdef HAVE_UNISTD_H
00039 # include <unistd.h>
00040 #endif
00041 #include <stdio.h>
00042 #include <assert.h>
00043 #include <stdarg.h>
00044 
00045 #include "windef.h"
00046 #include "winbase.h"
00047 #include "winuser.h"
00048 #include "ole2.h"
00049 #include "oleauto.h"
00050 
00051 #include "dbghelp_private.h"
00052 #include "image_private.h"
00053 
00054 #include "wine/debug.h"
00055 
00056 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_dwarf);
00057 
00058 /* FIXME:
00059  * - Functions:
00060  *      o unspecified parameters
00061  *      o inlined functions
00062  *      o Debug{Start|End}Point
00063  *      o CFA
00064  * - Udt
00065  *      o proper types loading (nesting)
00066  */
00067 
00068 #if 0
00069 static void dump(const void* ptr, unsigned len)
00070 {
00071     int         i, j;
00072     BYTE        msg[128];
00073     static const char hexof[] = "0123456789abcdef";
00074     const       BYTE* x = ptr;
00075 
00076     for (i = 0; i < len; i += 16)
00077     {
00078         sprintf(msg, "%08x: ", i);
00079         memset(msg + 10, ' ', 3 * 16 + 1 + 16);
00080         for (j = 0; j < min(16, len - i); j++)
00081         {
00082             msg[10 + 3 * j + 0] = hexof[x[i + j] >> 4];
00083             msg[10 + 3 * j + 1] = hexof[x[i + j] & 15];
00084             msg[10 + 3 * j + 2] = ' ';
00085             msg[10 + 3 * 16 + 1 + j] = (x[i + j] >= 0x20 && x[i + j] < 0x7f) ?
00086                 x[i + j] : '.';
00087         }
00088         msg[10 + 3 * 16] = ' ';
00089         msg[10 + 3 * 16 + 1 + 16] = '\0';
00090         TRACE("%s\n", msg);
00091     }
00092 }
00093 #endif
00094 
00107 #include "dwarf.h"
00108 
00113 typedef struct dwarf2_abbrev_entry_attr_s
00114 {
00115   unsigned long attribute;
00116   unsigned long form;
00117   struct dwarf2_abbrev_entry_attr_s* next;
00118 } dwarf2_abbrev_entry_attr_t;
00119 
00120 typedef struct dwarf2_abbrev_entry_s
00121 {
00122     unsigned long entry_code;
00123     unsigned long tag;
00124     unsigned char have_child;
00125     unsigned num_attr;
00126     dwarf2_abbrev_entry_attr_t* attrs;
00127 } dwarf2_abbrev_entry_t;
00128 
00129 struct dwarf2_block
00130 {
00131     unsigned                    size;
00132     const unsigned char*        ptr;
00133 };
00134 
00135 struct attribute
00136 {
00137     unsigned long               form;
00138     enum {attr_direct, attr_abstract_origin, attr_specification} gotten_from;
00139     union
00140     {
00141         unsigned long                   uvalue;
00142         ULONGLONG                       lluvalue;
00143         long                            svalue;
00144         const char*                     string;
00145         struct dwarf2_block             block;
00146     } u;
00147 };
00148 
00149 typedef struct dwarf2_debug_info_s
00150 {
00151     const dwarf2_abbrev_entry_t*abbrev;
00152     struct symt*                symt;
00153     const unsigned char**       data;
00154     struct vector               children;
00155     struct dwarf2_debug_info_s* parent;
00156 } dwarf2_debug_info_t;
00157 
00158 typedef struct dwarf2_section_s
00159 {
00160     const unsigned char*        address;
00161     unsigned                    size;
00162     DWORD_PTR                   rva;
00163 } dwarf2_section_t;
00164 
00165 enum dwarf2_sections {section_debug, section_string, section_abbrev, section_line, section_ranges, section_max};
00166 
00167 typedef struct dwarf2_traverse_context_s
00168 {
00169     const unsigned char*        data;
00170     const unsigned char*        end_data;
00171     unsigned char               word_size;
00172 } dwarf2_traverse_context_t;
00173 
00174 /* symt_cache indexes */
00175 #define sc_void 0
00176 #define sc_int1 1
00177 #define sc_int2 2
00178 #define sc_int4 3
00179 #define sc_num  4
00180 
00181 typedef struct dwarf2_parse_context_s
00182 {
00183     const dwarf2_section_t*     sections;
00184     unsigned                    section;
00185     struct pool                 pool;
00186     struct module*              module;
00187     struct symt_compiland*      compiland;
00188     const struct elf_thunk_area*thunks;
00189     struct sparse_array         abbrev_table;
00190     struct sparse_array         debug_info_table;
00191     unsigned long               load_offset;
00192     unsigned long               ref_offset;
00193     struct symt*                symt_cache[sc_num]; /* void, int1, int2, int4 */
00194     char*                       cpp_name;
00195 } dwarf2_parse_context_t;
00196 
00197 /* stored in the dbghelp's module internal structure for later reuse */
00198 struct dwarf2_module_info_s
00199 {
00200     dwarf2_section_t            debug_loc;
00201     dwarf2_section_t            debug_frame;
00202     dwarf2_section_t            eh_frame;
00203     unsigned char               word_size;
00204 };
00205 
00206 #define loc_dwarf2_location_list        (loc_user + 0)
00207 #define loc_dwarf2_block                (loc_user + 1)
00208 
00209 /* forward declarations */
00210 static struct symt* dwarf2_parse_enumeration_type(dwarf2_parse_context_t* ctx, dwarf2_debug_info_t* entry);
00211 
00212 static unsigned char dwarf2_get_byte(const unsigned char* ptr)
00213 {
00214     return *ptr;
00215 }
00216 
00217 static unsigned char dwarf2_parse_byte(dwarf2_traverse_context_t* ctx)
00218 {
00219     unsigned char uvalue = dwarf2_get_byte(ctx->data);
00220     ctx->data += 1;
00221     return uvalue;
00222 }
00223 
00224 static unsigned short dwarf2_get_u2(const unsigned char* ptr)
00225 {
00226     return *(const UINT16*)ptr;
00227 }
00228 
00229 static unsigned short dwarf2_parse_u2(dwarf2_traverse_context_t* ctx)
00230 {
00231     unsigned short uvalue = dwarf2_get_u2(ctx->data);
00232     ctx->data += 2;
00233     return uvalue;
00234 }
00235 
00236 static unsigned long dwarf2_get_u4(const unsigned char* ptr)
00237 {
00238     return *(const UINT32*)ptr;
00239 }
00240 
00241 static unsigned long dwarf2_parse_u4(dwarf2_traverse_context_t* ctx)
00242 {
00243     unsigned long uvalue = dwarf2_get_u4(ctx->data);
00244     ctx->data += 4;
00245     return uvalue;
00246 }
00247 
00248 static DWORD64 dwarf2_get_u8(const unsigned char* ptr)
00249 {
00250     return *(const UINT64*)ptr;
00251 }
00252 
00253 static DWORD64 dwarf2_parse_u8(dwarf2_traverse_context_t* ctx)
00254 {
00255     DWORD64 uvalue = dwarf2_get_u8(ctx->data);
00256     ctx->data += 8;
00257     return uvalue;
00258 }
00259 
00260 static unsigned long dwarf2_get_leb128_as_unsigned(const unsigned char* ptr, const unsigned char** end)
00261 {
00262     unsigned long ret = 0;
00263     unsigned char byte;
00264     unsigned shift = 0;
00265 
00266     do
00267     {
00268         byte = dwarf2_get_byte(ptr++);
00269         ret |= (byte & 0x7f) << shift;
00270         shift += 7;
00271     } while (byte & 0x80);
00272 
00273     if (end) *end = ptr;
00274     return ret;
00275 }
00276 
00277 static unsigned long dwarf2_leb128_as_unsigned(dwarf2_traverse_context_t* ctx)
00278 {
00279     unsigned long ret;
00280 
00281     assert(ctx);
00282 
00283     ret = dwarf2_get_leb128_as_unsigned(ctx->data, &ctx->data);
00284 
00285     return ret;
00286 }
00287 
00288 static long dwarf2_get_leb128_as_signed(const unsigned char* ptr, const unsigned char** end)
00289 {
00290     long ret = 0;
00291     unsigned char byte;
00292     unsigned shift = 0;
00293     const unsigned size = sizeof(int) * 8;
00294 
00295     do
00296     {
00297         byte = dwarf2_get_byte(ptr++);
00298         ret |= (byte & 0x7f) << shift;
00299         shift += 7;
00300     } while (byte & 0x80);
00301     if (end) *end = ptr;
00302 
00303     /* as spec: sign bit of byte is 2nd high order bit (80x40)
00304      *  -> 0x80 is used as flag.
00305      */
00306     if ((shift < size) && (byte & 0x40))
00307     {
00308         ret |= - (1 << shift);
00309     }
00310     return ret;
00311 }
00312 
00313 static long dwarf2_leb128_as_signed(dwarf2_traverse_context_t* ctx)
00314 {
00315     long ret = 0;
00316 
00317     assert(ctx);
00318 
00319     ret = dwarf2_get_leb128_as_signed(ctx->data, &ctx->data);
00320     return ret;
00321 }
00322 
00323 static unsigned dwarf2_leb128_length(const dwarf2_traverse_context_t* ctx)
00324 {
00325     unsigned    ret;
00326     for (ret = 0; ctx->data[ret] & 0x80; ret++);
00327     return ret + 1;
00328 }
00329 
00330 /******************************************************************
00331  *      dwarf2_get_addr
00332  *
00333  * Returns an address.
00334  * We assume that in all cases word size from Dwarf matches the size of
00335  * addresses in platform where the exec is compiled.
00336  */
00337 static unsigned long dwarf2_get_addr(const unsigned char* ptr, unsigned word_size)
00338 {
00339     unsigned long ret;
00340 
00341     switch (word_size)
00342     {
00343     case 4:
00344         ret = dwarf2_get_u4(ptr);
00345         break;
00346     case 8:
00347         ret = dwarf2_get_u8(ptr);
00348     break;
00349     default:
00350         FIXME("Unsupported Word Size %u\n", word_size);
00351         ret = 0;
00352     }
00353     return ret;
00354 }
00355 
00356 static unsigned long dwarf2_parse_addr(dwarf2_traverse_context_t* ctx)
00357 {
00358     unsigned long ret = dwarf2_get_addr(ctx->data, ctx->word_size);
00359     ctx->data += ctx->word_size;
00360     return ret;
00361 }
00362 
00363 static const char* dwarf2_debug_traverse_ctx(const dwarf2_traverse_context_t* ctx) 
00364 {
00365     return wine_dbg_sprintf("ctx(%p)", ctx->data); 
00366 }
00367 
00368 static const char* dwarf2_debug_ctx(const dwarf2_parse_context_t* ctx)
00369 {
00370     return wine_dbg_sprintf("ctx(%p,%s)",
00371                             ctx, debugstr_w(ctx->module->module.ModuleName));
00372 }
00373 
00374 static const char* dwarf2_debug_di(const dwarf2_debug_info_t* di)
00375 {
00376     return wine_dbg_sprintf("debug_info(abbrev:%p,symt:%p)",
00377                             di->abbrev, di->symt);
00378 }
00379 
00380 static dwarf2_abbrev_entry_t*
00381 dwarf2_abbrev_table_find_entry(const struct sparse_array* abbrev_table,
00382                                unsigned long entry_code)
00383 {
00384     assert( NULL != abbrev_table );
00385     return sparse_array_find(abbrev_table, entry_code);
00386 }
00387 
00388 static void dwarf2_parse_abbrev_set(dwarf2_traverse_context_t* abbrev_ctx, 
00389                                     struct sparse_array* abbrev_table,
00390                                     struct pool* pool)
00391 {
00392     unsigned long entry_code;
00393     dwarf2_abbrev_entry_t* abbrev_entry;
00394     dwarf2_abbrev_entry_attr_t* new = NULL;
00395     dwarf2_abbrev_entry_attr_t* last = NULL;
00396     unsigned long attribute;
00397     unsigned long form;
00398 
00399     assert( NULL != abbrev_ctx );
00400 
00401     TRACE("%s, end at %p\n",
00402           dwarf2_debug_traverse_ctx(abbrev_ctx), abbrev_ctx->end_data); 
00403 
00404     sparse_array_init(abbrev_table, sizeof(dwarf2_abbrev_entry_t), 32);
00405     while (abbrev_ctx->data < abbrev_ctx->end_data)
00406     {
00407         TRACE("now at %s\n", dwarf2_debug_traverse_ctx(abbrev_ctx)); 
00408         entry_code = dwarf2_leb128_as_unsigned(abbrev_ctx);
00409         TRACE("found entry_code %lu\n", entry_code);
00410         if (!entry_code)
00411         {
00412             TRACE("NULL entry code at %s\n", dwarf2_debug_traverse_ctx(abbrev_ctx)); 
00413             break;
00414         }
00415         abbrev_entry = sparse_array_add(abbrev_table, entry_code, pool);
00416         assert( NULL != abbrev_entry );
00417 
00418         abbrev_entry->entry_code = entry_code;
00419         abbrev_entry->tag        = dwarf2_leb128_as_unsigned(abbrev_ctx);
00420         abbrev_entry->have_child = dwarf2_parse_byte(abbrev_ctx);
00421         abbrev_entry->attrs      = NULL;
00422         abbrev_entry->num_attr   = 0;
00423 
00424         TRACE("table:(%p,#%u) entry_code(%lu) tag(0x%lx) have_child(%u) -> %p\n",
00425               abbrev_table, sparse_array_length(abbrev_table),
00426               entry_code, abbrev_entry->tag, abbrev_entry->have_child, abbrev_entry);
00427 
00428         last = NULL;
00429         while (1)
00430         {
00431             attribute = dwarf2_leb128_as_unsigned(abbrev_ctx);
00432             form = dwarf2_leb128_as_unsigned(abbrev_ctx);
00433             if (!attribute) break;
00434 
00435             new = pool_alloc(pool, sizeof(dwarf2_abbrev_entry_attr_t));
00436             assert(new);
00437 
00438             new->attribute = attribute;
00439             new->form      = form;
00440             new->next      = NULL;
00441             if (abbrev_entry->attrs)    last->next = new;
00442             else                        abbrev_entry->attrs = new;
00443             last = new;
00444             abbrev_entry->num_attr++;
00445         }
00446     }
00447     TRACE("found %u entries\n", sparse_array_length(abbrev_table));
00448 }
00449 
00450 static void dwarf2_swallow_attribute(dwarf2_traverse_context_t* ctx,
00451                                      const dwarf2_abbrev_entry_attr_t* abbrev_attr)
00452 {
00453     unsigned    step;
00454 
00455     TRACE("(attr:0x%lx,form:0x%lx)\n", abbrev_attr->attribute, abbrev_attr->form);
00456 
00457     switch (abbrev_attr->form)
00458     {
00459     case DW_FORM_ref_addr:
00460     case DW_FORM_addr:   step = ctx->word_size; break;
00461     case DW_FORM_flag:
00462     case DW_FORM_data1:
00463     case DW_FORM_ref1:   step = 1; break;
00464     case DW_FORM_data2:
00465     case DW_FORM_ref2:   step = 2; break;
00466     case DW_FORM_data4:
00467     case DW_FORM_ref4:
00468     case DW_FORM_strp:   step = 4; break;
00469     case DW_FORM_data8:
00470     case DW_FORM_ref8:   step = 8; break;
00471     case DW_FORM_sdata:
00472     case DW_FORM_ref_udata:
00473     case DW_FORM_udata:  step = dwarf2_leb128_length(ctx); break;
00474     case DW_FORM_string: step = strlen((const char*)ctx->data) + 1; break;
00475     case DW_FORM_block:  step = dwarf2_leb128_as_unsigned(ctx); break;
00476     case DW_FORM_block1: step = dwarf2_parse_byte(ctx); break;
00477     case DW_FORM_block2: step = dwarf2_parse_u2(ctx); break;
00478     case DW_FORM_block4: step = dwarf2_parse_u4(ctx); break;
00479     default:
00480         FIXME("Unhandled attribute form %lx\n", abbrev_attr->form);
00481         return;
00482     }
00483     ctx->data += step;
00484 }
00485 
00486 static void dwarf2_fill_attr(const dwarf2_parse_context_t* ctx,
00487                              const dwarf2_abbrev_entry_attr_t* abbrev_attr,
00488                              const unsigned char* data,
00489                              struct attribute* attr)
00490 {
00491     attr->form = abbrev_attr->form;
00492     switch (attr->form)
00493     {
00494     case DW_FORM_ref_addr:
00495     case DW_FORM_addr:
00496         attr->u.uvalue = dwarf2_get_addr(data,
00497                                          ctx->module->format_info[DFI_DWARF]->u.dwarf2_info->word_size);
00498         TRACE("addr<0x%lx>\n", attr->u.uvalue);
00499         break;
00500 
00501     case DW_FORM_flag:
00502         attr->u.uvalue = dwarf2_get_byte(data);
00503         TRACE("flag<0x%lx>\n", attr->u.uvalue);
00504         break;
00505 
00506     case DW_FORM_data1:
00507         attr->u.uvalue = dwarf2_get_byte(data);
00508         TRACE("data1<%lu>\n", attr->u.uvalue);
00509         break;
00510 
00511     case DW_FORM_data2:
00512         attr->u.uvalue = dwarf2_get_u2(data);
00513         TRACE("data2<%lu>\n", attr->u.uvalue);
00514         break;
00515 
00516     case DW_FORM_data4:
00517         attr->u.uvalue = dwarf2_get_u4(data);
00518         TRACE("data4<%lu>\n", attr->u.uvalue);
00519         break;
00520 
00521     case DW_FORM_data8:
00522         attr->u.lluvalue = dwarf2_get_u8(data);
00523         TRACE("data8<%s>\n", wine_dbgstr_longlong(attr->u.uvalue));
00524         break;
00525 
00526     case DW_FORM_ref1:
00527         attr->u.uvalue = ctx->ref_offset + dwarf2_get_byte(data);
00528         TRACE("ref1<0x%lx>\n", attr->u.uvalue);
00529         break;
00530 
00531     case DW_FORM_ref2:
00532         attr->u.uvalue = ctx->ref_offset + dwarf2_get_u2(data);
00533         TRACE("ref2<0x%lx>\n", attr->u.uvalue);
00534         break;
00535 
00536     case DW_FORM_ref4:
00537         attr->u.uvalue = ctx->ref_offset + dwarf2_get_u4(data);
00538         TRACE("ref4<0x%lx>\n", attr->u.uvalue);
00539         break;
00540     
00541     case DW_FORM_ref8:
00542         FIXME("Unhandled 64 bit support\n");
00543         break;
00544 
00545     case DW_FORM_sdata:
00546         attr->u.svalue = dwarf2_get_leb128_as_signed(data, NULL);
00547         break;
00548 
00549     case DW_FORM_ref_udata:
00550         attr->u.uvalue = dwarf2_get_leb128_as_unsigned(data, NULL);
00551         break;
00552 
00553     case DW_FORM_udata:
00554         attr->u.uvalue = dwarf2_get_leb128_as_unsigned(data, NULL);
00555         break;
00556 
00557     case DW_FORM_string:
00558         attr->u.string = (const char *)data;
00559         TRACE("string<%s>\n", attr->u.string);
00560         break;
00561 
00562     case DW_FORM_strp:
00563     {
00564         unsigned long offset = dwarf2_get_u4(data);
00565         attr->u.string = (const char*)ctx->sections[section_string].address + offset;
00566     }
00567     TRACE("strp<%s>\n", attr->u.string);
00568     break;
00569         
00570     case DW_FORM_block:
00571         attr->u.block.size = dwarf2_get_leb128_as_unsigned(data, &attr->u.block.ptr);
00572         break;
00573 
00574     case DW_FORM_block1:
00575         attr->u.block.size = dwarf2_get_byte(data);
00576         attr->u.block.ptr  = data + 1;
00577         break;
00578 
00579     case DW_FORM_block2:
00580         attr->u.block.size = dwarf2_get_u2(data);
00581         attr->u.block.ptr  = data + 2;
00582         break;
00583 
00584     case DW_FORM_block4:
00585         attr->u.block.size = dwarf2_get_u4(data);
00586         attr->u.block.ptr  = data + 4;
00587         break;
00588 
00589     default:
00590         FIXME("Unhandled attribute form %lx\n", abbrev_attr->form);
00591         break;
00592     }
00593 }
00594 
00595 static BOOL dwarf2_find_attribute(const dwarf2_parse_context_t* ctx,
00596                                   const dwarf2_debug_info_t* di,
00597                                   unsigned at, struct attribute* attr)
00598 {
00599     unsigned                    i, refidx = 0;
00600     dwarf2_abbrev_entry_attr_t* abbrev_attr;
00601     dwarf2_abbrev_entry_attr_t* ref_abbrev_attr = NULL;
00602 
00603     attr->gotten_from = attr_direct;
00604     while (di)
00605     {
00606         ref_abbrev_attr = NULL;
00607         for (i = 0, abbrev_attr = di->abbrev->attrs; abbrev_attr; i++, abbrev_attr = abbrev_attr->next)
00608         {
00609             if (abbrev_attr->attribute == at)
00610             {
00611                 dwarf2_fill_attr(ctx, abbrev_attr, di->data[i], attr);
00612                 return TRUE;
00613             }
00614             if ((abbrev_attr->attribute == DW_AT_abstract_origin ||
00615                  abbrev_attr->attribute == DW_AT_specification) &&
00616                 at != DW_AT_sibling)
00617             {
00618                 if (ref_abbrev_attr)
00619                     FIXME("two references %lx and %lx\n", ref_abbrev_attr->attribute, abbrev_attr->attribute);
00620                 ref_abbrev_attr = abbrev_attr;
00621                 refidx = i;
00622                 attr->gotten_from = (abbrev_attr->attribute == DW_AT_abstract_origin) ?
00623                     attr_abstract_origin : attr_specification;
00624             }
00625         }
00626         /* do we have either an abstract origin or a specification debug entry to look into ? */
00627         if (!ref_abbrev_attr) break;
00628         dwarf2_fill_attr(ctx, ref_abbrev_attr, di->data[refidx], attr);
00629         if (!(di = sparse_array_find(&ctx->debug_info_table, attr->u.uvalue)))
00630             FIXME("Should have found the debug info entry\n");
00631     }
00632     return FALSE;
00633 }
00634 
00635 static void dwarf2_load_one_entry(dwarf2_parse_context_t*, dwarf2_debug_info_t*);
00636 
00637 #define Wine_DW_no_register     0x7FFFFFFF
00638 
00639 static unsigned dwarf2_map_register(int regno)
00640 {
00641     if (regno == Wine_DW_no_register)
00642     {
00643         FIXME("What the heck map reg 0x%x\n",regno);
00644         return 0;
00645     }
00646     return dbghelp_current_cpu->map_dwarf_register(regno);
00647 }
00648 
00649 static enum location_error
00650 compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
00651                  HANDLE hproc, const struct location* frame)
00652 {
00653     DWORD_PTR tmp, stack[64];
00654     unsigned stk;
00655     unsigned char op;
00656     BOOL piece_found = FALSE;
00657 
00658     stack[stk = 0] = 0;
00659 
00660     loc->kind = loc_absolute;
00661     loc->reg = Wine_DW_no_register;
00662 
00663     while (ctx->data < ctx->end_data)
00664     {
00665         op = dwarf2_parse_byte(ctx);
00666 
00667         if (op >= DW_OP_lit0 && op <= DW_OP_lit31)
00668             stack[++stk] = op - DW_OP_lit0;
00669         else if (op >= DW_OP_reg0 && op <= DW_OP_reg31)
00670         {
00671             /* dbghelp APIs don't know how to cope with this anyway
00672              * (for example 'long long' stored in two registers)
00673              * FIXME: We should tell winedbg how to deal with it (sigh)
00674              */
00675             if (!piece_found)
00676             {
00677                 DWORD   cvreg = dwarf2_map_register(op - DW_OP_reg0);
00678                 if (loc->reg != Wine_DW_no_register)
00679                     FIXME("Only supporting one reg (%s/%d -> %s/%d)\n",
00680                           dbghelp_current_cpu->fetch_regname(loc->reg), loc->reg,
00681                           dbghelp_current_cpu->fetch_regname(cvreg), cvreg);
00682                 loc->reg = cvreg;
00683             }
00684             loc->kind = loc_register;
00685         }
00686         else if (op >= DW_OP_breg0 && op <= DW_OP_breg31)
00687         {
00688             /* dbghelp APIs don't know how to cope with this anyway
00689              * (for example 'long long' stored in two registers)
00690              * FIXME: We should tell winedbg how to deal with it (sigh)
00691              */
00692             if (!piece_found)
00693             {
00694                 DWORD   cvreg = dwarf2_map_register(op - DW_OP_breg0);
00695                 if (loc->reg != Wine_DW_no_register)
00696                     FIXME("Only supporting one breg (%s/%d -> %s/%d)\n",
00697                           dbghelp_current_cpu->fetch_regname(loc->reg), loc->reg,
00698                           dbghelp_current_cpu->fetch_regname(cvreg), cvreg);
00699                 loc->reg = cvreg;
00700             }
00701             stack[++stk] = dwarf2_leb128_as_signed(ctx);
00702             loc->kind = loc_regrel;
00703         }
00704         else switch (op)
00705         {
00706         case DW_OP_nop:         break;
00707         case DW_OP_addr:        stack[++stk] = dwarf2_parse_addr(ctx); break;
00708         case DW_OP_const1u:     stack[++stk] = dwarf2_parse_byte(ctx); break;
00709         case DW_OP_const1s:     stack[++stk] = dwarf2_parse_byte(ctx); break;
00710         case DW_OP_const2u:     stack[++stk] = dwarf2_parse_u2(ctx); break;
00711         case DW_OP_const2s:     stack[++stk] = dwarf2_parse_u2(ctx); break;
00712         case DW_OP_const4u:     stack[++stk] = dwarf2_parse_u4(ctx); break;
00713         case DW_OP_const4s:     stack[++stk] = dwarf2_parse_u4(ctx); break;
00714         case DW_OP_const8u:     stack[++stk] = dwarf2_parse_u8(ctx); break;
00715         case DW_OP_const8s:     stack[++stk] = dwarf2_parse_u8(ctx); break;
00716         case DW_OP_constu:      stack[++stk] = dwarf2_leb128_as_unsigned(ctx); break;
00717         case DW_OP_consts:      stack[++stk] = dwarf2_leb128_as_signed(ctx); break;
00718         case DW_OP_dup:         stack[stk + 1] = stack[stk]; stk++; break;
00719         case DW_OP_drop:        stk--; break;
00720         case DW_OP_over:        stack[stk + 1] = stack[stk - 1]; stk++; break;
00721         case DW_OP_pick:        stack[stk + 1] = stack[stk - dwarf2_parse_byte(ctx)]; stk++; break;
00722         case DW_OP_swap:        tmp = stack[stk]; stack[stk] = stack[stk-1]; stack[stk-1] = tmp; break;
00723         case DW_OP_rot:         tmp = stack[stk]; stack[stk] = stack[stk-1]; stack[stk-1] = stack[stk-2]; stack[stk-2] = tmp; break;
00724         case DW_OP_abs:         stack[stk] = labs(stack[stk]); break;
00725         case DW_OP_neg:         stack[stk] = -stack[stk]; break;
00726         case DW_OP_not:         stack[stk] = ~stack[stk]; break;
00727         case DW_OP_and:         stack[stk-1] &= stack[stk]; stk--; break;
00728         case DW_OP_or:          stack[stk-1] |= stack[stk]; stk--; break;
00729         case DW_OP_minus:       stack[stk-1] -= stack[stk]; stk--; break;
00730         case DW_OP_mul:         stack[stk-1] *= stack[stk]; stk--; break;
00731         case DW_OP_plus:        stack[stk-1] += stack[stk]; stk--; break;
00732         case DW_OP_xor:         stack[stk-1] ^= stack[stk]; stk--; break;
00733         case DW_OP_shl:         stack[stk-1] <<= stack[stk]; stk--; break;
00734         case DW_OP_shr:         stack[stk-1] >>= stack[stk]; stk--; break;
00735         case DW_OP_plus_uconst: stack[stk] += dwarf2_leb128_as_unsigned(ctx); break;
00736         case DW_OP_shra:        stack[stk-1] = stack[stk-1] / (1 << stack[stk]); stk--; break;
00737         case DW_OP_div:         stack[stk-1] = stack[stk-1] / stack[stk]; stk--; break;
00738         case DW_OP_mod:         stack[stk-1] = stack[stk-1] % stack[stk]; stk--; break;
00739         case DW_OP_ge:          stack[stk-1] = (stack[stk-1] >= stack[stk]); stk--; break;
00740         case DW_OP_gt:          stack[stk-1] = (stack[stk-1] >  stack[stk]); stk--; break;
00741         case DW_OP_le:          stack[stk-1] = (stack[stk-1] <= stack[stk]); stk--; break;
00742         case DW_OP_lt:          stack[stk-1] = (stack[stk-1] <  stack[stk]); stk--; break;
00743         case DW_OP_eq:          stack[stk-1] = (stack[stk-1] == stack[stk]); stk--; break;
00744         case DW_OP_ne:          stack[stk-1] = (stack[stk-1] != stack[stk]); stk--; break;
00745         case DW_OP_skip:        tmp = dwarf2_parse_u2(ctx); ctx->data += tmp; break;
00746         case DW_OP_bra:         tmp = dwarf2_parse_u2(ctx); if (!stack[stk--]) ctx->data += tmp; break;
00747         case DW_OP_regx:
00748             tmp = dwarf2_leb128_as_unsigned(ctx);
00749             if (!piece_found)
00750             {
00751                 if (loc->reg != Wine_DW_no_register)
00752                     FIXME("Only supporting one reg\n");
00753                 loc->reg = dwarf2_map_register(tmp);
00754             }
00755             loc->kind = loc_register;
00756             break;
00757         case DW_OP_bregx:
00758             tmp = dwarf2_leb128_as_unsigned(ctx);
00759             if (loc->reg != Wine_DW_no_register)
00760                 FIXME("Only supporting one regx\n");
00761             loc->reg = dwarf2_map_register(tmp);
00762             stack[++stk] = dwarf2_leb128_as_signed(ctx);
00763             loc->kind = loc_regrel;
00764             break;
00765         case DW_OP_fbreg:
00766             if (loc->reg != Wine_DW_no_register)
00767                 FIXME("Only supporting one reg (%s/%d -> -2)\n",
00768                       dbghelp_current_cpu->fetch_regname(loc->reg), loc->reg);
00769             if (frame && frame->kind == loc_register)
00770             {
00771                 loc->kind = loc_regrel;
00772                 loc->reg = frame->reg;
00773                 stack[++stk] = dwarf2_leb128_as_signed(ctx);
00774             }
00775             else if (frame && frame->kind == loc_regrel)
00776             {
00777                 loc->kind = loc_regrel;
00778                 loc->reg = frame->reg;
00779                 stack[++stk] = dwarf2_leb128_as_signed(ctx) + frame->offset;
00780             }
00781             else
00782             {
00783                 /* FIXME: this could be later optimized by not recomputing
00784                  * this very location expression
00785                  */
00786                 loc->kind = loc_dwarf2_block;
00787                 stack[++stk] = dwarf2_leb128_as_signed(ctx);
00788             }
00789             break;
00790         case DW_OP_piece:
00791             {
00792                 unsigned sz = dwarf2_leb128_as_unsigned(ctx);
00793                 WARN("Not handling OP_piece (size=%d)\n", sz);
00794                 piece_found = TRUE;
00795             }
00796             break;
00797         case DW_OP_deref:
00798             if (!stk)
00799             {
00800                 FIXME("Unexpected empty stack\n");
00801                 return loc_err_internal;
00802             }
00803             if (loc->reg != Wine_DW_no_register)
00804             {
00805                 WARN("Too complex expression for deref\n");
00806                 return loc_err_too_complex;
00807             }
00808             if (hproc)
00809             {
00810                 DWORD_PTR addr = stack[stk--];
00811                 DWORD_PTR deref;
00812 
00813                 if (!ReadProcessMemory(hproc, (void*)addr, &deref, sizeof(deref), NULL))
00814                 {
00815                     WARN("Couldn't read memory at %lx\n", addr);
00816                     return loc_err_cant_read;
00817                 }
00818                 stack[++stk] = deref;
00819             }
00820             else
00821             {
00822                loc->kind = loc_dwarf2_block;
00823             }
00824             break;
00825         case DW_OP_deref_size:
00826             if (!stk)
00827             {
00828                 FIXME("Unexpected empty stack\n");
00829                 return loc_err_internal;
00830             }
00831             if (loc->reg != Wine_DW_no_register)
00832             {
00833                 WARN("Too complex expression for deref\n");
00834                 return loc_err_too_complex;
00835             }
00836             if (hproc)
00837             {
00838                 DWORD_PTR addr = stack[stk--];
00839                 BYTE derefsize = dwarf2_parse_byte(ctx);
00840                 DWORD64 deref;
00841 
00842                 if (!ReadProcessMemory(hproc, (void*)addr, &deref, derefsize, NULL))
00843                 {
00844                     WARN("Couldn't read memory at %lx\n", addr);
00845                        return loc_err_cant_read;
00846                 }
00847 
00848                 switch (derefsize)
00849                 {
00850                    case 1: stack[++stk] = *(unsigned char*)&deref; break;
00851                    case 2: stack[++stk] = *(unsigned short*)&deref; break;
00852                    case 4: stack[++stk] = *(DWORD*)&deref; break;
00853                    case 8: if (ctx->word_size >= derefsize) stack[++stk] = deref; break;
00854                 }
00855             }
00856             else
00857             {
00858                 dwarf2_parse_byte(ctx);
00859                 loc->kind = loc_dwarf2_block;
00860             }
00861             break;
00862         case DW_OP_stack_value:
00863             /* Expected behaviour is that this is the last instruction of this
00864              * expression and just the "top of stack" value should be put to loc->offset. */
00865             break;
00866         default:
00867             if (op < DW_OP_lo_user) /* as DW_OP_hi_user is 0xFF, we don't need to test against it */
00868                 FIXME("Unhandled attr op: %x\n", op);
00869             /* FIXME else unhandled extension */
00870             return loc_err_internal;
00871         }
00872     }
00873     loc->offset = stack[stk];
00874     return 0;
00875 }
00876 
00877 static BOOL dwarf2_compute_location_attr(dwarf2_parse_context_t* ctx,
00878                                          const dwarf2_debug_info_t* di,
00879                                          unsigned long dw,
00880                                          struct location* loc,
00881                                          const struct location* frame)
00882 {
00883     struct attribute xloc;
00884 
00885     if (!dwarf2_find_attribute(ctx, di, dw, &xloc)) return FALSE;
00886 
00887     switch (xloc.form)
00888     {
00889     case DW_FORM_data1: case DW_FORM_data2:
00890     case DW_FORM_udata: case DW_FORM_sdata:
00891         loc->kind = loc_absolute;
00892         loc->reg = 0;
00893         loc->offset = xloc.u.uvalue;
00894         return TRUE;
00895     case DW_FORM_data4: case DW_FORM_data8:
00896         loc->kind = loc_dwarf2_location_list;
00897         loc->reg = Wine_DW_no_register;
00898         loc->offset = xloc.u.uvalue;
00899         return TRUE;
00900     case DW_FORM_block:
00901     case DW_FORM_block1:
00902     case DW_FORM_block2:
00903     case DW_FORM_block4:
00904         break;
00905     default: FIXME("Unsupported yet form %lx\n", xloc.form);
00906         return FALSE;
00907     }
00908 
00909     /* assume we have a block form */
00910 
00911     if (xloc.u.block.size)
00912     {
00913         dwarf2_traverse_context_t       lctx;
00914         enum location_error             err;
00915 
00916         lctx.data = xloc.u.block.ptr;
00917         lctx.end_data = xloc.u.block.ptr + xloc.u.block.size;
00918         lctx.word_size = ctx->module->format_info[DFI_DWARF]->u.dwarf2_info->word_size;
00919 
00920         err = compute_location(&lctx, loc, NULL, frame);
00921         if (err < 0)
00922         {
00923             loc->kind = loc_error;
00924             loc->reg = err;
00925         }
00926         else if (loc->kind == loc_dwarf2_block)
00927         {
00928             unsigned*   ptr = pool_alloc(&ctx->module->pool,
00929                                          sizeof(unsigned) + xloc.u.block.size);
00930             *ptr = xloc.u.block.size;
00931             memcpy(ptr + 1, xloc.u.block.ptr, xloc.u.block.size);
00932             loc->offset = (unsigned long)ptr;
00933         }
00934     }
00935     return TRUE;
00936 }
00937 
00938 static struct symt* dwarf2_lookup_type(dwarf2_parse_context_t* ctx,
00939                                        const dwarf2_debug_info_t* di)
00940 {
00941     struct attribute attr;
00942     dwarf2_debug_info_t* type;
00943 
00944     if (!dwarf2_find_attribute(ctx, di, DW_AT_type, &attr))
00945         return NULL;
00946     if (!(type = sparse_array_find(&ctx->debug_info_table, attr.u.uvalue)))
00947     {
00948         FIXME("Unable to find back reference to type %lx\n", attr.u.uvalue);
00949         return NULL;
00950     }
00951     if (!type->symt)
00952     {
00953         /* load the debug info entity */
00954         dwarf2_load_one_entry(ctx, type);
00955         if (!type->symt)
00956             FIXME("Unable to load forward reference for tag %lx\n", type->abbrev->tag);
00957     }
00958     return type->symt;
00959 }
00960 
00961 static const char* dwarf2_get_cpp_name(dwarf2_parse_context_t* ctx, dwarf2_debug_info_t* di, const char* name)
00962 {
00963     char* last;
00964     struct attribute diname;
00965     struct attribute spec;
00966 
00967     if (di->abbrev->tag == DW_TAG_compile_unit) return name;
00968     if (!ctx->cpp_name)
00969         ctx->cpp_name = pool_alloc(&ctx->pool, MAX_SYM_NAME);
00970     last = ctx->cpp_name + MAX_SYM_NAME - strlen(name) - 1;
00971     strcpy(last, name);
00972 
00973     /* if the di is a definition, but has also a (previous) declaration, then scope must
00974      * be gotten from declaration not definition
00975      */
00976     if (dwarf2_find_attribute(ctx, di, DW_AT_specification, &spec) && spec.gotten_from == attr_direct)
00977     {
00978         di = sparse_array_find(&ctx->debug_info_table, spec.u.uvalue);
00979         if (!di)
00980         {
00981             FIXME("Should have found the debug info entry\n");
00982             return NULL;
00983         }
00984     }
00985 
00986     for (di = di->parent; di; di = di->parent)
00987     {
00988         switch (di->abbrev->tag)
00989         {
00990         case DW_TAG_namespace:
00991         case DW_TAG_structure_type:
00992         case DW_TAG_class_type:
00993         case DW_TAG_interface_type:
00994         case DW_TAG_union_type:
00995             if (dwarf2_find_attribute(ctx, di, DW_AT_name, &diname))
00996             {
00997                 size_t  len = strlen(diname.u.string);
00998                 last -= 2 + len;
00999                 if (last < ctx->cpp_name) return NULL;
01000                 memcpy(last, diname.u.string, len);
01001                 last[len] = last[len + 1] = ':';
01002             }
01003             break;
01004         default:
01005             break;
01006         }
01007     }
01008     return last;
01009 }
01010 
01011 /******************************************************************
01012  *      dwarf2_read_range
01013  *
01014  * read a range for a given debug_info (either using AT_range attribute, in which
01015  * case we don't return all the details, or using AT_low_pc & AT_high_pc attributes)
01016  * in all cases, range is relative to beginning of compilation unit
01017  */
01018 static BOOL dwarf2_read_range(dwarf2_parse_context_t* ctx, const dwarf2_debug_info_t* di,
01019                               unsigned long* plow, unsigned long* phigh)
01020 {
01021     struct attribute            range;
01022 
01023     if (dwarf2_find_attribute(ctx, di, DW_AT_ranges, &range))
01024     {
01025         dwarf2_traverse_context_t   traverse;
01026         unsigned long               low, high;
01027 
01028         traverse.data = ctx->sections[section_ranges].address + range.u.uvalue;
01029         traverse.end_data = ctx->sections[section_ranges].address +
01030             ctx->sections[section_ranges].size;
01031         traverse.word_size = ctx->module->format_info[DFI_DWARF]->u.dwarf2_info->word_size;
01032 
01033         *plow  = ULONG_MAX;
01034         *phigh = 0;
01035         while (traverse.data + 2 * traverse.word_size < traverse.end_data)
01036         {
01037             low = dwarf2_parse_addr(&traverse);
01038             high = dwarf2_parse_addr(&traverse);
01039             if (low == 0 && high == 0) break;
01040             if (low == ULONG_MAX) FIXME("unsupported yet (base address selection)\n");
01041             if (low  < *plow)  *plow = low;
01042             if (high > *phigh) *phigh = high;
01043         }
01044         if (*plow == ULONG_MAX || *phigh == 0) {FIXME("no entry found\n"); return FALSE;}
01045         if (*plow == *phigh) {FIXME("entry found, but low=high\n"); return FALSE;}
01046 
01047         return TRUE;
01048     }
01049     else
01050     {
01051         struct attribute            low_pc;
01052         struct attribute            high_pc;
01053 
01054         if (!dwarf2_find_attribute(ctx, di, DW_AT_low_pc, &low_pc) ||
01055             !dwarf2_find_attribute(ctx, di, DW_AT_high_pc, &high_pc))
01056             return FALSE;
01057         *plow = low_pc.u.uvalue;
01058         *phigh = high_pc.u.uvalue;
01059         return TRUE;
01060     }
01061 }
01062 
01063 /******************************************************************
01064  *      dwarf2_read_one_debug_info
01065  *
01066  * Loads into memory one debug info entry, and recursively its children (if any)
01067  */
01068 static BOOL dwarf2_read_one_debug_info(dwarf2_parse_context_t* ctx,
01069                                        dwarf2_traverse_context_t* traverse,
01070                                        dwarf2_debug_info_t* parent_di,
01071                                        dwarf2_debug_info_t** pdi)
01072 {
01073     const dwarf2_abbrev_entry_t*abbrev;
01074     unsigned long               entry_code;
01075     unsigned long               offset;
01076     dwarf2_debug_info_t*        di;
01077     dwarf2_debug_info_t*        child;
01078     dwarf2_debug_info_t**       where;
01079     dwarf2_abbrev_entry_attr_t* attr;
01080     unsigned                    i;
01081     struct attribute            sibling;
01082 
01083     offset = traverse->data - ctx->sections[ctx->section].address;
01084     entry_code = dwarf2_leb128_as_unsigned(traverse);
01085     TRACE("found entry_code %lu at 0x%lx\n", entry_code, offset);
01086     if (!entry_code)
01087     {
01088         *pdi = NULL;
01089         return TRUE;
01090     }
01091     abbrev = dwarf2_abbrev_table_find_entry(&ctx->abbrev_table, entry_code);
01092     if (!abbrev)
01093     {
01094     WARN("Cannot find abbrev entry for %lu at 0x%lx\n", entry_code, offset);
01095     return FALSE;
01096     }
01097     di = sparse_array_add(&ctx->debug_info_table, offset, &ctx->pool);
01098     if (!di) return FALSE;
01099     di->abbrev = abbrev;
01100     di->symt   = NULL;
01101     di->parent = parent_di;
01102 
01103     if (abbrev->num_attr)
01104     {
01105         di->data = pool_alloc(&ctx->pool, abbrev->num_attr * sizeof(const char*));
01106         for (i = 0, attr = abbrev->attrs; attr; i++, attr = attr->next)
01107         {
01108             di->data[i] = traverse->data;
01109             dwarf2_swallow_attribute(traverse, attr);
01110         }
01111     }
01112     else di->data = NULL;
01113     if (abbrev->have_child)
01114     {
01115         vector_init(&di->children, sizeof(dwarf2_debug_info_t*), 16);
01116         while (traverse->data < traverse->end_data)
01117         {
01118             if (!dwarf2_read_one_debug_info(ctx, traverse, di, &child)) return FALSE;
01119             if (!child) break;
01120             where = vector_add(&di->children, &ctx->pool);
01121             if (!where) return FALSE;
01122             *where = child;
01123         }
01124     }
01125     if (dwarf2_find_attribute(ctx, di, DW_AT_sibling, &sibling) &&
01126         traverse->data != ctx->sections[ctx->section].address + sibling.u.uvalue)
01127     {
01128         WARN("setting cursor for %s to next sibling <0x%lx>\n",
01129              dwarf2_debug_traverse_ctx(traverse), sibling.u.uvalue);
01130         traverse->data = ctx->sections[ctx->section].address + sibling.u.uvalue;
01131     }
01132     *pdi = di;
01133     return TRUE;
01134 }
01135 
01136 static struct vector* dwarf2_get_di_children(dwarf2_parse_context_t* ctx,
01137                                              dwarf2_debug_info_t* di)
01138 {
01139     struct attribute    spec;
01140 
01141     while (di)
01142     {
01143         if (di->abbrev->have_child)
01144             return &di->children;
01145         if (!dwarf2_find_attribute(ctx, di, DW_AT_specification, &spec)) break;
01146         if (!(di = sparse_array_find(&ctx->debug_info_table, spec.u.uvalue)))
01147             FIXME("Should have found the debug info entry\n");
01148     }
01149     return NULL;
01150 }
01151 
01152 static struct symt* dwarf2_parse_base_type(dwarf2_parse_context_t* ctx,
01153                                            dwarf2_debug_info_t* di)
01154 {
01155     struct attribute name;
01156     struct attribute size;
01157     struct attribute encoding;
01158     enum BasicType bt;
01159     int cache_idx = -1;
01160     if (di->symt) return di->symt;
01161 
01162     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); 
01163 
01164     if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name))
01165         name.u.string = NULL;
01166     if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &size)) size.u.uvalue = 0;
01167     if (!dwarf2_find_attribute(ctx, di, DW_AT_encoding, &encoding)) encoding.u.uvalue = DW_ATE_void;
01168 
01169     switch (encoding.u.uvalue)
01170     {
01171     case DW_ATE_void:           bt = btVoid; break;
01172     case DW_ATE_address:        bt = btULong; break;
01173     case DW_ATE_boolean:        bt = btBool; break;
01174     case DW_ATE_complex_float:  bt = btComplex; break;
01175     case DW_ATE_float:          bt = btFloat; break;
01176     case DW_ATE_signed:         bt = btInt; break;
01177     case DW_ATE_unsigned:       bt = btUInt; break;
01178     case DW_ATE_signed_char:    bt = btChar; break;
01179     case DW_ATE_unsigned_char:  bt = btChar; break;
01180     default:                    bt = btNoType; break;
01181     }
01182     di->symt = &symt_new_basic(ctx->module, bt, name.u.string, size.u.uvalue)->symt;
01183     switch (bt)
01184     {
01185     case btVoid:
01186         assert(size.u.uvalue == 0);
01187         cache_idx = sc_void;
01188         break;
01189     case btInt:
01190         switch (size.u.uvalue)
01191         {
01192         case 1: cache_idx = sc_int1; break;
01193         case 2: cache_idx = sc_int2; break;
01194         case 4: cache_idx = sc_int4; break;
01195         }
01196         break;
01197     default: break;
01198     }
01199     if (cache_idx != -1 && !ctx->symt_cache[cache_idx])
01200         ctx->symt_cache[cache_idx] = di->symt;
01201 
01202     if (dwarf2_get_di_children(ctx, di)) FIXME("Unsupported children\n");
01203     return di->symt;
01204 }
01205 
01206 static struct symt* dwarf2_parse_typedef(dwarf2_parse_context_t* ctx,
01207                                          dwarf2_debug_info_t* di)
01208 {
01209     struct symt*        ref_type;
01210     struct attribute    name;
01211 
01212     if (di->symt) return di->symt;
01213 
01214     TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), di->abbrev->entry_code); 
01215 
01216     if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) name.u.string = NULL;
01217     ref_type = dwarf2_lookup_type(ctx, di);
01218 
01219     if (name.u.string)
01220         di->symt = &symt_new_typedef(ctx->module, ref_type, name.u.string)->symt;
01221     if (dwarf2_get_di_children(ctx, di)) FIXME("Unsupported children\n");
01222     return di->symt;
01223 }
01224 
01225 static struct symt* dwarf2_parse_pointer_type(dwarf2_parse_context_t* ctx,
01226                                               dwarf2_debug_info_t* di)
01227 {
01228     struct symt*        ref_type;
01229     struct attribute    size;
01230 
01231     if (di->symt) return di->symt;
01232 
01233     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); 
01234 
01235     if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &size)) size.u.uvalue = sizeof(void *);
01236     if (!(ref_type = dwarf2_lookup_type(ctx, di)))
01237     {
01238         ref_type = ctx->symt_cache[sc_void];
01239         assert(ref_type);
01240     }
01241     di->symt = &symt_new_pointer(ctx->module, ref_type, size.u.uvalue)->symt;
01242     if (dwarf2_get_di_children(ctx, di)) FIXME("Unsupported children\n");
01243     return di->symt;
01244 }
01245 
01246 static struct symt* dwarf2_parse_array_type(dwarf2_parse_context_t* ctx,
01247                                             dwarf2_debug_info_t* di)
01248 {
01249     struct symt* ref_type;
01250     struct symt* idx_type = NULL;
01251     struct attribute min, max, cnt;
01252     dwarf2_debug_info_t* child;
01253     unsigned int i;
01254     const struct vector* children;
01255 
01256     if (di->symt) return di->symt;
01257 
01258     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
01259 
01260     ref_type = dwarf2_lookup_type(ctx, di);
01261 
01262     if (!(children = dwarf2_get_di_children(ctx, di)))
01263     {
01264         /* fake an array with unknown size */
01265         /* FIXME: int4 even on 64bit machines??? */
01266         idx_type = ctx->symt_cache[sc_int4];
01267         min.u.uvalue = 0;
01268         max.u.uvalue = -1;
01269     }
01270     else for (i = 0; i < vector_length(children); i++)
01271     {
01272         child = *(dwarf2_debug_info_t**)vector_at(children, i);
01273         switch (child->abbrev->tag)
01274         {
01275         case DW_TAG_subrange_type:
01276             idx_type = dwarf2_lookup_type(ctx, child);
01277             if (!dwarf2_find_attribute(ctx, child, DW_AT_lower_bound, &min))
01278                 min.u.uvalue = 0;
01279             if (!dwarf2_find_attribute(ctx, child, DW_AT_upper_bound, &max))
01280                 max.u.uvalue = 0;
01281             if (dwarf2_find_attribute(ctx, child, DW_AT_count, &cnt))
01282                 max.u.uvalue = min.u.uvalue + cnt.u.uvalue;
01283             break;
01284         default:
01285             FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
01286                   child->abbrev->tag, dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
01287             break;
01288         }
01289     }
01290     di->symt = &symt_new_array(ctx->module, min.u.uvalue, max.u.uvalue, ref_type, idx_type)->symt;
01291     return di->symt;
01292 }
01293 
01294 static struct symt* dwarf2_parse_const_type(dwarf2_parse_context_t* ctx,
01295                                             dwarf2_debug_info_t* di)
01296 {
01297     struct symt* ref_type;
01298 
01299     if (di->symt) return di->symt;
01300 
01301     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
01302 
01303     if (!(ref_type = dwarf2_lookup_type(ctx, di)))
01304     {
01305         ref_type = ctx->symt_cache[sc_void];
01306         assert(ref_type);
01307     }
01308     if (dwarf2_get_di_children(ctx, di)) FIXME("Unsupported children\n");
01309     di->symt = ref_type;
01310 
01311     return ref_type;
01312 }
01313 
01314 static struct symt* dwarf2_parse_volatile_type(dwarf2_parse_context_t* ctx,
01315                                                dwarf2_debug_info_t* di)
01316 {
01317     struct symt* ref_type;
01318 
01319     if (di->symt) return di->symt;
01320 
01321     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
01322 
01323     if (!(ref_type = dwarf2_lookup_type(ctx, di)))
01324     {
01325         ref_type = ctx->symt_cache[sc_void];
01326         assert(ref_type);
01327     }
01328     if (dwarf2_get_di_children(ctx, di)) FIXME("Unsupported children\n");
01329     di->symt = ref_type;
01330 
01331     return ref_type;
01332 }
01333 
01334 static struct symt* dwarf2_parse_reference_type(dwarf2_parse_context_t* ctx,
01335                                                 dwarf2_debug_info_t* di)
01336 {
01337     struct symt* ref_type = NULL;
01338 
01339     if (di->symt) return di->symt;
01340 
01341     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
01342 
01343     ref_type = dwarf2_lookup_type(ctx, di);
01344     /* FIXME: for now, we hard-wire C++ references to pointers */
01345     di->symt = &symt_new_pointer(ctx->module, ref_type, sizeof(void *))->symt;
01346 
01347     if (dwarf2_get_di_children(ctx, di)) FIXME("Unsupported children\n");
01348 
01349     return di->symt;
01350 }
01351 
01352 static void dwarf2_parse_udt_member(dwarf2_parse_context_t* ctx,
01353                                     dwarf2_debug_info_t* di,
01354                                     struct symt_udt* parent)
01355 {
01356     struct symt* elt_type;
01357     struct attribute name;
01358     struct attribute bit_size;
01359     struct attribute bit_offset;
01360     struct location  loc;
01361 
01362     assert(parent);
01363 
01364     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
01365 
01366     if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) name.u.string = NULL;
01367     elt_type = dwarf2_lookup_type(ctx, di);
01368     if (dwarf2_compute_location_attr(ctx, di, DW_AT_data_member_location, &loc, NULL))
01369     {
01370         if (loc.kind != loc_absolute)
01371         {
01372            FIXME("Found register, while not expecting it\n");
01373            loc.offset = 0;
01374         }
01375         else
01376             TRACE("found member_location at %s -> %lu\n",
01377                   dwarf2_debug_ctx(ctx), loc.offset);
01378     }
01379     else
01380         loc.offset = 0;
01381     if (!dwarf2_find_attribute(ctx, di, DW_AT_bit_size, &bit_size))
01382         bit_size.u.uvalue = 0;
01383     if (dwarf2_find_attribute(ctx, di, DW_AT_bit_offset, &bit_offset))
01384     {
01385         /* FIXME: we should only do this when implementation is LSB (which is
01386          * the case on i386 processors)
01387          */
01388         struct attribute nbytes;
01389         if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &nbytes))
01390         {
01391             DWORD64     size;
01392             nbytes.u.uvalue = symt_get_info(ctx->module, elt_type, TI_GET_LENGTH, &size) ?
01393                 (unsigned long)size : 0;
01394         }
01395         bit_offset.u.uvalue = nbytes.u.uvalue * 8 - bit_offset.u.uvalue - bit_size.u.uvalue;
01396     }
01397     else bit_offset.u.uvalue = 0;
01398     symt_add_udt_element(ctx->module, parent, name.u.string, elt_type,    
01399                          (loc.offset << 3) + bit_offset.u.uvalue,
01400                          bit_size.u.uvalue);
01401 
01402     if (dwarf2_get_di_children(ctx, di)) FIXME("Unsupported children\n");
01403 }
01404 
01405 static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
01406                                             dwarf2_debug_info_t* di);
01407 
01408 static struct symt* dwarf2_parse_udt_type(dwarf2_parse_context_t* ctx,
01409                                           dwarf2_debug_info_t* di,
01410                                           enum UdtKind udt)
01411 {
01412     struct attribute    name;
01413     struct attribute    size;
01414     struct vector*      children;
01415     dwarf2_debug_info_t*child;
01416     unsigned int        i;
01417 
01418     if (di->symt) return di->symt;
01419 
01420     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); 
01421 
01422     /* quirk... FIXME provide real support for anonymous UDTs */
01423     if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name))
01424         name.u.string = "zz_anon_zz";
01425     if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &size)) size.u.uvalue = 0;
01426 
01427     di->symt = &symt_new_udt(ctx->module, dwarf2_get_cpp_name(ctx, di, name.u.string),
01428                              size.u.uvalue, udt)->symt;
01429 
01430     children = dwarf2_get_di_children(ctx, di);
01431     if (children) for (i = 0; i < vector_length(children); i++)
01432     {
01433         child = *(dwarf2_debug_info_t**)vector_at(children, i);
01434 
01435         switch (child->abbrev->tag)
01436         {
01437         case DW_TAG_member:
01438             /* FIXME: should I follow the sibling stuff ?? */
01439             dwarf2_parse_udt_member(ctx, child, (struct symt_udt*)di->symt);
01440             break;
01441         case DW_TAG_enumeration_type:
01442             dwarf2_parse_enumeration_type(ctx, child);
01443             break;
01444         case DW_TAG_subprogram:
01445             dwarf2_parse_subprogram(ctx, child);
01446             break;
01447         case DW_TAG_structure_type:
01448         case DW_TAG_class_type:
01449         case DW_TAG_union_type:
01450         case DW_TAG_typedef:
01451             /* FIXME: we need to handle nested udt definitions */
01452         case DW_TAG_inheritance:
01453         case DW_TAG_template_type_param:
01454         case DW_TAG_template_value_param:
01455         case DW_TAG_variable:
01456         case DW_TAG_imported_declaration:
01457         case DW_TAG_ptr_to_member_type:
01458             /* FIXME: some C++ related stuff */
01459             break;
01460         default:
01461             FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
01462                   child->abbrev->tag, dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
01463             break;
01464         }
01465     }
01466 
01467     return di->symt;
01468 }
01469 
01470 static void dwarf2_parse_enumerator(dwarf2_parse_context_t* ctx,
01471                                     dwarf2_debug_info_t* di,
01472                                     struct symt_enum* parent)
01473 {
01474     struct attribute    name;
01475     struct attribute    value;
01476 
01477     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); 
01478 
01479     if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) return;
01480     if (!dwarf2_find_attribute(ctx, di, DW_AT_const_value, &value)) value.u.svalue = 0;
01481     symt_add_enum_element(ctx->module, parent, name.u.string, value.u.svalue);
01482 
01483     if (dwarf2_get_di_children(ctx, di)) FIXME("Unsupported children\n");
01484 }
01485 
01486 static struct symt* dwarf2_parse_enumeration_type(dwarf2_parse_context_t* ctx,
01487                                                   dwarf2_debug_info_t* di)
01488 {
01489     struct attribute    name;
01490     struct attribute    size;
01491     struct symt_basic*  basetype;
01492     struct vector*      children;
01493     dwarf2_debug_info_t*child;
01494     unsigned int        i;
01495 
01496     if (di->symt) return di->symt;
01497 
01498     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); 
01499 
01500     if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) name.u.string = NULL;
01501     if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &size)) size.u.uvalue = 4;
01502 
01503     switch (size.u.uvalue) /* FIXME: that's wrong */
01504     {
01505     case 1: basetype = symt_new_basic(ctx->module, btInt, "char", 1); break;
01506     case 2: basetype = symt_new_basic(ctx->module, btInt, "short", 2); break;
01507     default:
01508     case 4: basetype = symt_new_basic(ctx->module, btInt, "int", 4); break;
01509     }
01510 
01511     di->symt = &symt_new_enum(ctx->module, name.u.string, &basetype->symt)->symt;
01512 
01513     children = dwarf2_get_di_children(ctx, di);
01514     /* FIXME: should we use the sibling stuff ?? */
01515     if (children) for (i = 0; i < vector_length(children); i++)
01516     {
01517         child = *(dwarf2_debug_info_t**)vector_at(children, i);
01518 
01519         switch (child->abbrev->tag)
01520         {
01521         case DW_TAG_enumerator:
01522             dwarf2_parse_enumerator(ctx, child, (struct symt_enum*)di->symt);
01523             break;
01524         default:
01525             FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
01526                   di->abbrev->tag, dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
01527     }
01528     }
01529     return di->symt;
01530 }
01531 
01532 /* structure used to pass information around when parsing a subprogram */
01533 typedef struct dwarf2_subprogram_s
01534 {
01535     dwarf2_parse_context_t*     ctx;
01536     struct symt_function*       func;
01537     BOOL                        non_computed_variable;
01538     struct location             frame;
01539 } dwarf2_subprogram_t;
01540 
01541 /******************************************************************
01542  *      dwarf2_parse_variable
01543  *
01544  * Parses any variable (parameter, local/global variable)
01545  */
01546 static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm,
01547                                   struct symt_block* block,
01548                                   dwarf2_debug_info_t* di)
01549 {
01550     struct symt*        param_type;
01551     struct attribute    name, value;
01552     struct location     loc;
01553     BOOL                is_pmt;
01554 
01555     TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
01556 
01557     is_pmt = !block && di->abbrev->tag == DW_TAG_formal_parameter;
01558     param_type = dwarf2_lookup_type(subpgm->ctx, di);
01559         
01560     if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_name, &name)) {
01561     /* cannot do much without the name, the functions below won't like it. */
01562         return;
01563     }
01564     if (dwarf2_compute_location_attr(subpgm->ctx, di, DW_AT_location,
01565                                      &loc, &subpgm->frame))
01566     {
01567         struct attribute ext;
01568 
01569     TRACE("found parameter %s (kind=%d, offset=%ld, reg=%d) at %s\n",
01570               name.u.string, loc.kind, loc.offset, loc.reg,
01571               dwarf2_debug_ctx(subpgm->ctx));
01572 
01573         switch (loc.kind)
01574         {
01575         case loc_error:
01576             break;
01577         case loc_absolute:
01578             /* it's a global variable */
01579             /* FIXME: we don't handle its scope yet */
01580             if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_external, &ext))
01581                 ext.u.uvalue = 0;
01582             loc.offset += subpgm->ctx->load_offset;
01583             symt_new_global_variable(subpgm->ctx->module, subpgm->ctx->compiland,
01584                                      dwarf2_get_cpp_name(subpgm->ctx, di, name.u.string), !ext.u.uvalue,
01585                                      loc, 0, param_type);
01586             break;
01587         default:
01588             subpgm->non_computed_variable = TRUE;
01589             /* fall through */
01590         case loc_register:
01591         case loc_regrel:
01592             /* either a pmt/variable relative to frame pointer or
01593              * pmt/variable in a register
01594              */
01595             assert(subpgm->func);
01596             symt_add_func_local(subpgm->ctx->module, subpgm->func, 
01597                                 is_pmt ? DataIsParam : DataIsLocal,
01598                                 &loc, block, param_type, name.u.string);
01599             break;
01600         }
01601     }
01602     else if (dwarf2_find_attribute(subpgm->ctx, di, DW_AT_const_value, &value))
01603     {
01604         VARIANT v;
01605         if (subpgm->func) WARN("Unsupported constant %s in function\n", name.u.string);
01606         if (is_pmt)       FIXME("Unsupported constant (parameter) %s in function\n", name.u.string);
01607         switch (value.form)
01608         {
01609         case DW_FORM_data1:
01610         case DW_FORM_data2:
01611         case DW_FORM_data4:
01612         case DW_FORM_udata:
01613         case DW_FORM_addr:
01614             v.n1.n2.vt = VT_UI4;
01615             v.n1.n2.n3.lVal = value.u.uvalue;
01616             break;
01617 
01618         case DW_FORM_data8:
01619             v.n1.n2.vt = VT_UI8;
01620             v.n1.n2.n3.llVal = value.u.lluvalue;
01621             break;
01622 
01623         case DW_FORM_sdata:
01624             v.n1.n2.vt = VT_I4;
01625             v.n1.n2.n3.lVal = value.u.svalue;
01626             break;
01627 
01628         case DW_FORM_strp:
01629         case DW_FORM_string:
01630             /* FIXME: native doesn't report const strings from here !!
01631              * however, the value of the string is in the code somewhere
01632              */
01633             v.n1.n2.vt = VT_I1 | VT_BYREF;
01634             v.n1.n2.n3.byref = pool_strdup(&subpgm->ctx->module->pool, value.u.string);
01635             break;
01636 
01637         case DW_FORM_block:
01638         case DW_FORM_block1:
01639         case DW_FORM_block2:
01640         case DW_FORM_block4:
01641             v.n1.n2.vt = VT_I4;
01642             switch (value.u.block.size)
01643             {
01644             case 1:     v.n1.n2.n3.lVal = *(BYTE*)value.u.block.ptr;    break;
01645             case 2:     v.n1.n2.n3.lVal = *(USHORT*)value.u.block.ptr;  break;
01646             case 4:     v.n1.n2.n3.lVal = *(DWORD*)value.u.block.ptr;   break;
01647             default:
01648                 v.n1.n2.vt = VT_I1 | VT_BYREF;
01649                 v.n1.n2.n3.byref = pool_alloc(&subpgm->ctx->module->pool, value.u.block.size);
01650                 memcpy(v.n1.n2.n3.byref, value.u.block.ptr, value.u.block.size);
01651             }
01652             break;
01653 
01654         default:
01655             FIXME("Unsupported form for const value %s (%lx)\n",
01656                   name.u.string, value.form);
01657             v.n1.n2.vt = VT_EMPTY;
01658         }
01659         di->symt = &symt_new_constant(subpgm->ctx->module, subpgm->ctx->compiland,
01660                                       name.u.string, param_type, &v)->symt;
01661     }
01662     else
01663     {
01664         /* variable has been optimized away... report anyway */
01665         loc.kind = loc_error;
01666         loc.reg = loc_err_no_location;
01667         if (subpgm->func)
01668         {
01669             symt_add_func_local(subpgm->ctx->module, subpgm->func,
01670                                 is_pmt ? DataIsParam : DataIsLocal,
01671                                 &loc, block, param_type, name.u.string);
01672         }
01673         else
01674         {
01675             WARN("dropping global variable %s which has been optimized away\n", name.u.string);
01676         }
01677     }
01678     if (is_pmt && subpgm->func && subpgm->func->type)
01679         symt_add_function_signature_parameter(subpgm->ctx->module,
01680                                               (struct symt_function_signature*)subpgm->func->type,
01681                                               param_type);
01682 
01683     if (dwarf2_get_di_children(subpgm->ctx, di)) FIXME("Unsupported children\n");
01684 }
01685 
01686 static void dwarf2_parse_subprogram_label(dwarf2_subprogram_t* subpgm,
01687                                           const dwarf2_debug_info_t* di)
01688 {
01689     struct attribute    name;
01690     struct attribute    low_pc;
01691     struct location     loc;
01692 
01693     TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
01694 
01695     if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0;
01696     if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_name, &name))
01697         name.u.string = NULL;
01698 
01699     loc.kind = loc_absolute;
01700     loc.offset = subpgm->ctx->load_offset + low_pc.u.uvalue;
01701     symt_add_function_point(subpgm->ctx->module, subpgm->func, SymTagLabel,
01702                             &loc, name.u.string);
01703 }
01704 
01705 static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
01706                                           struct symt_block* parent_block,
01707                       dwarf2_debug_info_t* di);
01708 
01709 static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm,
01710                                             struct symt_block* parent_block,
01711                                             dwarf2_debug_info_t* di)
01712 {
01713     struct symt_block*  block;
01714     unsigned long       low_pc, high_pc;
01715     struct vector*      children;
01716     dwarf2_debug_info_t*child;
01717     unsigned int        i;
01718 
01719     TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
01720 
01721     if (!dwarf2_read_range(subpgm->ctx, di, &low_pc, &high_pc))
01722     {
01723         FIXME("cannot read range\n");
01724         return;
01725     }
01726 
01727     block = symt_open_func_block(subpgm->ctx->module, subpgm->func, parent_block,
01728                                  subpgm->ctx->load_offset + low_pc - subpgm->func->address,
01729                                  high_pc - low_pc);
01730 
01731     children = dwarf2_get_di_children(subpgm->ctx, di);
01732     if (children) for (i = 0; i < vector_length(children); i++)
01733     {
01734         child = *(dwarf2_debug_info_t**)vector_at(children, i);
01735 
01736         switch (child->abbrev->tag)
01737         {
01738         case DW_TAG_formal_parameter:
01739         case DW_TAG_variable:
01740             dwarf2_parse_variable(subpgm, block, child);
01741             break;
01742         case DW_TAG_lexical_block:
01743             dwarf2_parse_subprogram_block(subpgm, block, child);
01744             break;
01745         case DW_TAG_inlined_subroutine:
01746             dwarf2_parse_inlined_subroutine(subpgm, block, child);
01747             break;
01748         case DW_TAG_label:
01749             dwarf2_parse_subprogram_label(subpgm, child);
01750             break;
01751         case DW_TAG_GNU_call_site:
01752             /* this isn't properly supported by dbghelp interface. skip it for now */
01753             break;
01754         default:
01755             FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
01756                   child->abbrev->tag, dwarf2_debug_ctx(subpgm->ctx),
01757                   dwarf2_debug_di(di));
01758         }
01759     }
01760     symt_close_func_block(subpgm->ctx->module, subpgm->func, block, 0);
01761 }
01762 
01763 static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
01764                                           struct symt_block* parent_block,
01765                       dwarf2_debug_info_t* di)
01766 {
01767     struct symt_block*  block;
01768     unsigned long       low_pc, high_pc;
01769     struct vector*      children;
01770     dwarf2_debug_info_t*child;
01771     unsigned int        i;
01772 
01773     TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
01774 
01775     if (!dwarf2_read_range(subpgm->ctx, di, &low_pc, &high_pc))
01776     {
01777         FIXME("no range\n");
01778         return;
01779     }
01780 
01781     block = symt_open_func_block(subpgm->ctx->module, subpgm->func, parent_block,
01782                                  subpgm->ctx->load_offset + low_pc - subpgm->func->address,
01783                                  high_pc - low_pc);
01784 
01785     children = dwarf2_get_di_children(subpgm->ctx, di);
01786     if (children) for (i = 0; i < vector_length(children); i++)
01787     {
01788         child = *(dwarf2_debug_info_t**)vector_at(children, i);
01789 
01790         switch (child->abbrev->tag)
01791         {
01792         case DW_TAG_inlined_subroutine:
01793             dwarf2_parse_inlined_subroutine(subpgm, block, child);
01794             break;
01795         case DW_TAG_variable:
01796             dwarf2_parse_variable(subpgm, block, child);
01797             break;
01798         case DW_TAG_lexical_block:
01799             dwarf2_parse_subprogram_block(subpgm, block, child);
01800             break;
01801         case DW_TAG_subprogram:
01802             /* FIXME: likely a declaration (to be checked)
01803              * skip it for now
01804              */
01805             break;
01806         case DW_TAG_formal_parameter:
01807             /* FIXME: likely elements for exception handling (GCC flavor)
01808              * Skip it for now
01809              */
01810             break;
01811         case DW_TAG_imported_module:
01812             /* C++ stuff to be silenced (for now) */
01813             break;
01814         case DW_TAG_GNU_call_site:
01815             /* this isn't properly supported by dbghelp interface. skip it for now */
01816             break;
01817         case DW_TAG_label:
01818             dwarf2_parse_subprogram_label(subpgm, child);
01819             break;
01820         case DW_TAG_class_type:
01821         case DW_TAG_structure_type:
01822         case DW_TAG_union_type:
01823         case DW_TAG_enumeration_type:
01824         case DW_TAG_typedef:
01825             /* the type referred to will be loaded when we need it, so skip it */
01826             break;
01827         default:
01828             FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
01829                   child->abbrev->tag, dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
01830         }
01831     }
01832 
01833     symt_close_func_block(subpgm->ctx->module, subpgm->func, block, 0);
01834 }
01835 
01836 static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
01837                                             dwarf2_debug_info_t* di)
01838 {
01839     struct attribute name;
01840     unsigned long low_pc, high_pc;
01841     struct attribute is_decl;
01842     struct attribute inline_flags;
01843     struct symt* ret_type;
01844     struct symt_function_signature* sig_type;
01845     dwarf2_subprogram_t subpgm;
01846     struct vector* children;
01847     dwarf2_debug_info_t* child;
01848     unsigned int i;
01849 
01850     if (di->symt) return di->symt;
01851 
01852     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
01853 
01854     if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name))
01855     {
01856         WARN("No name for function... dropping function\n");
01857         return NULL;
01858     }
01859     /* if it's an abstract representation of an inline function, there should be
01860      * a concrete object that we'll handle
01861      */
01862     if (dwarf2_find_attribute(ctx, di, DW_AT_inline, &inline_flags) &&
01863         inline_flags.u.uvalue != DW_INL_not_inlined)
01864     {
01865         TRACE("Function %s declared as inlined (%ld)... skipping\n",
01866               name.u.string ? name.u.string : "(null)", inline_flags.u.uvalue);
01867         return NULL;
01868     }
01869 
01870     if (dwarf2_find_attribute(ctx, di, DW_AT_declaration, &is_decl) &&
01871         is_decl.u.uvalue && is_decl.gotten_from == attr_direct)
01872     {
01873         /* it's a real declaration, skip it */
01874         return NULL;
01875     }
01876     if (!dwarf2_read_range(ctx, di, &low_pc, &high_pc))
01877     {
01878         WARN("cannot get range for %s\n", name.u.string);
01879         return NULL;
01880     }
01881     /* As functions (defined as inline assembly) get debug info with dwarf
01882      * (not the case for stabs), we just drop Wine's thunks here...
01883      * Actual thunks will be created in elf_module from the symbol table
01884      */
01885     if (elf_is_in_thunk_area(ctx->load_offset + low_pc, ctx->thunks) >= 0)
01886         return NULL;
01887     if (!(ret_type = dwarf2_lookup_type(ctx, di)))
01888     {
01889         ret_type = ctx->symt_cache[sc_void];
01890         assert(ret_type);
01891     }
01892     /* FIXME: assuming C source code */
01893     sig_type = symt_new_function_signature(ctx->module, ret_type, CV_CALL_FAR_C);
01894     subpgm.func = symt_new_function(ctx->module, ctx->compiland,
01895                                     dwarf2_get_cpp_name(ctx, di, name.u.string),
01896                                     ctx->load_offset + low_pc, high_pc - low_pc,
01897                                     &sig_type->symt);
01898     di->symt = &subpgm.func->symt;
01899     subpgm.ctx = ctx;
01900     if (!dwarf2_compute_location_attr(ctx, di, DW_AT_frame_base,
01901                                       &subpgm.frame, NULL))
01902     {
01903         /* on stack !! */
01904         subpgm.frame.kind = loc_regrel;
01905         subpgm.frame.reg = dbghelp_current_cpu->frame_regno;
01906         subpgm.frame.offset = 0;
01907     }
01908     subpgm.non_computed_variable = FALSE;
01909 
01910     children = dwarf2_get_di_children(ctx, di);
01911     if (children) for (i = 0; i < vector_length(children); i++)
01912     {
01913         child = *(dwarf2_debug_info_t**)vector_at(children, i);
01914 
01915         switch (child->abbrev->tag)
01916         {
01917         case DW_TAG_variable:
01918         case DW_TAG_formal_parameter:
01919             dwarf2_parse_variable(&subpgm, NULL, child);
01920             break;
01921         case DW_TAG_lexical_block:
01922             dwarf2_parse_subprogram_block(&subpgm, NULL, child);
01923             break;
01924         case DW_TAG_inlined_subroutine:
01925             dwarf2_parse_inlined_subroutine(&subpgm, NULL, child);
01926             break;
01927         case DW_TAG_subprogram:
01928             /* FIXME: likely a declaration (to be checked)
01929              * skip it for now
01930              */
01931             break;
01932         case DW_TAG_label:
01933             dwarf2_parse_subprogram_label(&subpgm, child);
01934             break;
01935         case DW_TAG_class_type:
01936         case DW_TAG_structure_type:
01937         case DW_TAG_union_type:
01938         case DW_TAG_enumeration_type:
01939         case DW_TAG_typedef:
01940             /* the type referred to will be loaded when we need it, so skip it */
01941             break;
01942         case DW_TAG_unspecified_parameters:
01943         case DW_TAG_template_type_param:
01944         case DW_TAG_template_value_param:
01945         case DW_TAG_GNU_call_site:
01946             /* FIXME: no support in dbghelp's internals so far */
01947             break;
01948         default:
01949             FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
01950                   child->abbrev->tag, dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
01951     }
01952     }
01953 
01954     if (subpgm.non_computed_variable || subpgm.frame.kind >= loc_user)
01955     {
01956         symt_add_function_point(ctx->module, subpgm.func, SymTagCustom,
01957                                 &subpgm.frame, NULL);
01958     }
01959     if (subpgm.func) symt_normalize_function(subpgm.ctx->module, subpgm.func);
01960 
01961     return di->symt;
01962 }
01963 
01964 static struct symt* dwarf2_parse_subroutine_type(dwarf2_parse_context_t* ctx,
01965                                                  dwarf2_debug_info_t* di)
01966 {
01967     struct symt* ret_type;
01968     struct symt_function_signature* sig_type;
01969     struct vector* children;
01970     dwarf2_debug_info_t* child;
01971     unsigned int i;
01972 
01973     if (di->symt) return di->symt;
01974 
01975     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
01976 
01977     if (!(ret_type = dwarf2_lookup_type(ctx, di)))
01978     {
01979         ret_type = ctx->symt_cache[sc_void];
01980         assert(ret_type);
01981     }
01982 
01983     /* FIXME: assuming C source code */
01984     sig_type = symt_new_function_signature(ctx->module, ret_type, CV_CALL_FAR_C);
01985 
01986     children = dwarf2_get_di_children(ctx, di);
01987     if (children) for (i = 0; i < vector_length(children); i++)
01988     {
01989         child = *(dwarf2_debug_info_t**)vector_at(children, i);
01990 
01991         switch (child->abbrev->tag)
01992         {
01993         case DW_TAG_formal_parameter:
01994             symt_add_function_signature_parameter(ctx->module, sig_type,
01995                                                   dwarf2_lookup_type(ctx, child));
01996             break;
01997         case DW_TAG_unspecified_parameters:
01998             WARN("Unsupported unspecified parameters\n");
01999             break;
02000     }
02001     }
02002 
02003     return di->symt = &sig_type->symt;
02004 }
02005 
02006 static void dwarf2_parse_namespace(dwarf2_parse_context_t* ctx,
02007                                    dwarf2_debug_info_t* di)
02008 {
02009     struct vector*          children;
02010     dwarf2_debug_info_t*    child;
02011     unsigned int            i;
02012 
02013     if (di->symt) return;
02014 
02015     TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
02016 
02017     di->symt = ctx->symt_cache[sc_void];
02018 
02019     children = dwarf2_get_di_children(ctx, di);
02020     if (children) for (i = 0; i < vector_length(children); i++)
02021     {
02022         child = *(dwarf2_debug_info_t**)vector_at(children, i);
02023         dwarf2_load_one_entry(ctx, child);
02024     }
02025 }
02026 
02027 static void dwarf2_load_one_entry(dwarf2_parse_context_t* ctx,
02028                                   dwarf2_debug_info_t* di)
02029 {
02030     switch (di->abbrev->tag)
02031     {
02032     case DW_TAG_typedef:
02033         dwarf2_parse_typedef(ctx, di);
02034         break;
02035     case DW_TAG_base_type:
02036         dwarf2_parse_base_type(ctx, di);
02037         break;
02038     case DW_TAG_pointer_type:
02039         dwarf2_parse_pointer_type(ctx, di);
02040         break;
02041     case DW_TAG_class_type:
02042         dwarf2_parse_udt_type(ctx, di, UdtClass);
02043         break;
02044     case DW_TAG_structure_type:
02045         dwarf2_parse_udt_type(ctx, di, UdtStruct);
02046         break;
02047     case DW_TAG_union_type:
02048         dwarf2_parse_udt_type(ctx, di, UdtUnion);
02049         break;
02050     case DW_TAG_array_type:
02051         dwarf2_parse_array_type(ctx, di);
02052         break;
02053     case DW_TAG_const_type:
02054         dwarf2_parse_const_type(ctx, di);
02055         break;
02056     case DW_TAG_volatile_type:
02057         dwarf2_parse_volatile_type(ctx, di);
02058         break;
02059     case DW_TAG_reference_type:
02060         dwarf2_parse_reference_type(ctx, di);
02061         break;
02062     case DW_TAG_enumeration_type:
02063         dwarf2_parse_enumeration_type(ctx, di);
02064         break;
02065     case DW_TAG_subprogram:
02066         dwarf2_parse_subprogram(ctx, di);
02067         break;
02068     case DW_TAG_subroutine_type:
02069         dwarf2_parse_subroutine_type(ctx, di);
02070         break;
02071     case DW_TAG_variable:
02072         {
02073             dwarf2_subprogram_t subpgm;
02074 
02075             subpgm.ctx = ctx;
02076             subpgm.func = NULL;
02077             subpgm.frame.kind = loc_absolute;
02078             subpgm.frame.offset = 0;
02079             subpgm.frame.reg = Wine_DW_no_register;
02080             dwarf2_parse_variable(&subpgm, NULL, di);
02081         }
02082         break;
02083     case DW_TAG_namespace:
02084         dwarf2_parse_namespace(ctx, di);
02085         break;
02086     /* silence a couple of C++ defines */
02087     case DW_TAG_imported_module:
02088     case DW_TAG_imported_declaration:
02089     case DW_TAG_ptr_to_member_type:
02090         break;
02091     default:
02092         FIXME("Unhandled Tag type 0x%lx at %s, for %lu\n",
02093               di->abbrev->tag, dwarf2_debug_ctx(ctx), di->abbrev->entry_code); 
02094     }
02095 }
02096 
02097 static void dwarf2_set_line_number(struct module* module, unsigned long address,
02098                                    const struct vector* v, unsigned file, unsigned line)
02099 {
02100     struct symt_function*       func;
02101     struct symt_ht*             symt;
02102     unsigned*                   psrc;
02103 
02104     if (!file || !(psrc = vector_at(v, file - 1))) return;
02105 
02106     TRACE("%s %lx %s %u\n",
02107           debugstr_w(module->module.ModuleName), address, source_get(module, *psrc), line);
02108     if (!(symt = symt_find_nearest(module, address)) ||
02109         symt->symt.tag != SymTagFunction) return;
02110     func = (struct symt_function*)symt;
02111     symt_add_func_line(module, func, *psrc, line, address - func->address);
02112 }
02113 
02114 static BOOL dwarf2_parse_line_numbers(const dwarf2_section_t* sections,
02115                                       dwarf2_parse_context_t* ctx,
02116                                       const char* compile_dir,
02117                                       unsigned long offset)
02118 {
02119     dwarf2_traverse_context_t   traverse;
02120     unsigned long               length;
02121     unsigned                    insn_size, default_stmt;
02122     unsigned                    line_range, opcode_base;
02123     int                         line_base;
02124     const unsigned char*        opcode_len;
02125     struct vector               dirs;
02126     struct vector               files;
02127     const char**                p;
02128 
02129     /* section with line numbers stripped */
02130     if (sections[section_line].address == IMAGE_NO_MAP)
02131         return FALSE;
02132 
02133     if (offset + 4 > sections[section_line].size)
02134     {
02135         WARN("out of bounds offset\n");
02136         return FALSE;
02137     }
02138     traverse.data = sections[section_line].address + offset;
02139     traverse.end_data = traverse.data + 4;
02140     traverse.word_size = ctx->module->format_info[DFI_DWARF]->u.dwarf2_info->word_size;
02141 
02142     length = dwarf2_parse_u4(&traverse);
02143     traverse.end_data = sections[section_line].address + offset + length;
02144 
02145     if (offset + 4 + length > sections[section_line].size)
02146     {
02147         WARN("out of bounds header\n");
02148         return FALSE;
02149     }
02150     dwarf2_parse_u2(&traverse); /* version */
02151     dwarf2_parse_u4(&traverse); /* header_len */
02152     insn_size = dwarf2_parse_byte(&traverse);
02153     default_stmt = dwarf2_parse_byte(&traverse);
02154     line_base = (signed char)dwarf2_parse_byte(&traverse);
02155     line_range = dwarf2_parse_byte(&traverse);
02156     opcode_base = dwarf2_parse_byte(&traverse);
02157 
02158     opcode_len = traverse.data;
02159     traverse.data += opcode_base - 1;
02160 
02161     vector_init(&dirs, sizeof(const char*), 4);
02162     p = vector_add(&dirs, &ctx->pool);
02163     *p = compile_dir ? compile_dir : ".";
02164     while (*traverse.data)
02165     {
02166         const char*  rel = (const char*)traverse.data;
02167         unsigned     rellen = strlen(rel);
02168         TRACE("Got include %s\n", rel);
02169         traverse.data += rellen + 1;
02170         p = vector_add(&dirs, &ctx->pool);
02171 
02172         if (*rel == '/' || !compile_dir)
02173             *p = rel;
02174         else
02175         {
02176            /* include directory relative to compile directory */
02177            unsigned  baselen = strlen(compile_dir);
02178            char*     tmp = pool_alloc(&ctx->pool, baselen + 1 + rellen + 1);
02179            strcpy(tmp, compile_dir);
02180            if (tmp[baselen - 1] != '/') tmp[baselen++] = '/';
02181            strcpy(&tmp[baselen], rel);
02182            *p = tmp;
02183         }
02184 
02185     }
02186     traverse.data++;
02187 
02188     vector_init(&files, sizeof(unsigned), 16);
02189     while (*traverse.data)
02190     {
02191         unsigned int    dir_index, mod_time, length;
02192         const char*     name;
02193         const char*     dir;
02194         unsigned*       psrc;
02195 
02196         name = (const char*)traverse.data;
02197         traverse.data += strlen(name) + 1;
02198         dir_index = dwarf2_leb128_as_unsigned(&traverse);
02199         mod_time = dwarf2_leb128_as_unsigned(&traverse);
02200         length = dwarf2_leb128_as_unsigned(&traverse);
02201         dir = *(const char**)vector_at(&dirs, dir_index);
02202         TRACE("Got file %s/%s (%u,%u)\n", dir, name, mod_time, length);
02203         psrc = vector_add(&files, &ctx->pool);
02204         *psrc = source_new(ctx->module, dir, name);
02205     }
02206     traverse.data++;
02207 
02208     while (traverse.data < traverse.end_data)
02209     {
02210         unsigned long address = 0;
02211         unsigned file = 1;
02212         unsigned line = 1;
02213         unsigned is_stmt = default_stmt;
02214         BOOL end_sequence = FALSE;
02215         unsigned opcode, extopcode, i;
02216 
02217         while (!end_sequence)
02218         {
02219             opcode = dwarf2_parse_byte(&traverse);
02220             TRACE("Got opcode %x\n", opcode);
02221 
02222             if (opcode >= opcode_base)
02223             {
02224                 unsigned delta = opcode - opcode_base;
02225 
02226                 address += (delta / line_range) * insn_size;
02227                 line += line_base + (delta % line_range);
02228                 dwarf2_set_line_number(ctx->module, address, &files, file, line);
02229             }
02230             else
02231             {
02232                 switch (opcode)
02233                 {
02234                 case DW_LNS_copy:
02235                     dwarf2_set_line_number(ctx->module, address, &files, file, line);
02236                     break;
02237                 case DW_LNS_advance_pc:
02238                     address += insn_size * dwarf2_leb128_as_unsigned(&traverse);
02239                     break;
02240                 case DW_LNS_advance_line:
02241                     line += dwarf2_leb128_as_signed(&traverse);
02242                     break;
02243                 case DW_LNS_set_file:
02244                     file = dwarf2_leb128_as_unsigned(&traverse);
02245                     break;
02246                 case DW_LNS_set_column:
02247                     dwarf2_leb128_as_unsigned(&traverse);
02248                     break;
02249                 case DW_LNS_negate_stmt:
02250                     is_stmt = !is_stmt;
02251                     break;
02252                 case DW_LNS_set_basic_block:
02253                     break;
02254                 case DW_LNS_const_add_pc:
02255                     address += ((255 - opcode_base) / line_range) * insn_size;
02256                     break;
02257                 case DW_LNS_fixed_advance_pc:
02258                     address += dwarf2_parse_u2(&traverse);
02259                     break;
02260                 case DW_LNS_extended_op:
02261                     dwarf2_leb128_as_unsigned(&traverse);
02262                     extopcode = dwarf2_parse_byte(&traverse);
02263                     switch (extopcode)
02264                     {
02265                     case DW_LNE_end_sequence:
02266                         dwarf2_set_line_number(ctx->module, address, &files, file, line);
02267                         end_sequence = TRUE;
02268                         break;
02269                     case DW_LNE_set_address:
02270                         address = ctx->load_offset + dwarf2_parse_addr(&traverse);
02271                         break;
02272                     case DW_LNE_define_file:
02273                         FIXME("not handled %s\n", traverse.data);
02274                         traverse.data += strlen((const char *)traverse.data) + 1;
02275                         dwarf2_leb128_as_unsigned(&traverse);
02276                         dwarf2_leb128_as_unsigned(&traverse);
02277                         dwarf2_leb128_as_unsigned(&traverse);
02278                         break;
02279                     case DW_LNE_set_discriminator:
02280                         WARN("not handled %s\n", traverse.data);
02281                         dwarf2_leb128_as_unsigned(&traverse);
02282                         break;
02283                     default:
02284                         FIXME("Unsupported extended opcode %x\n", extopcode);
02285                         break;
02286                     }
02287                     break;
02288                 default:
02289                     WARN("Unsupported opcode %x\n", opcode);
02290                     for (i = 0; i < opcode_len[opcode]; i++)
02291                         dwarf2_leb128_as_unsigned(&traverse);
02292                     break;
02293                 }
02294             }
02295         }
02296     }
02297     return TRUE;
02298 }
02299 
02300 static BOOL dwarf2_parse_compilation_unit(const dwarf2_section_t* sections,
02301                                           struct module* module,
02302                                           const struct elf_thunk_area* thunks,
02303                                           dwarf2_traverse_context_t* mod_ctx,
02304                                           unsigned long load_offset)
02305 {
02306     dwarf2_parse_context_t ctx;
02307     dwarf2_traverse_context_t abbrev_ctx;
02308     dwarf2_debug_info_t* di;
02309     dwarf2_traverse_context_t cu_ctx;
02310     const unsigned char* comp_unit_start = mod_ctx->data;
02311     unsigned long cu_length;
02312     unsigned short cu_version;
02313     unsigned long cu_abbrev_offset;
02314     BOOL ret = FALSE;
02315 
02316     cu_length = dwarf2_parse_u4(mod_ctx);
02317     cu_ctx.data = mod_ctx->data;
02318     cu_ctx.end_data = mod_ctx->data + cu_length;
02319     mod_ctx->data += cu_length;
02320     cu_version = dwarf2_parse_u2(&cu_ctx);
02321     cu_abbrev_offset = dwarf2_parse_u4(&cu_ctx);
02322     cu_ctx.word_size = dwarf2_parse_byte(&cu_ctx);
02323 
02324     TRACE("Compilation Unit Header found at 0x%x:\n",
02325           (int)(comp_unit_start - sections[section_debug].address));
02326     TRACE("- length:        %lu\n", cu_length);
02327     TRACE("- version:       %u\n",  cu_version);
02328     TRACE("- abbrev_offset: %lu\n", cu_abbrev_offset);
02329     TRACE("- word_size:     %u\n",  cu_ctx.word_size);
02330 
02331     if (cu_version != 2)
02332     {
02333         WARN("%u DWARF version unsupported. Wine dbghelp only support DWARF 2.\n",
02334              cu_version);
02335         return FALSE;
02336     }
02337 
02338     module->format_info[DFI_DWARF]->u.dwarf2_info->word_size = cu_ctx.word_size;
02339     mod_ctx->word_size = cu_ctx.word_size;
02340 
02341     pool_init(&ctx.pool, 65536);
02342     ctx.sections = sections;
02343     ctx.section = section_debug;
02344     ctx.module = module;
02345     ctx.thunks = thunks;
02346     ctx.load_offset = load_offset;
02347     ctx.ref_offset = comp_unit_start - sections[section_debug].address;
02348     memset(ctx.symt_cache, 0, sizeof(ctx.symt_cache));
02349     ctx.symt_cache[sc_void] = &symt_new_basic(module, btVoid, "void", 0)->symt;
02350     ctx.cpp_name = NULL;
02351 
02352     abbrev_ctx.data = sections[section_abbrev].address + cu_abbrev_offset;
02353     abbrev_ctx.end_data = sections[section_abbrev].address + sections[section_abbrev].size;
02354     abbrev_ctx.word_size = cu_ctx.word_size;
02355     dwarf2_parse_abbrev_set(&abbrev_ctx, &ctx.abbrev_table, &ctx.pool);
02356 
02357     sparse_array_init(&ctx.debug_info_table, sizeof(dwarf2_debug_info_t), 128);
02358     dwarf2_read_one_debug_info(&ctx, &cu_ctx, NULL, &di);
02359 
02360     if (di->abbrev->tag == DW_TAG_compile_unit)
02361     {
02362         struct attribute            name;
02363         struct vector*              children;
02364         dwarf2_debug_info_t*        child = NULL;
02365         unsigned int                i;
02366         struct attribute            stmt_list, low_pc;
02367         struct attribute            comp_dir;
02368 
02369         if (!dwarf2_find_attribute(&ctx, di, DW_AT_name, &name))
02370             name.u.string = NULL;
02371 
02372         /* get working directory of current compilation unit */
02373         if (!dwarf2_find_attribute(&ctx, di, DW_AT_comp_dir, &comp_dir))
02374             comp_dir.u.string = NULL;
02375 
02376         if (!dwarf2_find_attribute(&ctx, di, DW_AT_low_pc, &low_pc))
02377             low_pc.u.uvalue = 0;
02378         ctx.compiland = symt_new_compiland(module, ctx.load_offset + low_pc.u.uvalue,
02379                                            source_new(module, comp_dir.u.string, name.u.string));
02380         di->symt = &ctx.compiland->symt;
02381         children = dwarf2_get_di_children(&ctx, di);
02382         if (children) for (i = 0; i < vector_length(children); i++)
02383         {
02384             child = *(dwarf2_debug_info_t**)vector_at(children, i);
02385             dwarf2_load_one_entry(&ctx, child);
02386         }
02387         if (dwarf2_find_attribute(&ctx, di, DW_AT_stmt_list, &stmt_list))
02388         {
02389             if (dwarf2_parse_line_numbers(sections, &ctx, comp_dir.u.string, stmt_list.u.uvalue))
02390                 module->module.LineNumbers = TRUE;
02391         }
02392         ret = TRUE;
02393     }
02394     else FIXME("Should have a compilation unit here\n");
02395     pool_destroy(&ctx.pool);
02396     return ret;
02397 }
02398 
02399 static BOOL dwarf2_lookup_loclist(const struct module_format* modfmt, const BYTE* start,
02400                                   unsigned long ip, dwarf2_traverse_context_t* lctx)
02401 {
02402     DWORD_PTR                   beg, end;
02403     const BYTE*                 ptr = start;
02404     DWORD                       len;
02405 
02406     while (ptr < modfmt->u.dwarf2_info->debug_loc.address + modfmt->u.dwarf2_info->debug_loc.size)
02407     {
02408         beg = dwarf2_get_addr(ptr, modfmt->u.dwarf2_info->word_size); ptr += modfmt->u.dwarf2_info->word_size;
02409         end = dwarf2_get_addr(ptr, modfmt->u.dwarf2_info->word_size); ptr += modfmt->u.dwarf2_info->word_size;
02410         if (!beg && !end) break;
02411         len = dwarf2_get_u2(ptr); ptr += 2;
02412 
02413         if (beg <= ip && ip < end)
02414         {
02415             lctx->data = ptr;
02416             lctx->end_data = ptr + len;
02417             lctx->word_size = modfmt->u.dwarf2_info->word_size;
02418             return TRUE;
02419         }
02420         ptr += len;
02421     }
02422     WARN("Couldn't find ip in location list\n");
02423     return FALSE;
02424 }
02425 
02426 static enum location_error loc_compute_frame(struct process* pcs,
02427                                              const struct module_format* modfmt,
02428                                              const struct symt_function* func,
02429                                              DWORD_PTR ip, struct location* frame)
02430 {
02431     struct symt**               psym = NULL;
02432     struct location*            pframe;
02433     dwarf2_traverse_context_t   lctx;
02434     enum location_error         err;
02435     unsigned int                i;
02436 
02437     for (i=0; i<vector_length(&func->vchildren); i++)
02438     {
02439         psym = vector_at(&func->vchildren, i);
02440         if ((*psym)->tag == SymTagCustom)
02441         {
02442             pframe = &((struct symt_hierarchy_point*)*psym)->loc;
02443 
02444             /* First, recompute the frame information, if needed */
02445             switch (pframe->kind)
02446             {
02447             case loc_regrel:
02448             case loc_register:
02449                 *frame = *pframe;
02450                 break;
02451             case loc_dwarf2_location_list:
02452                 WARN("Searching loclist for %s\n", func->hash_elt.name);
02453                 if (!dwarf2_lookup_loclist(modfmt,
02454                                            modfmt->u.dwarf2_info->debug_loc.address + pframe->offset,
02455                                            ip, &lctx))
02456                     return loc_err_out_of_scope;
02457                 if ((err = compute_location(&lctx, frame, pcs->handle, NULL)) < 0) return err;
02458                 if (frame->kind >= loc_user)
02459                 {
02460                     WARN("Couldn't compute runtime frame location\n");
02461                     return loc_err_too_complex;
02462                 }
02463                 break;
02464             default:
02465                 WARN("Unsupported frame kind %d\n", pframe->kind);
02466                 return loc_err_internal;
02467             }
02468             return 0;
02469         }
02470     }
02471     WARN("Couldn't find Custom function point, whilst location list offset is searched\n");
02472     return loc_err_internal;
02473 }
02474 
02475 enum reg_rule
02476 {
02477     RULE_UNSET,          /* not set at all */
02478     RULE_UNDEFINED,      /* undefined value */
02479     RULE_SAME,           /* same value as previous frame */
02480     RULE_CFA_OFFSET,     /* stored at cfa offset */
02481     RULE_OTHER_REG,      /* stored in other register */
02482     RULE_EXPRESSION,     /* address specified by expression */
02483     RULE_VAL_EXPRESSION  /* value specified by expression */
02484 };
02485 
02486 /* make it large enough for all CPUs */
02487 #define NB_FRAME_REGS 64
02488 #define MAX_SAVED_STATES 16
02489 
02490 struct frame_state
02491 {
02492     ULONG_PTR     cfa_offset;
02493     unsigned char cfa_reg;
02494     enum reg_rule cfa_rule;
02495     enum reg_rule rules[NB_FRAME_REGS];
02496     ULONG_PTR     regs[NB_FRAME_REGS];
02497 };
02498 
02499 struct frame_info
02500 {
02501     ULONG_PTR     ip;
02502     ULONG_PTR     code_align;
02503     LONG_PTR      data_align;
02504     unsigned char retaddr_reg;
02505     unsigned char fde_encoding;
02506     unsigned char lsda_encoding;
02507     unsigned char signal_frame;
02508     unsigned char aug_z_format;
02509     unsigned char state_sp;
02510     struct frame_state state;
02511     struct frame_state state_stack[MAX_SAVED_STATES];
02512 };
02513 
02514 static ULONG_PTR dwarf2_parse_augmentation_ptr(dwarf2_traverse_context_t* ctx, unsigned char encoding)
02515 {
02516     ULONG_PTR   base;
02517 
02518     if (encoding == DW_EH_PE_omit) return 0;
02519 
02520     switch (encoding & 0xf0)
02521     {
02522     case DW_EH_PE_abs:
02523         base = 0;
02524         break;
02525     case DW_EH_PE_pcrel:
02526         base = (ULONG_PTR)ctx->data;
02527         break;
02528     default:
02529         FIXME("unsupported encoding %02x\n", encoding);
02530         return 0;
02531     }
02532 
02533     switch (encoding & 0x0f)
02534     {
02535     case DW_EH_PE_native:
02536         return base + dwarf2_parse_addr(ctx);
02537     case DW_EH_PE_leb128:
02538         return base + dwarf2_leb128_as_unsigned(ctx);
02539     case DW_EH_PE_data2:
02540         return base + dwarf2_parse_u2(ctx);
02541     case DW_EH_PE_data4:
02542         return base + dwarf2_parse_u4(ctx);
02543     case DW_EH_PE_data8:
02544         return base + dwarf2_parse_u8(ctx);
02545     case DW_EH_PE_signed|DW_EH_PE_leb128:
02546         return base + dwarf2_leb128_as_signed(ctx);
02547     case DW_EH_PE_signed|DW_EH_PE_data2:
02548         return base + (signed short)dwarf2_parse_u2(ctx);
02549     case DW_EH_PE_signed|DW_EH_PE_data4:
02550         return base + (signed int)dwarf2_parse_u4(ctx);
02551     case DW_EH_PE_signed|DW_EH_PE_data8:
02552         return base + (LONG64)dwarf2_parse_u8(ctx);
02553     default:
02554         FIXME("unsupported encoding %02x\n", encoding);
02555         return 0;
02556     }
02557 }
02558 
02559 static BOOL parse_cie_details(dwarf2_traverse_context_t* ctx, struct frame_info* info)
02560 {
02561     unsigned char version;
02562     const char* augmentation;
02563     const unsigned char* end;
02564     ULONG_PTR len;
02565 
02566     memset(info, 0, sizeof(*info));
02567     info->lsda_encoding = DW_EH_PE_omit;
02568     info->aug_z_format = 0;
02569 
02570     /* parse the CIE first */
02571     version = dwarf2_parse_byte(ctx);
02572     if (version != 1)
02573     {
02574         FIXME("unknown CIE version %u at %p\n", version, ctx->data - 1);
02575         return FALSE;
02576     }
02577     augmentation = (const char*)ctx->data;
02578     ctx->data += strlen(augmentation) + 1;
02579 
02580     info->code_align = dwarf2_leb128_as_unsigned(ctx);
02581     info->data_align = dwarf2_leb128_as_signed(ctx);
02582     info->retaddr_reg = dwarf2_parse_byte(ctx);
02583     info->state.cfa_rule = RULE_CFA_OFFSET;
02584 
02585     end = NULL;
02586     TRACE("\tparsing augmentation %s\n", augmentation);
02587     if (*augmentation) do
02588     {
02589         switch (*augmentation)
02590         {
02591         case 'z':
02592             len = dwarf2_leb128_as_unsigned(ctx);
02593             end = ctx->data + len;
02594             info->aug_z_format = 1;
02595             continue;
02596         case 'L':
02597             info->lsda_encoding = dwarf2_parse_byte(ctx);
02598             continue;
02599         case 'P':
02600         {
02601             unsigned char encoding = dwarf2_parse_byte(ctx);
02602             /* throw away the indirect bit, as we don't care for the result */
02603             encoding &= ~DW_EH_PE_indirect;
02604             dwarf2_parse_augmentation_ptr(ctx, encoding); /* handler */
02605             continue;
02606         }
02607         case 'R':
02608             info->fde_encoding = dwarf2_parse_byte(ctx);
02609             continue;
02610         case 'S':
02611             info->signal_frame = 1;
02612             continue;
02613         }
02614         FIXME("unknown augmentation '%c'\n", *augmentation);
02615         if (!end) return FALSE;
02616         break;
02617     } while (*++augmentation);
02618     if (end) ctx->data = end;
02619     return TRUE;
02620 }
02621 
02622 static BOOL dwarf2_get_cie(unsigned long addr, struct module* module, DWORD_PTR delta,
02623                            dwarf2_traverse_context_t* fde_ctx, dwarf2_traverse_context_t* cie_ctx,
02624                            struct frame_info* info, BOOL in_eh_frame)
02625 {
02626     const unsigned char*        ptr_blk;
02627     const unsigned char*        cie_ptr;
02628     const unsigned char*        last_cie_ptr = (const unsigned char*)~0;
02629     unsigned                    len, id;
02630     unsigned long               start, range;
02631     unsigned                    cie_id;
02632     const BYTE*                 start_data = fde_ctx->data;
02633 
02634     cie_id = in_eh_frame ? 0 : DW_CIE_ID;
02635     for (; fde_ctx->data + 2 * 4 < fde_ctx->end_data; fde_ctx->data = ptr_blk)
02636     {
02637         /* find the FDE for address addr (skip CIE) */
02638         len = dwarf2_parse_u4(fde_ctx);
02639         if (len == 0xffffffff) FIXME("Unsupported yet 64-bit CIEs\n");
02640         ptr_blk = fde_ctx->data + len;
02641         id  = dwarf2_parse_u4(fde_ctx);
02642         if (id == cie_id)
02643         {
02644             last_cie_ptr = fde_ctx->data - 8;
02645             /* we need some bits out of the CIE in order to parse all contents */
02646             if (!parse_cie_details(fde_ctx, info)) return FALSE;
02647             cie_ctx->data = fde_ctx->data;
02648             cie_ctx->end_data = ptr_blk;
02649             cie_ctx->word_size = fde_ctx->word_size;
02650             continue;
02651         }
02652         cie_ptr = (in_eh_frame) ? fde_ctx->data - id - 4 : start_data + id;
02653         if (cie_ptr != last_cie_ptr)
02654         {
02655             last_cie_ptr = cie_ptr;
02656             cie_ctx->data = cie_ptr;
02657             cie_ctx->word_size = fde_ctx->word_size;
02658             cie_ctx->end_data = cie_ptr + 4;
02659             cie_ctx->end_data = cie_ptr + 4 + dwarf2_parse_u4(cie_ctx);
02660             if (dwarf2_parse_u4(cie_ctx) != cie_id)
02661             {
02662                 FIXME("wrong CIE pointer\n");
02663                 return FALSE;
02664             }
02665             if (!parse_cie_details(cie_ctx, info)) return FALSE;
02666         }
02667         start = delta + dwarf2_parse_augmentation_ptr(fde_ctx, info->fde_encoding);
02668         range = dwarf2_parse_augmentation_ptr(fde_ctx, info->fde_encoding & 0x0F);
02669 
02670         if (addr >= start && addr < start + range)
02671         {
02672             /* reset the FDE context */
02673             fde_ctx->end_data = ptr_blk;
02674 
02675             info->ip = start;
02676             return TRUE;
02677         }
02678     }
02679     return FALSE;
02680 }
02681 
02682 static int valid_reg(ULONG_PTR reg)
02683 {
02684     if (reg >= NB_FRAME_REGS) FIXME("unsupported reg %lx\n", reg);
02685     return (reg < NB_FRAME_REGS);
02686 }
02687 
02688 static void execute_cfa_instructions(dwarf2_traverse_context_t* ctx,
02689                                      ULONG_PTR last_ip, struct frame_info *info)
02690 {
02691     while (ctx->data < ctx->end_data && info->ip <= last_ip + info->signal_frame)
02692     {
02693         enum dwarf_call_frame_info op = dwarf2_parse_byte(ctx);
02694 
02695         if (op & 0xc0)
02696         {
02697             switch (op & 0xc0)
02698             {
02699             case DW_CFA_advance_loc:
02700             {
02701                 ULONG_PTR offset = (op & 0x3f) * info->code_align;
02702                 TRACE("%lx: DW_CFA_advance_loc %lu\n", info->ip, offset);
02703                 info->ip += offset;
02704                 break;
02705             }
02706             case DW_CFA_offset:
02707             {
02708                 ULONG_PTR reg = op & 0x3f;
02709                 LONG_PTR offset = dwarf2_leb128_as_unsigned(ctx) * info->data_align;
02710                 if (!valid_reg(reg)) break;
02711                 TRACE("%lx: DW_CFA_offset %s, %ld\n",
02712                       info->ip,
02713                       dbghelp_current_cpu->fetch_regname(dbghelp_current_cpu->map_dwarf_register(reg)),
02714                       offset);
02715                 info->state.regs[reg]  = offset;
02716                 info->state.rules[reg] = RULE_CFA_OFFSET;
02717                 break;
02718             }
02719             case DW_CFA_restore:
02720             {
02721                 ULONG_PTR reg = op & 0x3f;
02722                 if (!valid_reg(reg)) break;
02723                 TRACE("%lx: DW_CFA_restore %s\n",
02724                       info->ip,
02725                       dbghelp_current_cpu->fetch_regname(dbghelp_current_cpu->map_dwarf_register(reg)));
02726                 info->state.rules[reg] = RULE_UNSET;
02727                 break;
02728             }
02729             }
02730         }
02731         else switch (op)
02732         {
02733         case DW_CFA_nop:
02734             break;
02735         case DW_CFA_set_loc:
02736         {
02737             ULONG_PTR loc = dwarf2_parse_augmentation_ptr(ctx, info->fde_encoding);
02738             TRACE("%lx: DW_CFA_set_loc %lx\n", info->ip, loc);
02739             info->ip = loc;
02740             break;
02741         }
02742         case DW_CFA_advance_loc1:
02743         {
02744             ULONG_PTR offset = dwarf2_parse_byte(ctx) * info->code_align;
02745             TRACE("%lx: DW_CFA_advance_loc1 %lu\n", info->ip, offset);
02746             info->ip += offset;
02747             break;
02748         }
02749         case DW_CFA_advance_loc2:
02750         {
02751             ULONG_PTR offset = dwarf2_parse_u2(ctx) * info->code_align;
02752             TRACE("%lx: DW_CFA_advance_loc2 %lu\n", info->ip, offset);
02753             info->ip += offset;
02754             break;
02755         }
02756         case DW_CFA_advance_loc4:
02757         {
02758             ULONG_PTR offset = dwarf2_parse_u4(ctx) * info->code_align;
02759             TRACE("%lx: DW_CFA_advance_loc4 %lu\n", info->ip, offset);
02760             info->ip += offset;
02761             break;
02762         }
02763         case DW_CFA_offset_extended:
02764         case DW_CFA_offset_extended_sf:
02765         {
02766             ULONG_PTR reg = dwarf2_leb128_as_unsigned(ctx);
02767             LONG_PTR offset = (op == DW_CFA_offset_extended) ? dwarf2_leb128_as_unsigned(ctx) * info->data_align
02768                                                              : dwarf2_leb128_as_signed(ctx) * info->data_align;
02769             if (!valid_reg(reg)) break;
02770             TRACE("%lx: DW_CFA_offset_extended %s, %ld\n",
02771                   info->ip,
02772                   dbghelp_current_cpu->fetch_regname(dbghelp_current_cpu->map_dwarf_register(reg)),
02773                   offset);
02774             info->state.regs[reg]  = offset;
02775             info->state.rules[reg] = RULE_CFA_OFFSET;
02776             break;
02777         }
02778         case DW_CFA_restore_extended:
02779         {
02780             ULONG_PTR reg = dwarf2_leb128_as_unsigned(ctx);
02781             if (!valid_reg(reg)) break;
02782             TRACE("%lx: DW_CFA_restore_extended %s\n",
02783                   info->ip,
02784                   dbghelp_current_cpu->fetch_regname(dbghelp_current_cpu->map_dwarf_register(reg)));
02785             info->state.rules[reg] = RULE_UNSET;
02786             break;
02787         }
02788         case DW_CFA_undefined:
02789         {
02790             ULONG_PTR reg = dwarf2_leb128_as_unsigned(ctx);
02791             if (!valid_reg(reg)) break;
02792             TRACE("%lx: DW_CFA_undefined %s\n",
02793                   info->ip,
02794                   dbghelp_current_cpu->fetch_regname(dbghelp_current_cpu->map_dwarf_register(reg)));
02795             info->state.rules[reg] = RULE_UNDEFINED;
02796             break;
02797         }
02798         case DW_CFA_same_value:
02799         {
02800             ULONG_PTR reg = dwarf2_leb128_as_unsigned(ctx);
02801             if (!valid_reg(reg)) break;
02802             TRACE("%lx: DW_CFA_same_value %s\n",
02803                   info->ip,
02804                   dbghelp_current_cpu->fetch_regname(dbghelp_current_cpu->map_dwarf_register(reg)));
02805             info->state.regs[reg]  = reg;
02806             info->state.rules[reg] = RULE_SAME;
02807             break;
02808         }
02809         case DW_CFA_register:
02810         {
02811             ULONG_PTR reg = dwarf2_leb128_as_unsigned(ctx);
02812             ULONG_PTR reg2 = dwarf2_leb128_as_unsigned(ctx);
02813             if (!valid_reg(reg) || !valid_reg(reg2)) break;
02814             TRACE("%lx: DW_CFA_register %s == %s\n",
02815                   info->ip,
02816                   dbghelp_current_cpu->fetch_regname(dbghelp_current_cpu->map_dwarf_register(reg)),
02817                   dbghelp_current_cpu->fetch_regname(dbghelp_current_cpu->map_dwarf_register(reg2)));
02818             info->state.regs[reg]  = reg2;
02819             info->state.rules[reg] = RULE_OTHER_REG;
02820             break;
02821         }
02822         case DW_CFA_remember_state:
02823             TRACE("%lx: DW_CFA_remember_state\n", info->ip);
02824             if (info->state_sp >= MAX_SAVED_STATES)
02825                 FIXME("%lx: DW_CFA_remember_state too many nested saves\n", info->ip);
02826             else
02827                 info->state_stack[info->state_sp++] = info->state;
02828             break;
02829         case DW_CFA_restore_state:
02830             TRACE("%lx: DW_CFA_restore_state\n", info->ip);
02831             if (!info->state_sp)
02832                 FIXME("%lx: DW_CFA_restore_state without corresponding save\n", info->ip);
02833             else
02834                 info->state = info->state_stack[--info->state_sp];
02835             break;
02836         case DW_CFA_def_cfa:
02837         case DW_CFA_def_cfa_sf:
02838         {
02839             ULONG_PTR reg = dwarf2_leb128_as_unsigned(ctx);
02840             ULONG_PTR offset = (op == DW_CFA_def_cfa) ? dwarf2_leb128_as_unsigned(ctx)
02841                                                       : dwarf2_leb128_as_signed(ctx) * info->data_align;
02842             if (!valid_reg(reg)) break;
02843             TRACE("%lx: DW_CFA_def_cfa %s, %lu\n",
02844                   info->ip,
02845                   dbghelp_current_cpu->fetch_regname(dbghelp_current_cpu->map_dwarf_register(reg)),
02846                   offset);
02847             info->state.cfa_reg    = reg;
02848             info->state.cfa_offset = offset;
02849             info->state.cfa_rule   = RULE_CFA_OFFSET;
02850             break;
02851         }
02852         case DW_CFA_def_cfa_register:
02853         {
02854             ULONG_PTR reg = dwarf2_leb128_as_unsigned(ctx);
02855             if (!valid_reg(reg)) break;
02856             TRACE("%lx: DW_CFA_def_cfa_register %s\n",
02857                   info->ip,
02858                   dbghelp_current_cpu->fetch_regname(dbghelp_current_cpu->map_dwarf_register(reg)));
02859             info->state.cfa_reg  = reg;
02860             info->state.cfa_rule = RULE_CFA_OFFSET;
02861             break;
02862         }
02863         case DW_CFA_def_cfa_offset:
02864         case DW_CFA_def_cfa_offset_sf:
02865         {
02866             ULONG_PTR offset = (op == DW_CFA_def_cfa_offset) ? dwarf2_leb128_as_unsigned(ctx)
02867                                                              : dwarf2_leb128_as_signed(ctx) * info->data_align;
02868             TRACE("%lx: DW_CFA_def_cfa_offset %lu\n", info->ip, offset);
02869             info->state.cfa_offset = offset;
02870             info->state.cfa_rule   = RULE_CFA_OFFSET;
02871             break;
02872         }
02873         case DW_CFA_def_cfa_expression:
02874         {
02875             ULONG_PTR expr = (ULONG_PTR)ctx->data;
02876             ULONG_PTR len = dwarf2_leb128_as_unsigned(ctx);
02877             TRACE("%lx: DW_CFA_def_cfa_expression %lx-%lx\n", info->ip, expr, expr+len);
02878             info->state.cfa_offset = expr;
02879             info->state.cfa_rule   = RULE_VAL_EXPRESSION;
02880             ctx->data += len;
02881             break;
02882         }
02883         case DW_CFA_expression:
02884         case DW_CFA_val_expression:
02885         {
02886             ULONG_PTR reg = dwarf2_leb128_as_unsigned(ctx);
02887             ULONG_PTR expr = (ULONG_PTR)ctx->data;
02888             ULONG_PTR len = dwarf2_leb128_as_unsigned(ctx);
02889             if (!valid_reg(reg)) break;
02890             TRACE("%lx: DW_CFA_%sexpression %s %lx-%lx\n",
02891                   info->ip, (op == DW_CFA_expression) ? "" : "val_",
02892                   dbghelp_current_cpu->fetch_regname(dbghelp_current_cpu->map_dwarf_register(reg)),
02893                   expr, expr + len);
02894             info->state.regs[reg]  = expr;
02895             info->state.rules[reg] = (op == DW_CFA_expression) ? RULE_EXPRESSION : RULE_VAL_EXPRESSION;
02896             ctx->data += len;
02897             break;
02898         }
02899         case DW_CFA_GNU_args_size:
02900         /* FIXME: should check that GCC is the compiler for this CU */
02901         {
02902             ULONG_PTR   args = dwarf2_leb128_as_unsigned(ctx);
02903             TRACE("%lx: DW_CFA_GNU_args_size %lu\n", info->ip, args);
02904             /* ignored */
02905             break;
02906         }
02907         default:
02908             FIXME("%lx: unknown CFA opcode %02x\n", info->ip, op);
02909             break;
02910         }
02911     }
02912 }
02913 
02914 /* retrieve a context register from its dwarf number */
02915 static ULONG_PTR get_context_reg(CONTEXT *context, ULONG_PTR dw_reg)
02916 {
02917     unsigned regno = dbghelp_current_cpu->map_dwarf_register(dw_reg), sz;
02918     ULONG_PTR* ptr = dbghelp_current_cpu->fetch_context_reg(context, regno, &sz);
02919 
02920     if (sz != sizeof(ULONG_PTR))
02921     {
02922         FIXME("reading register %lu/%u of wrong size %u\n", dw_reg, regno, sz);
02923         return 0;
02924     }
02925     return *ptr;
02926 }
02927 
02928 /* set a context register from its dwarf number */
02929 static void set_context_reg(struct cpu_stack_walk* csw, CONTEXT *context, ULONG_PTR dw_reg,
02930                             ULONG_PTR val, BOOL isdebuggee)
02931 {
02932     unsigned regno = dbghelp_current_cpu->map_dwarf_register(dw_reg), sz;
02933     ULONG_PTR* ptr = dbghelp_current_cpu->fetch_context_reg(context, regno, &sz);
02934 
02935     if (isdebuggee)
02936     {
02937         char    tmp[16];
02938 
02939         if (sz > sizeof(tmp))
02940         {
02941             FIXME("register %lu/%u size is too wide: %u\n", dw_reg, regno, sz);
02942             return;
02943         }
02944         if (!sw_read_mem(csw, val, tmp, sz))
02945         {
02946             WARN("Couldn't read memory at %p\n", (void*)val);
02947             return;
02948         }
02949         memcpy(ptr, tmp, sz);
02950     }
02951     else
02952     {
02953         if (sz != sizeof(ULONG_PTR))
02954         {
02955             FIXME("assigning to register %lu/%u of wrong size %u\n", dw_reg, regno, sz);
02956             return;
02957         }
02958         *ptr = val;
02959     }
02960 }
02961 
02962 /* copy a register from one context to another using dwarf number */
02963 static void copy_context_reg(CONTEXT *dstcontext, ULONG_PTR dwregdst, CONTEXT* srccontext, ULONG_PTR dwregsrc)
02964 {
02965     unsigned regdstno = dbghelp_current_cpu->map_dwarf_register(dwregdst), szdst;
02966     unsigned regsrcno = dbghelp_current_cpu->map_dwarf_register(dwregsrc), szsrc;
02967     ULONG_PTR* ptrdst = dbghelp_current_cpu->fetch_context_reg(dstcontext, regdstno, &szdst);
02968     ULONG_PTR* ptrsrc = dbghelp_current_cpu->fetch_context_reg(srccontext, regsrcno, &szsrc);
02969 
02970     if (szdst != szsrc)
02971     {
02972         FIXME("Cannot copy register %lu/%u => %lu/%u because of size mismatch (%u => %u)\n",
02973               dwregsrc, regsrcno, dwregdst, regdstno, szsrc, szdst);
02974         return;
02975     }
02976     memcpy(ptrdst, ptrsrc, szdst);
02977 }
02978 
02979 static ULONG_PTR eval_expression(const struct module* module, struct cpu_stack_walk* csw,
02980                                  const unsigned char* zp, CONTEXT *context)
02981 {
02982     dwarf2_traverse_context_t    ctx;
02983     ULONG_PTR reg, sz, tmp, stack[64];
02984     int sp = -1;
02985     ULONG_PTR len;
02986 
02987     ctx.data = zp;
02988     ctx.end_data = zp + 4;
02989     len = dwarf2_leb128_as_unsigned(&ctx);
02990     ctx.end_data = ctx.data + len;
02991     ctx.word_size = module->format_info[DFI_DWARF]->u.dwarf2_info->word_size;
02992 
02993     while (ctx.data < ctx.end_data)
02994     {
02995         unsigned char opcode = dwarf2_parse_byte(&ctx);
02996 
02997         if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31)
02998             stack[++sp] = opcode - DW_OP_lit0;
02999         else if (opcode >= DW_OP_reg0 && opcode <= DW_OP_reg31)
03000             stack[++sp] = get_context_reg(context, opcode - DW_OP_reg0);
03001         else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31)
03002             stack[++sp] = get_context_reg(context, opcode - DW_OP_breg0) + dwarf2_leb128_as_signed(&ctx);
03003         else switch (opcode)
03004         {
03005         case DW_OP_nop:         break;
03006         case DW_OP_addr:        stack[++sp] = dwarf2_parse_addr(&ctx); break;
03007         case DW_OP_const1u:     stack[++sp] = dwarf2_parse_byte(&ctx); break;
03008         case DW_OP_const1s:     stack[++sp] = (signed char)dwarf2_parse_byte(&ctx); break;
03009         case DW_OP_const2u:     stack[++sp] = dwarf2_parse_u2(&ctx); break;
03010         case DW_OP_const2s:     stack[++sp] = (short)dwarf2_parse_u2(&ctx); break;
03011         case DW_OP_const4u:     stack[++sp] = dwarf2_parse_u4(&ctx); break;
03012         case DW_OP_const4s:     stack[++sp] = (signed int)dwarf2_parse_u4(&ctx); break;
03013         case DW_OP_const8u:     stack[++sp] = dwarf2_parse_u8(&ctx); break;
03014         case DW_OP_const8s:     stack[++sp] = (LONG_PTR)dwarf2_parse_u8(&ctx); break;
03015         case DW_OP_constu:      stack[++sp] = dwarf2_leb128_as_unsigned(&ctx); break;
03016         case DW_OP_consts:      stack[++sp] = dwarf2_leb128_as_signed(&ctx); break;
03017         case DW_OP_deref:
03018             if (!sw_read_mem(csw, stack[sp], &tmp, sizeof(tmp)))
03019             {
03020                 ERR("Couldn't read memory at %lx\n", stack[sp]);
03021                 tmp = 0;
03022             }
03023             stack[sp] = tmp;
03024             break;
03025         case DW_OP_dup:         stack[sp + 1] = stack[sp]; sp++; break;
03026         case DW_OP_drop:        sp--; break;
03027         case DW_OP_over:        stack[sp + 1] = stack[sp - 1]; sp++; break;
03028         case DW_OP_pick:        stack[sp + 1] = stack[sp - dwarf2_parse_byte(&ctx)]; sp++; break;
03029         case DW_OP_swap:        tmp = stack[sp]; stack[sp] = stack[sp-1]; stack[sp-1] = tmp; break;
03030         case DW_OP_rot:         tmp = stack[sp]; stack[sp] = stack[sp-1]; stack[sp-1] = stack[sp-2]; stack[sp-2] = tmp; break;
03031         case DW_OP_abs:         stack[sp] = labs(stack[sp]); break;
03032         case DW_OP_neg:         stack[sp] = -stack[sp]; break;
03033         case DW_OP_not:         stack[sp] = ~stack[sp]; break;
03034         case DW_OP_and:         stack[sp-1] &= stack[sp]; sp--; break;
03035         case DW_OP_or:          stack[sp-1] |= stack[sp]; sp--; break;
03036         case DW_OP_minus:       stack[sp-1] -= stack[sp]; sp--; break;
03037         case DW_OP_mul:         stack[sp-1] *= stack[sp]; sp--; break;
03038         case DW_OP_plus:        stack[sp-1] += stack[sp]; sp--; break;
03039         case DW_OP_xor:         stack[sp-1] ^= stack[sp]; sp--; break;
03040         case DW_OP_shl:         stack[sp-1] <<= stack[sp]; sp--; break;
03041         case DW_OP_shr:         stack[sp-1] >>= stack[sp]; sp--; break;
03042         case DW_OP_plus_uconst: stack[sp] += dwarf2_leb128_as_unsigned(&ctx); break;
03043         case DW_OP_shra:        stack[sp-1] = (LONG_PTR)stack[sp-1] / (1 << stack[sp]); sp--; break;
03044         case DW_OP_div:         stack[sp-1] = (LONG_PTR)stack[sp-1] / (LONG_PTR)stack[sp]; sp--; break;
03045         case DW_OP_mod:         stack[sp-1] = (LONG_PTR)stack[sp-1] % (LONG_PTR)stack[sp]; sp--; break;
03046         case DW_OP_ge:          stack[sp-1] = ((LONG_PTR)stack[sp-1] >= (LONG_PTR)stack[sp]); sp--; break;
03047         case DW_OP_gt:          stack[sp-1] = ((LONG_PTR)stack[sp-1] >  (LONG_PTR)stack[sp]); sp--; break;
03048         case DW_OP_le:          stack[sp-1] = ((LONG_PTR)stack[sp-1] <= (LONG_PTR)stack[sp]); sp--; break;
03049         case DW_OP_lt:          stack[sp-1] = ((LONG_PTR)stack[sp-1] <  (LONG_PTR)stack[sp]); sp--; break;
03050         case DW_OP_eq:          stack[sp-1] = (stack[sp-1] == stack[sp]); sp--; break;
03051         case DW_OP_ne:          stack[sp-1] = (stack[sp-1] != stack[sp]); sp--; break;
03052         case DW_OP_skip:        tmp = (short)dwarf2_parse_u2(&ctx); ctx.data += tmp; break;
03053         case DW_OP_bra:         tmp = (short)dwarf2_parse_u2(&ctx); if (!stack[sp--]) ctx.data += tmp; break;
03054         case DW_OP_GNU_encoded_addr:
03055             tmp = dwarf2_parse_byte(&ctx);
03056             stack[++sp] = dwarf2_parse_augmentation_ptr(&ctx, tmp);
03057             break;
03058         case DW_OP_regx:
03059             stack[++sp] = get_context_reg(context, dwarf2_leb128_as_unsigned(&ctx));
03060             break;
03061         case DW_OP_bregx:
03062             reg = dwarf2_leb128_as_unsigned(&ctx);
03063             tmp = dwarf2_leb128_as_signed(&ctx);
03064             stack[++sp] = get_context_reg(context, reg) + tmp;
03065             break;
03066         case DW_OP_deref_size:
03067             sz = dwarf2_parse_byte(&ctx);
03068             if (!sw_read_mem(csw, stack[sp], &tmp, sz))
03069             {
03070                 ERR("Couldn't read memory at %lx\n", stack[sp]);
03071                 tmp = 0;
03072             }
03073             /* do integral promotion */
03074             switch (sz)
03075             {
03076             case 1: stack[sp] = *(unsigned char*)&tmp; break;
03077             case 2: stack[sp] = *(unsigned short*)&tmp; break;
03078             case 4: stack[sp] = *(unsigned int*)&tmp; break;
03079             case 8: stack[sp] = *(ULONG_PTR*)&tmp; break; /* FIXME: won't work on 32bit platform */
03080             default: FIXME("Unknown size for deref 0x%lx\n", sz);
03081             }
03082             break;
03083         default:
03084             FIXME("unhandled opcode %02x\n", opcode);
03085         }
03086     }
03087     return stack[sp];
03088 }
03089 
03090 static void apply_frame_state(const struct module* module, struct cpu_stack_walk* csw,
03091                               CONTEXT *context, struct frame_state *state, ULONG_PTR* cfa)
03092 {
03093     unsigned int i;
03094     ULONG_PTR value;
03095     CONTEXT new_context = *context;
03096 
03097     switch (state->cfa_rule)
03098     {
03099     case RULE_EXPRESSION:
03100         *cfa = eval_expression(module, csw, (const unsigned char*)state->cfa_offset, context);
03101         if (!sw_read_mem(csw, *cfa, cfa, sizeof(*cfa)))
03102         {
03103             WARN("Couldn't read memory at %p\n", (void*)*cfa);
03104             return;
03105         }
03106         break;
03107     case RULE_VAL_EXPRESSION:
03108         *cfa = eval_expression(module, csw, (const unsigned char*)state->cfa_offset, context);
03109         break;
03110     default:
03111         *cfa = get_context_reg(context, state->cfa_reg) + state->cfa_offset;
03112         break;
03113     }
03114     if (!*cfa) return;
03115 
03116     for (i = 0; i < NB_FRAME_REGS; i++)
03117     {
03118         switch (state->rules[i])
03119         {
03120         case RULE_UNSET:
03121         case RULE_UNDEFINED:
03122         case RULE_SAME:
03123             break;
03124         case RULE_CFA_OFFSET:
03125             set_context_reg(csw, &new_context, i, *cfa + state->regs[i], TRUE);
03126             break;
03127         case RULE_OTHER_REG:
03128             copy_context_reg(&new_context, i, context, state->regs[i]);
03129             break;
03130         case RULE_EXPRESSION:
03131             value = eval_expression(module, csw, (const unsigned char*)state->regs[i], context);
03132             set_context_reg(csw, &new_context, i, value, TRUE);
03133             break;
03134         case RULE_VAL_EXPRESSION:
03135             value = eval_expression(module, csw, (const unsigned char*)state->regs[i], context);
03136             set_context_reg(csw, &new_context, i, value, FALSE);
03137             break;
03138         }
03139     }
03140     *context = new_context;
03141 }
03142 
03143 /***********************************************************************
03144  *           dwarf2_virtual_unwind
03145  *
03146  */
03147 BOOL dwarf2_virtual_unwind(struct cpu_stack_walk* csw, ULONG_PTR ip, CONTEXT* context, ULONG_PTR* cfa)
03148 {
03149     struct module_pair pair;
03150     struct frame_info info;
03151     dwarf2_traverse_context_t cie_ctx, fde_ctx;
03152     struct module_format* modfmt;
03153     const unsigned char* end;
03154     DWORD_PTR delta;
03155 
03156     if (!(pair.pcs = process_find_by_handle(csw->hProcess)) ||
03157         !(pair.requested = module_find_by_addr(pair.pcs, ip, DMT_UNKNOWN)) ||
03158         !module_get_debug(&pair))
03159         return FALSE;
03160     modfmt = pair.effective->format_info[DFI_DWARF];
03161     if (!modfmt) return FALSE;
03162     memset(&info, 0, sizeof(info));
03163     fde_ctx.data = modfmt->u.dwarf2_info->eh_frame.address;
03164     fde_ctx.end_data = fde_ctx.data + modfmt->u.dwarf2_info->eh_frame.size;
03165     fde_ctx.word_size = modfmt->u.dwarf2_info->word_size;
03166     /* let offsets relative to the eh_frame sections be correctly computed, as we'll map
03167      * in this process the IMAGE section at a different address as the one expected by
03168      * the image
03169      */
03170     delta = pair.effective->module.BaseOfImage + modfmt->u.dwarf2_info->eh_frame.rva -
03171         (DWORD_PTR)modfmt->u.dwarf2_info->eh_frame.address;
03172     if (!dwarf2_get_cie(ip, pair.effective, delta, &fde_ctx, &cie_ctx, &info, TRUE))
03173     {
03174         fde_ctx.data = modfmt->u.dwarf2_info->debug_frame.address;
03175         fde_ctx.end_data = fde_ctx.data + modfmt->u.dwarf2_info->debug_frame.size;
03176         fde_ctx.word_size = modfmt->u.dwarf2_info->word_size;
03177         delta = pair.effective->reloc_delta;
03178         if (!dwarf2_get_cie(ip, pair.effective, delta, &fde_ctx, &cie_ctx, &info, FALSE))
03179         {
03180             TRACE("Couldn't find information for %lx\n", ip);
03181             return FALSE;
03182         }
03183     }
03184 
03185     TRACE("function %lx/%lx code_align %lu data_align %ld retaddr %s\n",
03186           ip, info.ip, info.code_align, info.data_align,
03187           dbghelp_current_cpu->fetch_regname(dbghelp_current_cpu->map_dwarf_register(info.retaddr_reg)));
03188 
03189     /* if at very beginning of function, return and use default unwinder */
03190     if (ip == info.ip) return FALSE;
03191     execute_cfa_instructions(&cie_ctx, ip, &info);
03192 
03193     if (info.aug_z_format)  /* get length of augmentation data */
03194     {
03195         ULONG_PTR len = dwarf2_leb128_as_unsigned(&fde_ctx);
03196         end = fde_ctx.data + len;
03197     }
03198     else end = NULL;
03199     dwarf2_parse_augmentation_ptr(&fde_ctx, info.lsda_encoding); /* handler_data */
03200     if (end) fde_ctx.data = end;
03201 
03202     execute_cfa_instructions(&fde_ctx, ip, &info);
03203     apply_frame_state(pair.effective, csw, context, &info.state, cfa);
03204 
03205     return TRUE;
03206 }
03207 
03208 static void dwarf2_location_compute(struct process* pcs,
03209                                     const struct module_format* modfmt,
03210                                     const struct symt_function* func,
03211                                     struct location* loc)
03212 {
03213     struct location             frame;
03214     DWORD_PTR                   ip;
03215     int                         err;
03216     dwarf2_traverse_context_t   lctx;
03217 
03218     if (!func->container || func->container->tag != SymTagCompiland)
03219     {
03220         WARN("We'd expect function %s's container to exist and be a compiland\n", func->hash_elt.name);
03221         err = loc_err_internal;
03222     }
03223     else
03224     {
03225         /* instruction pointer relative to compiland's start */
03226         ip = pcs->ctx_frame.InstructionOffset - ((struct symt_compiland*)func->container)->address;
03227 
03228         if ((err = loc_compute_frame(pcs, modfmt, func, ip, &frame)) == 0)
03229         {
03230             switch (loc->kind)
03231             {
03232             case loc_dwarf2_location_list:
03233                 /* Then, if the variable has a location list, find it !! */
03234                 if (dwarf2_lookup_loclist(modfmt,
03235                                           modfmt->u.dwarf2_info->debug_loc.address + loc->offset,
03236                                           ip, &lctx))
03237                     goto do_compute;
03238                 err = loc_err_out_of_scope;
03239                 break;
03240             case loc_dwarf2_block:
03241                 /* or if we have a copy of an existing block, get ready for it */
03242                 {
03243                     unsigned*   ptr = (unsigned*)loc->offset;
03244 
03245                     lctx.data = (const BYTE*)(ptr + 1);
03246                     lctx.end_data = lctx.data + *ptr;
03247                     lctx.word_size = modfmt->u.dwarf2_info->word_size;
03248                 }
03249             do_compute:
03250                 /* now get the variable */
03251                 err = compute_location(&lctx, loc, pcs->handle, &frame);
03252                 break;
03253             case loc_register:
03254             case loc_regrel:
03255                 /* nothing to do */
03256                 break;
03257             default:
03258                 WARN("Unsupported local kind %d\n", loc->kind);
03259                 err = loc_err_internal;
03260             }
03261         }
03262     }
03263     if (err < 0)
03264     {
03265         loc->kind = loc_register;
03266         loc->reg = err;
03267     }
03268 }
03269 
03270 static void dwarf2_module_remove(struct process* pcs, struct module_format* modfmt)
03271 {
03272     HeapFree(GetProcessHeap(), 0, modfmt);
03273 }
03274 
03275 static inline BOOL dwarf2_init_section(dwarf2_section_t* section, struct image_file_map* fmap,
03276                                        const char* sectname, struct image_section_map* ism)
03277 {
03278     struct image_section_map    local_ism;
03279 
03280     if (!ism) ism = &local_ism;
03281     if (!image_find_section(fmap, sectname, ism))
03282     {
03283         section->address = NULL;
03284         section->size    = 0;
03285         section->rva     = 0;
03286         return FALSE;
03287     }
03288 
03289     section->address = (const BYTE*)image_map_section(ism);
03290     section->size    = image_get_map_size(ism);
03291     section->rva     = image_get_map_rva(ism);
03292     return TRUE;
03293 }
03294 
03295 BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
03296                   const struct elf_thunk_area* thunks,
03297                   struct image_file_map* fmap)
03298 {
03299     dwarf2_section_t    eh_frame, section[section_max];
03300     dwarf2_traverse_context_t   mod_ctx;
03301     struct image_section_map    debug_sect, debug_str_sect, debug_abbrev_sect,
03302                                 debug_line_sect, debug_ranges_sect, eh_frame_sect;
03303     BOOL                ret = TRUE;
03304     struct module_format* dwarf2_modfmt;
03305 
03306     dwarf2_init_section(&eh_frame,                fmap, ".eh_frame",     &eh_frame_sect);
03307     dwarf2_init_section(&section[section_debug],  fmap, ".debug_info",   &debug_sect);
03308     dwarf2_init_section(&section[section_abbrev], fmap, ".debug_abbrev", &debug_abbrev_sect);
03309     dwarf2_init_section(&section[section_string], fmap, ".debug_str",    &debug_str_sect);
03310     dwarf2_init_section(&section[section_line],   fmap, ".debug_line",   &debug_line_sect);
03311     dwarf2_init_section(&section[section_ranges], fmap, ".debug_ranges", &debug_ranges_sect);
03312 
03313     /* to do anything useful we need either .eh_frame or .debug_info */
03314     if ((!eh_frame.address || eh_frame.address == IMAGE_NO_MAP) &&
03315         (!section[section_debug].address || section[section_debug].address == IMAGE_NO_MAP))
03316     {
03317         ret = FALSE;
03318         goto leave;
03319     }
03320 
03321     if (fmap->modtype == DMT_ELF && debug_sect.fmap)
03322     {
03323         /* debug info might have a different base address than .so file
03324          * when elf file is prelinked after splitting off debug info
03325          * adjust symbol base addresses accordingly
03326          */
03327         load_offset += fmap->u.elf.elf_start - debug_sect.fmap->u.elf.elf_start;
03328     }
03329 
03330     TRACE("Loading Dwarf2 information for %s\n", debugstr_w(module->module.ModuleName));
03331 
03332     mod_ctx.data = section[section_debug].address;
03333     mod_ctx.end_data = mod_ctx.data + section[section_debug].size;
03334     mod_ctx.word_size = 0; /* will be correctly set later on */
03335 
03336     dwarf2_modfmt = HeapAlloc(GetProcessHeap(), 0,
03337                               sizeof(*dwarf2_modfmt) + sizeof(*dwarf2_modfmt->u.dwarf2_info));
03338     if (!dwarf2_modfmt)
03339     {
03340         ret = FALSE;
03341         goto leave;
03342     }
03343     dwarf2_modfmt->module = module;
03344     dwarf2_modfmt->remove = dwarf2_module_remove;
03345     dwarf2_modfmt->loc_compute = dwarf2_location_compute;
03346     dwarf2_modfmt->u.dwarf2_info = (struct dwarf2_module_info_s*)(dwarf2_modfmt + 1);
03347     dwarf2_modfmt->u.dwarf2_info->word_size = 0; /* will be correctly set later on */
03348     dwarf2_modfmt->module->format_info[DFI_DWARF] = dwarf2_modfmt;
03349 
03350     /* As we'll need later some sections' content, we won't unmap these
03351      * sections upon existing this function
03352      */
03353     dwarf2_init_section(&dwarf2_modfmt->u.dwarf2_info->debug_loc,   fmap, ".debug_loc",   NULL);
03354     dwarf2_init_section(&dwarf2_modfmt->u.dwarf2_info->debug_frame, fmap, ".debug_frame", NULL);
03355     dwarf2_modfmt->u.dwarf2_info->eh_frame = eh_frame;
03356 
03357     while (mod_ctx.data < mod_ctx.end_data)
03358     {
03359         dwarf2_parse_compilation_unit(section, dwarf2_modfmt->module, thunks, &mod_ctx, load_offset);
03360     }
03361     dwarf2_modfmt->module->module.SymType = SymDia;
03362     dwarf2_modfmt->module->module.CVSig = 'D' | ('W' << 8) | ('A' << 16) | ('R' << 24);
03363     /* FIXME: we could have a finer grain here */
03364     dwarf2_modfmt->module->module.GlobalSymbols = TRUE;
03365     dwarf2_modfmt->module->module.TypeInfo = TRUE;
03366     dwarf2_modfmt->module->module.SourceIndexed = TRUE;
03367     dwarf2_modfmt->module->module.Publics = TRUE;
03368 
03369 leave:
03370     image_unmap_section(&debug_sect);
03371     image_unmap_section(&debug_abbrev_sect);
03372     image_unmap_section(&debug_str_sect);
03373     image_unmap_section(&debug_line_sect);
03374     image_unmap_section(&debug_ranges_sect);
03375     if (!ret) image_unmap_section(&eh_frame_sect);
03376 
03377     return ret;
03378 }

Generated on Fri May 25 2012 04:21:20 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.