dbghelp: Add support for loading dwarf debug information out of PE images.
This commit is contained in:
parent
1c238c77f7
commit
bc38d3eaac
|
@ -369,7 +369,7 @@ int elf_is_in_thunk_area(unsigned long addr,
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
for (i = 0; thunks[i].symname; i++)
|
if (thunks) for (i = 0; thunks[i].symname; i++)
|
||||||
{
|
{
|
||||||
if (addr >= thunks[i].rva_start && addr < thunks[i].rva_end)
|
if (addr >= thunks[i].rva_start && addr < thunks[i].rva_end)
|
||||||
return i;
|
return i;
|
||||||
|
|
|
@ -98,6 +98,17 @@ static BOOL pe_load_symbol_table(struct module* module, IMAGE_NT_HEADERS* nth, v
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void* pe_get_sect(IMAGE_NT_HEADERS* nth, void* mapping,
|
||||||
|
IMAGE_SECTION_HEADER* sect)
|
||||||
|
{
|
||||||
|
return (sect) ? RtlImageRvaToVa(nth, mapping, sect->VirtualAddress, NULL) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline DWORD pe_get_sect_size(IMAGE_SECTION_HEADER* sect)
|
||||||
|
{
|
||||||
|
return (sect) ? sect->SizeOfRawData : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* pe_load_stabs
|
* pe_load_stabs
|
||||||
*
|
*
|
||||||
|
@ -108,39 +119,85 @@ static BOOL pe_load_stabs(const struct process* pcs, struct module* module,
|
||||||
void* mapping, IMAGE_NT_HEADERS* nth)
|
void* mapping, IMAGE_NT_HEADERS* nth)
|
||||||
{
|
{
|
||||||
IMAGE_SECTION_HEADER* section;
|
IMAGE_SECTION_HEADER* section;
|
||||||
int i, stabsize = 0, stabstrsize = 0;
|
IMAGE_SECTION_HEADER* sect_stabs = NULL;
|
||||||
unsigned int stabs = 0, stabstr = 0;
|
IMAGE_SECTION_HEADER* sect_stabstr = NULL;
|
||||||
BOOL ret = FALSE;
|
int i;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
section = (IMAGE_SECTION_HEADER*)
|
section = (IMAGE_SECTION_HEADER*)
|
||||||
((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
|
((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
|
||||||
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
|
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
|
||||||
{
|
{
|
||||||
if (!strcasecmp((const char*)section->Name, ".stab"))
|
if (!strcasecmp((const char*)section->Name, ".stab")) sect_stabs = section;
|
||||||
{
|
else if (!strncasecmp((const char*)section->Name, ".stabstr", 8)) sect_stabstr = section;
|
||||||
stabs = section->VirtualAddress;
|
|
||||||
stabsize = section->SizeOfRawData;
|
|
||||||
}
|
}
|
||||||
else if (!strncasecmp((const char*)section->Name, ".stabstr", 8))
|
if (sect_stabs && sect_stabstr)
|
||||||
{
|
|
||||||
stabstr = section->VirtualAddress;
|
|
||||||
stabstrsize = section->SizeOfRawData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stabstrsize && stabsize)
|
|
||||||
{
|
{
|
||||||
ret = stabs_parse(module,
|
ret = stabs_parse(module,
|
||||||
module->module.BaseOfImage - nth->OptionalHeader.ImageBase,
|
module->module.BaseOfImage - nth->OptionalHeader.ImageBase,
|
||||||
RtlImageRvaToVa(nth, mapping, stabs, NULL),
|
pe_get_sect(nth, mapping, sect_stabs), pe_get_sect_size(sect_stabs),
|
||||||
stabsize,
|
pe_get_sect(nth, mapping, sect_stabstr), pe_get_sect_size(sect_stabstr),
|
||||||
RtlImageRvaToVa(nth, mapping, stabstr, NULL),
|
|
||||||
stabstrsize,
|
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
if (ret) pe_load_symbol_table(module, nth, mapping);
|
if (ret) pe_load_symbol_table(module, nth, mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("%s the STABS debug info\n", ret ? "successfully loaded" : "failed to load");
|
TRACE("%s the STABS debug info\n", ret ? "successfully loaded" : "failed to load");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* pe_load_dwarf
|
||||||
|
*
|
||||||
|
* look for dwarf information in PE header (it's also a way for the mingw compiler
|
||||||
|
* to provide its debugging information)
|
||||||
|
*/
|
||||||
|
static BOOL pe_load_dwarf(const struct process* pcs, struct module* module,
|
||||||
|
void* mapping, IMAGE_NT_HEADERS* nth)
|
||||||
|
{
|
||||||
|
IMAGE_SECTION_HEADER* section;
|
||||||
|
IMAGE_SECTION_HEADER* sect_debuginfo = NULL;
|
||||||
|
IMAGE_SECTION_HEADER* sect_debugstr = NULL;
|
||||||
|
IMAGE_SECTION_HEADER* sect_debugabbrev = NULL;
|
||||||
|
IMAGE_SECTION_HEADER* sect_debugline = NULL;
|
||||||
|
IMAGE_SECTION_HEADER* sect_debugloc = NULL;
|
||||||
|
int i;
|
||||||
|
const char* strtable;
|
||||||
|
const char* sectname;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
if (nth->FileHeader.PointerToSymbolTable && nth->FileHeader.NumberOfSymbols)
|
||||||
|
/* FIXME: no way to get strtable size */
|
||||||
|
strtable = (const char*)mapping + nth->FileHeader.PointerToSymbolTable +
|
||||||
|
nth->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL);
|
||||||
|
else strtable = NULL;
|
||||||
|
|
||||||
|
section = (IMAGE_SECTION_HEADER*)
|
||||||
|
((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
|
||||||
|
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
|
||||||
|
{
|
||||||
|
sectname = (const char*)section->Name;
|
||||||
|
/* long section names start with a '/' (at least on MinGW32) */
|
||||||
|
if (*sectname == '/' && strtable)
|
||||||
|
sectname = strtable + atoi(sectname + 1);
|
||||||
|
if (!strcasecmp(sectname, ".debug_info")) sect_debuginfo = section;
|
||||||
|
else if (!strcasecmp(sectname, ".debug_str")) sect_debugstr = section;
|
||||||
|
else if (!strcasecmp(sectname, ".debug_abbrev")) sect_debugabbrev = section;
|
||||||
|
else if (!strcasecmp(sectname, ".debug_line")) sect_debugline = section;
|
||||||
|
else if (!strcasecmp(sectname, ".debug_loc")) sect_debugloc = section;
|
||||||
|
}
|
||||||
|
if (sect_debuginfo)
|
||||||
|
{
|
||||||
|
ret = dwarf2_parse(module,
|
||||||
|
module->module.BaseOfImage - nth->OptionalHeader.ImageBase,
|
||||||
|
NULL, /* FIXME: some thunks to deal with ? */
|
||||||
|
pe_get_sect(nth, mapping, sect_debuginfo), pe_get_sect_size(sect_debuginfo),
|
||||||
|
pe_get_sect(nth, mapping, sect_debugabbrev), pe_get_sect_size(sect_debugabbrev),
|
||||||
|
pe_get_sect(nth, mapping, sect_debugstr), pe_get_sect_size(sect_debugstr),
|
||||||
|
pe_get_sect(nth, mapping, sect_debugline), pe_get_sect_size(sect_debugline),
|
||||||
|
pe_get_sect(nth, mapping, sect_debugloc), pe_get_sect_size(sect_debugloc));
|
||||||
|
}
|
||||||
|
TRACE("%s the DWARF debug info\n", ret ? "successfully loaded" : "failed to load");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,6 +406,7 @@ BOOL pe_load_debug_info(const struct process* pcs, struct module* module)
|
||||||
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
|
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
|
||||||
{
|
{
|
||||||
ret = pe_load_stabs(pcs, module, mapping, nth) ||
|
ret = pe_load_stabs(pcs, module, mapping, nth) ||
|
||||||
|
pe_load_dwarf(pcs, module, mapping, nth) ||
|
||||||
pe_load_msc_debug_info(pcs, module, mapping, nth);
|
pe_load_msc_debug_info(pcs, module, mapping, nth);
|
||||||
/* if we still have no debug info (we could only get SymExport at this
|
/* if we still have no debug info (we could only get SymExport at this
|
||||||
* point), then do the SymExport except if we have an ELF container,
|
* point), then do the SymExport except if we have an ELF container,
|
||||||
|
|
Loading…
Reference in New Issue