Robert Shearman a écrit :
Keep the debuglink elf_file_map mapped until after elf_new_public_symbols is called, otherwise we could use unmapped memory.
this is still not the full valid solution... what should be done is: when we search for a given section, we should look first in the original .so, then, if not found, in the .gnu_debuglink one... your patch only covers the case where all relevant information is to be found in the .gnu_debuglink file, which is not guaranteed A+
Eric Pouech wrote:
Robert Shearman a écrit :
Keep the debuglink elf_file_map mapped until after elf_new_public_symbols is called, otherwise we could use unmapped memory.
this is still not the full valid solution... what should be done is: when we search for a given section, we should look first in the original .so, then, if not found, in the .gnu_debuglink one... your patch only covers the case where all relevant information is to be found in the .gnu_debuglink file, which is not guaranteed
And that should be easier for an interested person to do after this patch is applied, right? I was just interested in getting rid of bogus crc errors when using winedbg.
Robert Shearman a écrit :
Eric Pouech wrote:
Robert Shearman a écrit :
Keep the debuglink elf_file_map mapped until after elf_new_public_symbols is called, otherwise we could use unmapped memory.
this is still not the full valid solution... what should be done is: when we search for a given section, we should look first in the original .so, then, if not found, in the .gnu_debuglink one... your patch only covers the case where all relevant information is to be found in the .gnu_debuglink file, which is not guaranteed
And that should be easier for an interested person to do after this patch is applied, right? I was just interested in getting rid of bogus crc errors when using winedbg.
first, it's not exactly what your patch is entirely about... your patch ensures that the newly .gnu_debuglink mapped file is present for symbols resolution... and the bogus CRC errors come from the fact that we have an ERR for that, were it should be a WARN... a user could have different versions of the debug info files secondly, the correct fix will require a rewrite of the mapping algorithm itself, which is rather orthogonal to what you did my reco would simply to downgrade the ERR to a WARN if you don't want to go into the full fix A+
Eric Pouech a écrit :
Robert Shearman a écrit :
Eric Pouech wrote:
Robert Shearman a écrit :
Keep the debuglink elf_file_map mapped until after elf_new_public_symbols is called, otherwise we could use unmapped memory.
this is still not the full valid solution... what should be done is: when we search for a given section, we should look first in the original .so, then, if not found, in the .gnu_debuglink one... your patch only covers the case where all relevant information is to be found in the .gnu_debuglink file, which is not guaranteed
And that should be easier for an interested person to do after this patch is applied, right? I was just interested in getting rid of bogus crc errors when using winedbg.
first, it's not exactly what your patch is entirely about... your patch ensures that the newly .gnu_debuglink mapped file is present for symbols resolution... and the bogus CRC errors come from the fact that we have an ERR for that, were it should be a WARN... a user could have different versions of the debug info files secondly, the correct fix will require a rewrite of the mapping algorithm itself, which is rather orthogonal to what you did my reco would simply to downgrade the ERR to a WARN if you don't want to go into the full fix A+
Rob, Peter
as you both were looking for solution to public symbols hashing in .gnu_link files, the attached patches should fix it could you test them to ensure that they really fix it ?
(order to apply patches: 1/ dbghelp-elf-map, 2/ dbghelp-elf-alternate, 3/ dbghelp-elf-link-alternate)
A+
[DbgHelp]: allowed to add an alternate file_map for an ELF file (where to
From: Eric Pouech eric.pouech@wanadoo.fr
look for its debug information) ---
dlls/dbghelp/elf_module.c | 37 ++++++++++++++++++++++++------------- 1 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index b0cc90c..41a37f9 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -115,6 +115,7 @@ struct elf_file_map unsigned with_crc; unsigned long crc; const char* shstrtab; + struct elf_file_map* alternate; /* another ELF file (linked to this one) */ };
struct elf_section_map @@ -167,6 +168,7 @@ static const char* elf_map_section(struc * elf_find_section * * Finds a section by name (and type) into memory from an ELF file + * or its alternate if any */ static BOOL elf_find_section(struct elf_file_map* fmap, const char* name, unsigned sht, struct elf_section_map* esm) @@ -179,15 +181,19 @@ static BOOL elf_find_section(struct elf_ fmap->shstrtab = elf_map_section(&hdr_esm); if (fmap->shstrtab == ELF_NO_MAP) return FALSE; } - for (i = 0; i < fmap->elfhdr.e_shnum; i++) + while (fmap) { - if (strcmp(fmap->shstrtab + fmap->sect[i].shdr.sh_name, name) == 0 && - (sht == SHT_NULL || sht == fmap->sect[i].shdr.sh_type)) + for (i = 0; i < fmap->elfhdr.e_shnum; i++) { - esm->fmap = fmap; - esm->sidx = i; - return TRUE; + if (strcmp(fmap->shstrtab + fmap->sect[i].shdr.sh_name, name) == 0 && + (sht == SHT_NULL || sht == fmap->sect[i].shdr.sh_type)) + { + esm->fmap = fmap; + esm->sidx = i; + return TRUE; + } } + fmap = fmap->alternate; } return FALSE; } @@ -257,6 +263,7 @@ static BOOL elf_map_file(const WCHAR* fi fmap->fd = -1; fmap->with_crc = 0; fmap->shstrtab = ELF_NO_MAP; + fmap->alternate = NULL;
/* check that the file exists, and that the module hasn't been loaded yet */ if (stat(filename, &statbuf) == -1 || S_ISDIR(statbuf.st_mode)) goto done; @@ -312,16 +319,20 @@ done: */ static void elf_unmap_file(struct elf_file_map* fmap) { - if (fmap->fd != -1) + while (fmap) { - struct elf_section_map esm; - esm.fmap = fmap; - for (esm.sidx = 0; esm.sidx < fmap->elfhdr.e_shnum; esm.sidx++) + if (fmap->fd != -1) { - elf_unmap_section(&esm); + struct elf_section_map esm; + esm.fmap = fmap; + for (esm.sidx = 0; esm.sidx < fmap->elfhdr.e_shnum; esm.sidx++) + { + elf_unmap_section(&esm); + } + HeapFree(GetProcessHeap(), 0, fmap->sect); + close(fmap->fd); } - HeapFree(GetProcessHeap(), 0, fmap->sect); - close(fmap->fd); + fmap = fmap->alternate; } }
[DbgHelp]: now handling the .gnu_debuglink files with the newly added
From: Eric Pouech eric.pouech@wanadoo.fr
alternate mechanism ---
dlls/dbghelp/elf_module.c | 118 +++++++++++++++++++-------------------------- 1 files changed, 51 insertions(+), 67 deletions(-)
diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index 41a37f9..4c5e53a 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -112,8 +112,6 @@ struct elf_file_map const char* mapped; }* sect; int fd; - unsigned with_crc; - unsigned long crc; const char* shstrtab; struct elf_file_map* alternate; /* another ELF file (linked to this one) */ }; @@ -261,7 +259,6 @@ static BOOL elf_map_file(const WCHAR* fi WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, filename, len, NULL, NULL);
fmap->fd = -1; - fmap->with_crc = 0; fmap->shstrtab = ELF_NO_MAP; fmap->alternate = NULL;
@@ -851,10 +848,18 @@ #define UPDC32(octet,crc) (crc_32_tab[(( #undef UPDC32 }
-static BOOL elf_load_debug_info_from_map(struct module* module, - struct elf_file_map* fmap, - struct pool* pool, - struct hash_table* ht_symtab); +static BOOL elf_check_debug_link(const WCHAR* file, struct elf_file_map* fmap, DWORD crc) +{ + BOOL ret; + if (!elf_map_file(file, fmap)) return FALSE; + if (!(ret = crc == calc_crc32(fmap))) + { + WARN("Bad CRC for file %s (got %08x while expecting %08x)\n", + debugstr_w(file), calc_crc32(fmap), crc); + elf_unmap_file(fmap); + } + return ret; +}
/****************************************************************** * elf_locate_debug_link @@ -875,20 +880,24 @@ static BOOL elf_load_debug_info_from_map * is the global debug file directory, and execdir has been turned * into a relative path)." (from GDB manual) */ -static WCHAR* elf_locate_debug_link(const char* filename, const WCHAR* loaded_file, - struct elf_file_map* fmap_link) +static BOOL elf_locate_debug_link(struct elf_file_map* fmap, const char* filename, + const WCHAR* loaded_file, DWORD crc) { static const WCHAR globalDebugDirW[] = {'/','u','s','r','/','l','i','b','/','d','e','b','u','g','/'}; static const WCHAR dotDebugW[] = {'.','d','e','b','u','g','/'}; const size_t globalDebugDirLen = sizeof(globalDebugDirW) / sizeof(WCHAR); size_t filename_len; - WCHAR* p; + WCHAR* p = NULL; WCHAR* slash; + struct elf_file_map* fmap_link = NULL; + + fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link)); + if (!fmap_link) return FALSE;
filename_len = MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, NULL, 0); p = HeapAlloc(GetProcessHeap(), 0, (globalDebugDirLen + strlenW(loaded_file) + 6 + 1 + filename_len + 1) * sizeof(WCHAR)); - if (!p) return FALSE; + if (!p) goto found;
/* we prebuild the string with "execdir" */ strcpyW(p, loaded_file); @@ -897,33 +906,34 @@ static WCHAR* elf_locate_debug_link(cons
/* testing execdir/filename */ MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len); - if (elf_map_file(p, fmap_link)) goto found; - - HeapValidate(GetProcessHeap(), 0, 0); + if (elf_check_debug_link(p, fmap_link, crc)) goto found;
/* testing execdir/.debug/filename */ memcpy(slash, dotDebugW, sizeof(dotDebugW)); MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash + sizeof(dotDebugW) / sizeof(WCHAR), filename_len); - if (elf_map_file(p, fmap_link)) goto found; + if (elf_check_debug_link(p, fmap_link, crc)) goto found;
/* testing globaldebugdir/execdir/filename */ memmove(p + globalDebugDirLen, p, (slash - p) * sizeof(WCHAR)); memcpy(p, globalDebugDirW, globalDebugDirLen * sizeof(WCHAR)); slash += globalDebugDirLen; MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len); - if (elf_map_file(p, fmap_link)) goto found; + if (elf_check_debug_link(p, fmap_link, crc)) goto found;
/* finally testing filename */ - if (elf_map_file(slash, fmap_link)) goto found; + if (elf_check_debug_link(slash, fmap_link, crc)) goto found;
- HeapFree(GetProcessHeap(), 0, p);
WARN("Couldn't locate or map %s\n", filename); - return NULL; + HeapFree(GetProcessHeap(), 0, p); + HeapFree(GetProcessHeap(), 0, fmap_link); + return FALSE;
found: TRACE("Located debug information file %s at %s\n", filename, debugstr_w(p)); - return p; + HeapFree(GetProcessHeap(), 0, p); + fmap->alternate = fmap_link; + return TRUE; }
/****************************************************************** @@ -932,10 +942,8 @@ found: * Parses a .gnu_debuglink section and loads the debug info from * the external file specified there. */ -static BOOL elf_debuglink_parse (struct module* module, - struct pool* pool, - struct hash_table* ht_symtab, - const BYTE* debuglink) +static BOOL elf_debuglink_parse(struct elf_file_map* fmap, struct module* module, + const BYTE* debuglink) { /* The content of a debug link section is: * 1/ a NULL terminated string, containing the file name for the @@ -943,28 +951,11 @@ static BOOL elf_debuglink_parse (struct * 2/ padding on 4 byte boundary * 3/ CRC of the linked ELF file */ - BOOL ret = FALSE; const char* dbg_link = (char*)debuglink; - struct elf_file_map fmap_link; - WCHAR* link_file; + DWORD crc;
- link_file = elf_locate_debug_link(dbg_link, module->module.LoadedImageName, &fmap_link); - - if (link_file) - { - fmap_link.crc = *(const DWORD*)(dbg_link + ((DWORD_PTR)(strlen(dbg_link) + 4) & ~3)); - fmap_link.with_crc = 1; - ret = elf_load_debug_info_from_map(module, &fmap_link, pool, - ht_symtab); - if (ret) - strcpyW(module->module.LoadedPdbName,link_file); - else - WARN("Couldn't load debug information from %s\n", debugstr_w(link_file)); - elf_unmap_file(&fmap_link); - HeapFree(GetProcessHeap(), 0, link_file); - } - - return ret; + crc = *(const DWORD*)(dbg_link + ((DWORD_PTR)(strlen(dbg_link) + 4) & ~3)); + return elf_locate_debug_link(fmap, dbg_link, module->module.LoadedImageName, crc); }
/****************************************************************** @@ -997,14 +988,6 @@ static BOOL elf_load_debug_info_from_map {NULL, 0, 0, 0} };
- if (fmap->with_crc && (fmap->crc != calc_crc32(fmap))) - { - ERR("Bad CRC for module %s (got %08x while expecting %08lx)\n", - debugstr_w(module->module.LoadedImageName), calc_crc32(fmap), fmap->crc); - /* we don't tolerate mis-matched files */ - return FALSE; - } - module->module.SymType = SymExport;
/* create a hash table for the symtab */ @@ -1017,6 +1000,22 @@ static BOOL elf_load_debug_info_from_map debug_line_sect, debug_loclist_sect; struct elf_section_map debuglink_sect;
+ /* if present, add the .gnu_debuglink file as an alternate to current one */ + if (elf_find_section(fmap, ".gnu_debuglink", SHT_NULL, &debuglink_sect)) + { + const BYTE* dbg_link; + + dbg_link = (const BYTE*)elf_map_section(&debuglink_sect); + if (dbg_link != ELF_NO_MAP) + { + lret = elf_debuglink_parse(fmap, module, dbg_link); + if (!lret) + WARN("Couldn't load linked debug file for %s\n", + debugstr_w(module->module.ModuleName)); + ret = ret || lret; + } + elf_unmap_section(&debuglink_sect); + } if (elf_find_section(fmap, ".stab", SHT_NULL, &stab_sect) && elf_find_section(fmap, ".stabstr", SHT_NULL, &stabstr_sect)) { @@ -1083,21 +1082,6 @@ static BOOL elf_load_debug_info_from_map elf_unmap_section(&debug_line_sect); elf_unmap_section(&debug_loclist_sect); } - if (elf_find_section(fmap, ".gnu_debuglink", SHT_NULL, &debuglink_sect)) - { - const BYTE* dbg_link; - - dbg_link = (const BYTE*)elf_map_section(&debuglink_sect); - if (dbg_link != ELF_NO_MAP) - { - lret = elf_debuglink_parse(module, pool, ht_symtab, dbg_link); - if (!lret) - WARN("Couldn't load linked debug file for %s\n", - debugstr_w(module->module.ModuleName)); - ret = ret || lret; - } - elf_unmap_section(&debuglink_sect); - } } if (strstrW(module->module.ModuleName, S_ElfW) || !strcmpW(module->module.ModuleName, S_WineLoaderW))
[DbgHelp]: rewrote the ELF section mapper for better data encapsulation
From: Eric Pouech eric.pouech@wanadoo.fr
---
dlls/dbghelp/elf_module.c | 273 +++++++++++++++++++++++---------------------- 1 files changed, 137 insertions(+), 136 deletions(-)
diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index 7758199..b0cc90c 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -114,6 +114,13 @@ struct elf_file_map int fd; unsigned with_crc; unsigned long crc; + const char* shstrtab; +}; + +struct elf_section_map +{ + struct elf_file_map* fmap; + unsigned sidx; };
struct symtab_elt @@ -137,21 +144,52 @@ struct elf_thunk_area * * Maps a single section into memory from an ELF file */ -static const char* elf_map_section(struct elf_file_map* fmap, int sidx) +static const char* elf_map_section(struct elf_section_map* esm) { unsigned pgsz = getpagesize(); unsigned ofst, size;
- if (sidx < 0 || sidx >= fmap->elfhdr.e_shnum || - fmap->sect[sidx].shdr.sh_type == SHT_NOBITS) + if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum || + esm->fmap->sect[esm->sidx].shdr.sh_type == SHT_NOBITS) return ELF_NO_MAP; + /* align required information on page size (we assume pagesize is a power of 2) */ - ofst = fmap->sect[sidx].shdr.sh_offset & ~(pgsz - 1); - size = ((fmap->sect[sidx].shdr.sh_offset + - fmap->sect[sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst; - fmap->sect[sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fmap->fd, ofst); - if (fmap->sect[sidx].mapped == ELF_NO_MAP) return ELF_NO_MAP; - return fmap->sect[sidx].mapped + (fmap->sect[sidx].shdr.sh_offset & (pgsz - 1)); + ofst = esm->fmap->sect[esm->sidx].shdr.sh_offset & ~(pgsz - 1); + size = ((esm->fmap->sect[esm->sidx].shdr.sh_offset + + esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst; + esm->fmap->sect[esm->sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE, + esm->fmap->fd, ofst); + if (esm->fmap->sect[esm->sidx].mapped == ELF_NO_MAP) return ELF_NO_MAP; + return esm->fmap->sect[esm->sidx].mapped + (esm->fmap->sect[esm->sidx].shdr.sh_offset & (pgsz - 1)); +} + +/****************************************************************** + * elf_find_section + * + * Finds a section by name (and type) into memory from an ELF file + */ +static BOOL elf_find_section(struct elf_file_map* fmap, const char* name, + unsigned sht, struct elf_section_map* esm) +{ + unsigned i; + + if (fmap->shstrtab == ELF_NO_MAP) + { + struct elf_section_map hdr_esm = {fmap, fmap->elfhdr.e_shstrndx}; + fmap->shstrtab = elf_map_section(&hdr_esm); + if (fmap->shstrtab == ELF_NO_MAP) return FALSE; + } + for (i = 0; i < fmap->elfhdr.e_shnum; i++) + { + if (strcmp(fmap->shstrtab + fmap->sect[i].shdr.sh_name, name) == 0 && + (sht == SHT_NULL || sht == fmap->sect[i].shdr.sh_type)) + { + esm->fmap = fmap; + esm->sidx = i; + return TRUE; + } + } + return FALSE; }
/****************************************************************** @@ -159,32 +197,41 @@ static const char* elf_map_section(struc * * Unmaps a single section from memory */ -static void elf_unmap_section(struct elf_file_map* fmap, int sidx) +static void elf_unmap_section(struct elf_section_map* esm) { - if (sidx >= 0 && sidx < fmap->elfhdr.e_shnum && fmap->sect[sidx].mapped != ELF_NO_MAP) + if (esm->sidx >= 0 && esm->sidx < esm->fmap->elfhdr.e_shnum && esm->fmap->sect[esm->sidx].mapped != ELF_NO_MAP) { unsigned pgsz = getpagesize(); unsigned ofst, size;
- ofst = fmap->sect[sidx].shdr.sh_offset & ~(pgsz - 1); - size = ((fmap->sect[sidx].shdr.sh_offset + - fmap->sect[sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst; - if (munmap((char*)fmap->sect[sidx].mapped, size) < 0) + ofst = esm->fmap->sect[esm->sidx].shdr.sh_offset & ~(pgsz - 1); + size = ((esm->fmap->sect[esm->sidx].shdr.sh_offset + + esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst; + if (munmap((char*)esm->fmap->sect[esm->sidx].mapped, size) < 0) WARN("Couldn't unmap the section\n"); - fmap->sect[sidx].mapped = ELF_NO_MAP; + esm->fmap->sect[esm->sidx].mapped = ELF_NO_MAP; } }
+static void elf_end_find(struct elf_file_map* fmap) +{ + struct elf_section_map esm; + + esm.fmap = fmap; esm.sidx = fmap->elfhdr.e_shstrndx; + elf_unmap_section(&esm); + fmap->shstrtab = ELF_NO_MAP; +} + /****************************************************************** * elf_get_map_size * * Get the size of an ELF section */ -static inline unsigned elf_get_map_size(struct elf_file_map* fmap, int sidx) +static inline unsigned elf_get_map_size(struct elf_section_map* esm) { - if (sidx < 0 || sidx >= fmap->elfhdr.e_shnum) + if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum) return 0; - return fmap->sect[sidx].shdr.sh_size; + return esm->fmap->sect[esm->sidx].shdr.sh_size; }
/****************************************************************** @@ -209,6 +256,7 @@ static BOOL elf_map_file(const WCHAR* fi
fmap->fd = -1; fmap->with_crc = 0; + fmap->shstrtab = ELF_NO_MAP;
/* check that the file exists, and that the module hasn't been loaded yet */ if (stat(filename, &statbuf) == -1 || S_ISDIR(statbuf.st_mode)) goto done; @@ -266,10 +314,11 @@ static void elf_unmap_file(struct elf_fi { if (fmap->fd != -1) { - int i; - for (i = 0; i < fmap->elfhdr.e_shnum; i++) + struct elf_section_map esm; + esm.fmap = fmap; + for (esm.sidx = 0; esm.sidx < fmap->elfhdr.e_shnum; esm.sidx++) { - elf_unmap_section(fmap, i); + elf_unmap_section(&esm); } HeapFree(GetProcessHeap(), 0, fmap->sect); close(fmap->fd); @@ -302,7 +351,7 @@ int elf_is_in_thunk_area(unsigned long a */ static void elf_hash_symtab(struct module* module, struct pool* pool, struct hash_table* ht_symtab, struct elf_file_map* fmap, - int symtab_idx, struct elf_thunk_area* thunks) + struct elf_thunk_area* thunks) { int i, j, nsym; const char* strp; @@ -311,12 +360,16 @@ static void elf_hash_symtab(struct modul const char* ptr; const Elf32_Sym* symp; struct symtab_elt* ste; + struct elf_section_map esm, esm_str;
- symp = (const Elf32_Sym*)elf_map_section(fmap, symtab_idx); - strp = elf_map_section(fmap, fmap->sect[symtab_idx].shdr.sh_link); - if (symp == ELF_NO_MAP || strp == ELF_NO_MAP) return; + if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &esm) && + !elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &esm)) return; + if ((symp = (const Elf32_Sym*)elf_map_section(&esm)) == ELF_NO_MAP) return; + esm_str.fmap = fmap; + esm_str.sidx = fmap->sect[esm.sidx].shdr.sh_link; + if ((strp = elf_map_section(&esm_str)) == ELF_NO_MAP) return;
- nsym = elf_get_map_size(fmap, symtab_idx) / sizeof(*symp); + nsym = elf_get_map_size(&esm) / sizeof(*symp);
for (j = 0; thunks[j].symname; j++) thunks[j].rva_start = thunks[j].rva_end = 0; @@ -922,12 +975,6 @@ static BOOL elf_load_debug_info_from_map struct hash_table* ht_symtab) { BOOL ret = FALSE, lret; - const char* shstrtab; - int i; - int symtab_sect, dynsym_sect, stab_sect, stabstr_sect; - int debug_sect, debug_str_sect, debug_abbrev_sect; - int debug_line_sect, debug_loclist_sect; - int debuglink_sect; struct elf_thunk_area thunks[] = { {"__wine_spec_import_thunks", THUNK_ORDINAL_NOTYPE, 0, 0}, /* inter DLL calls */ @@ -947,77 +994,32 @@ static BOOL elf_load_debug_info_from_map return FALSE; }
- /* - * Next, we need to find a few of the internal ELF headers within - * this thing. We need the main executable header, and the section - * table. - */ - shstrtab = elf_map_section(fmap, fmap->elfhdr.e_shstrndx); - if (shstrtab == ELF_NO_MAP) return FALSE; - - symtab_sect = dynsym_sect = stab_sect = stabstr_sect = -1; - debug_sect = debug_str_sect = debug_abbrev_sect = -1; - debug_line_sect = debug_loclist_sect = -1; - debuglink_sect = -1; - - for (i = 0; i < fmap->elfhdr.e_shnum; i++) - { - if (strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".stab") == 0) - stab_sect = i; - if (strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".stabstr") == 0) - stabstr_sect = i; - if (strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".debug_info") == 0) - debug_sect = i; - if (strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".debug_str") == 0) - debug_str_sect = i; - if (strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".debug_abbrev") == 0) - debug_abbrev_sect = i; - if (strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".debug_line") == 0) - debug_line_sect = i; - if (strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".debug_loc") == 0) - debug_loclist_sect = i; - if (strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".gnu_debuglink") == 0) - debuglink_sect = i; - if ((strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".symtab") == 0) && - (fmap->sect[i].shdr.sh_type == SHT_SYMTAB)) - symtab_sect = i; - if ((strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".dynsym") == 0) && - (fmap->sect[i].shdr.sh_type == SHT_DYNSYM)) - dynsym_sect = i; - } - elf_unmap_section(fmap, fmap->elfhdr.e_shstrndx); - shstrtab = NULL; - - if (symtab_sect == -1) - { - /* if we don't have a symtab but a dynsym, process the dynsym - * section instead. It'll contain less (relevant) information, - * but it'll be better than nothing - */ - if (dynsym_sect == -1) return FALSE; - symtab_sect = dynsym_sect; - } - module->module.SymType = SymExport;
/* create a hash table for the symtab */ - elf_hash_symtab(module, pool, ht_symtab, fmap, symtab_sect, thunks); + elf_hash_symtab(module, pool, ht_symtab, fmap, thunks);
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) { - if (stab_sect != -1 && stabstr_sect != -1) + struct elf_section_map stab_sect, stabstr_sect; + struct elf_section_map debug_sect, debug_str_sect, debug_abbrev_sect, + debug_line_sect, debug_loclist_sect; + struct elf_section_map debuglink_sect; + + if (elf_find_section(fmap, ".stab", SHT_NULL, &stab_sect) && + elf_find_section(fmap, ".stabstr", SHT_NULL, &stabstr_sect)) { const char* stab; const char* stabstr;
- stab = elf_map_section(fmap, stab_sect); - stabstr = elf_map_section(fmap, stabstr_sect); + stab = elf_map_section(&stab_sect); + stabstr = elf_map_section(&stabstr_sect); if (stab != ELF_NO_MAP && stabstr != ELF_NO_MAP) { /* OK, now just parse all of the stabs. */ lret = stabs_parse(module, module->elf_info->elf_addr, - stab, elf_get_map_size(fmap, stab_sect), - stabstr, elf_get_map_size(fmap, stabstr_sect)); + stab, elf_get_map_size(&stab_sect), + stabstr, elf_get_map_size(&stabstr_sect)); if (lret) /* and fill in the missing information for stabs */ elf_finish_stabs_info(module, ht_symtab); @@ -1026,11 +1028,10 @@ static BOOL elf_load_debug_info_from_map ret = ret || lret; } else lret = FALSE; - elf_unmap_section(fmap, stab_sect); - elf_unmap_section(fmap, stabstr_sect); - + elf_unmap_section(&stab_sect); + elf_unmap_section(&stabstr_sect); } - if (debug_sect != -1) + if (elf_find_section(fmap, ".debug_info", SHT_NULL, &debug_sect)) { /* Dwarf 2 debug information */ const BYTE* dw2_debug; @@ -1041,36 +1042,41 @@ static BOOL elf_load_debug_info_from_map
TRACE("Loading Dwarf2 information for %s\n", module->module_name);
- dw2_debug = (const BYTE*) elf_map_section(fmap, debug_sect); - dw2_debug_abbrev = (const BYTE*) elf_map_section(fmap, debug_abbrev_sect); - dw2_debug_str = (const BYTE*) elf_map_section(fmap, debug_str_sect); - dw2_debug_line = (const BYTE*) elf_map_section(fmap, debug_line_sect); - dw2_debug_loclist = (const BYTE*) elf_map_section(fmap, debug_loclist_sect); + elf_find_section(fmap, ".debug_str", SHT_NULL, &debug_str_sect); + elf_find_section(fmap, ".debug_abbrev", SHT_NULL, &debug_abbrev_sect); + elf_find_section(fmap, ".debug_line", SHT_NULL, &debug_line_sect); + elf_find_section(fmap, ".debug_loc", SHT_NULL, &debug_loclist_sect); + + dw2_debug = (const BYTE*)elf_map_section(&debug_sect); + dw2_debug_abbrev = (const BYTE*)elf_map_section(&debug_abbrev_sect); + dw2_debug_str = (const BYTE*)elf_map_section(&debug_str_sect); + dw2_debug_line = (const BYTE*)elf_map_section(&debug_line_sect); + dw2_debug_loclist = (const BYTE*)elf_map_section(&debug_loclist_sect); if (dw2_debug != ELF_NO_MAP && dw2_debug_abbrev != ELF_NO_MAP && dw2_debug_str != ELF_NO_MAP) { /* OK, now just parse dwarf2 debug infos. */ lret = dwarf2_parse(module, module->elf_info->elf_addr, thunks, - dw2_debug, elf_get_map_size(fmap, debug_sect), - dw2_debug_abbrev, elf_get_map_size(fmap, debug_abbrev_sect), - dw2_debug_str, elf_get_map_size(fmap, debug_str_sect), - dw2_debug_line, elf_get_map_size(fmap, debug_line_sect), - dw2_debug_loclist, elf_get_map_size(fmap, debug_loclist_sect)); + dw2_debug, elf_get_map_size(&debug_sect), + dw2_debug_abbrev, elf_get_map_size(&debug_abbrev_sect), + dw2_debug_str, elf_get_map_size(&debug_str_sect), + dw2_debug_line, elf_get_map_size(&debug_line_sect), + dw2_debug_loclist, elf_get_map_size(&debug_loclist_sect));
if (!lret) WARN("Couldn't correctly read stabs\n"); ret = ret || lret; } - elf_unmap_section(fmap, debug_sect); - elf_unmap_section(fmap, debug_abbrev_sect); - elf_unmap_section(fmap, debug_str_sect); - elf_unmap_section(fmap, debug_line_sect); - elf_unmap_section(fmap, debug_loclist_sect); + elf_unmap_section(&debug_sect); + elf_unmap_section(&debug_abbrev_sect); + elf_unmap_section(&debug_str_sect); + elf_unmap_section(&debug_line_sect); + elf_unmap_section(&debug_loclist_sect); } - if (debuglink_sect != -1) + if (elf_find_section(fmap, ".gnu_debuglink", SHT_NULL, &debuglink_sect)) { const BYTE* dbg_link;
- dbg_link = (const BYTE*) elf_map_section(fmap, debuglink_sect); + dbg_link = (const BYTE*)elf_map_section(&debuglink_sect); if (dbg_link != ELF_NO_MAP) { lret = elf_debuglink_parse(module, pool, ht_symtab, dbg_link); @@ -1079,7 +1085,7 @@ static BOOL elf_load_debug_info_from_map debugstr_w(module->module.ModuleName)); ret = ret || lret; } - elf_unmap_section(fmap, debuglink_sect); + elf_unmap_section(&debuglink_sect); } } if (strstrW(module->module.ModuleName, S_ElfW) || @@ -1163,7 +1169,6 @@ static BOOL elf_load_file(struct process { BOOL ret = FALSE; struct elf_file_map fmap; - int i;
TRACE("Processing elf file '%s' at %08lx\n", debugstr_w(filename), load_offset);
@@ -1185,33 +1190,29 @@ static BOOL elf_load_file(struct process
if (elf_info->flags & ELF_INFO_DEBUG_HEADER) { - const char* shstrtab = elf_map_section(&fmap, fmap.elfhdr.e_shstrndx); - if (shstrtab == ELF_NO_MAP) goto leave; - for (i = 0; i < fmap.elfhdr.e_shnum; i++) + struct elf_section_map esm; + + if (elf_find_section(&fmap, ".dynamic", SHT_DYNAMIC, &esm)) { - if (strcmp(shstrtab + fmap.sect[i].shdr.sh_name, ".dynamic") == 0 && - fmap.sect[i].shdr.sh_type == SHT_DYNAMIC) - { - Elf32_Dyn dyn; - char* ptr = (char*)fmap.sect[i].shdr.sh_addr; - unsigned long len; + Elf32_Dyn dyn; + char* ptr = (char*)fmap.sect[esm.sidx].shdr.sh_addr; + unsigned long len;
- do + do + { + if (!ReadProcessMemory(pcs->handle, ptr, &dyn, sizeof(dyn), &len) || + len != sizeof(dyn)) + goto leave; + if (dyn.d_tag == DT_DEBUG) { - if (!ReadProcessMemory(pcs->handle, ptr, &dyn, sizeof(dyn), &len) || - len != sizeof(dyn)) - goto leave; - if (dyn.d_tag == DT_DEBUG) - { - elf_info->dbg_hdr_addr = dyn.d_un.d_ptr; - break; - } - ptr += sizeof(dyn); - } while (dyn.d_tag != DT_NULL); - if (dyn.d_tag == DT_NULL) goto leave; - } + elf_info->dbg_hdr_addr = dyn.d_un.d_ptr; + break; + } + ptr += sizeof(dyn); + } while (dyn.d_tag != DT_NULL); + if (dyn.d_tag == DT_NULL) goto leave; } - elf_unmap_section(&fmap, fmap.elfhdr.e_shstrndx); + elf_end_find(&fmap); }
if (elf_info->flags & ELF_INFO_MODULE)
# This series applies on GIT commit a52c2c0dfe3deaa872fe10c751447844e73dcdef dbghelp-elf-map dbghelp-elf-alternate dbghelp-elf-link-alternate