Author: cwittich Date: Sun Mar 21 22:08:48 2010 New Revision: 46325
URL: http://svn.reactos.org/svn/reactos?rev=46325&view=rev Log: [DBGHELP] sync dbghelp with wine 1.1.41
Added: trunk/reactos/dll/win32/dbghelp/image_private.h (with props) Modified: trunk/reactos/dll/win32/dbghelp/dbghelp_private.h trunk/reactos/dll/win32/dbghelp/dwarf.c trunk/reactos/dll/win32/dbghelp/elf_module.c trunk/reactos/dll/win32/dbghelp/macho_module.c trunk/reactos/dll/win32/dbghelp/module.c trunk/reactos/dll/win32/dbghelp/pe_module.c trunk/reactos/dll/win32/dbghelp/symbol.c
Modified: trunk/reactos/dll/win32/dbghelp/dbghelp_private.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dbghelp/dbghelp_p... ============================================================================== --- trunk/reactos/dll/win32/dbghelp/dbghelp_private.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/dbghelp/dbghelp_private.h [iso-8859-1] Sun Mar 21 22:08:48 2010 @@ -313,6 +313,36 @@ };
struct process; +struct module; + +/* a module can be made of several debug information formats, so we have to + * support them all + */ +enum format_info +{ + DFI_ELF, + DFI_PE, + DFI_MACHO, + DFI_DWARF, + DFI_LAST +}; + +struct module_format +{ + struct module* module; + void (*remove)(struct process* pcs, struct module_format* modfmt); + void (*loc_compute)(struct process* pcs, + const struct module_format* modfmt, + const struct symt_function* func, + struct location* loc); + union + { + struct elf_module_info* elf_info; + struct dwarf2_module_info_s* dwarf2_info; + struct pe_module_info* pe_info; + struct macho_module_info* macho_info; + } u; +};
struct module { @@ -324,10 +354,7 @@ unsigned short is_virtual : 1;
/* specific information for debug types */ - struct elf_module_info* elf_info; - struct dwarf2_module_info_s*dwarf2_info; - - struct macho_module_info* macho_info; + struct module_format* format_info[DFI_LAST];
/* memory allocation pool */ struct pool pool; @@ -340,10 +367,6 @@ unsigned sorttab_size; struct symt_ht** addr_sorttab; struct hash_table ht_symbols; - void (*loc_compute)(struct process* pcs, - const struct module* module, - const struct symt_function* func, - struct location* loc);
/* types */ struct hash_table ht_types; @@ -471,11 +494,10 @@ typedef BOOL (*enum_modules_cb)(const WCHAR*, unsigned long addr, void* user);
/* elf_module.c */ -#define ELF_NO_MAP ((const void*)-1) extern BOOL elf_enum_modules(HANDLE hProc, enum_modules_cb, void*); extern BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum); -struct elf_file_map; -extern BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap); +struct image_file_map; +extern BOOL elf_load_debug_info(struct module* module, struct image_file_map* fmap); extern struct module* elf_load_module(struct process* pcs, const WCHAR* name, unsigned long); extern BOOL elf_read_wine_loader_dbg_info(struct process* pcs); @@ -565,11 +587,7 @@ /* dwarf.c */ extern BOOL dwarf2_parse(struct module* module, unsigned long load_offset, const struct elf_thunk_area* thunks, - const unsigned char* debug, unsigned int debug_size, - const unsigned char* abbrev, unsigned int abbrev_size, - const unsigned char* str, unsigned int str_size, - const unsigned char* line, unsigned int line_size, - const unsigned char* loclist, unsigned int loclist_size); + struct image_file_map* fmap);
/* stack.c */ extern BOOL sw_read_mem(struct cpu_stack_walk* csw, DWORD64 addr, void* ptr, DWORD sz);
Modified: trunk/reactos/dll/win32/dbghelp/dwarf.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dbghelp/dwarf.c?r... ============================================================================== --- trunk/reactos/dll/win32/dbghelp/dwarf.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/dbghelp/dwarf.c [iso-8859-1] Sun Mar 21 22:08:48 2010 @@ -51,6 +51,7 @@ #include "oleauto.h"
#include "dbghelp_private.h" +#include "image_private.h"
#include "wine/debug.h"
@@ -139,6 +140,7 @@ union { unsigned long uvalue; + ULONGLONG lluvalue; long svalue; const char* string; struct dwarf2_block block; @@ -157,6 +159,7 @@ { const unsigned char* address; unsigned size; + DWORD_PTR rva; } dwarf2_section_t;
enum dwarf2_sections {section_debug, section_string, section_abbrev, section_line, section_max}; @@ -512,9 +515,8 @@ break;
case DW_FORM_data8: - attr->u.block.size = 8; - attr->u.block.ptr = data; - data += 8; + attr->u.lluvalue = dwarf2_get_u8(data); + TRACE("data8<%s>\n", wine_dbgstr_longlong(attr->u.uvalue)); break;
case DW_FORM_ref1: @@ -1480,6 +1482,11 @@ v.n1.n2.n3.lVal = value.u.uvalue; break;
+ case DW_FORM_data8: + v.n1.n2.vt = VT_UI8; + v.n1.n2.n3.llVal = value.u.lluvalue; + break; + case DW_FORM_sdata: v.n1.n2.vt = VT_I4; v.n1.n2.n3.lVal = value.u.svalue; @@ -1510,12 +1517,6 @@ memcpy(v.n1.n2.n3.byref, value.u.block.ptr, value.u.block.size); } break; - - case DW_FORM_data8: - v.n1.n2.vt = VT_I1 | VT_BYREF; - v.n1.n2.n3.byref = pool_alloc(&subpgm->ctx->module->pool, value.u.block.size); - memcpy(v.n1.n2.n3.byref, value.u.block.ptr, value.u.block.size); - break;
default: FIXME("Unsupported form for const value %s (%lx)\n", @@ -1952,7 +1953,7 @@ const char** p;
/* section with line numbers stripped */ - if (sections[section_line].address == ELF_NO_MAP) + if (sections[section_line].address == IMAGE_NO_MAP) return FALSE;
traverse.data = sections[section_line].address + offset; @@ -2211,7 +2212,7 @@ return ret; }
-static BOOL dwarf2_lookup_loclist(const struct module* module, const BYTE* start, +static BOOL dwarf2_lookup_loclist(const struct module_format* modfmt, const BYTE* start, unsigned long ip, dwarf2_traverse_context_t* lctx) { @@ -2219,7 +2220,7 @@ const BYTE* ptr = start; DWORD len;
- while (ptr < module->dwarf2_info->debug_loc.address + module->dwarf2_info->debug_loc.size) + while (ptr < modfmt->u.dwarf2_info->debug_loc.address + modfmt->u.dwarf2_info->debug_loc.size) { beg = dwarf2_get_u4(ptr); ptr += 4; end = dwarf2_get_u4(ptr); ptr += 4; @@ -2240,7 +2241,7 @@ }
static enum location_error loc_compute_frame(struct process* pcs, - const struct module* module, + const struct module_format* modfmt, const struct symt_function* func, DWORD ip, struct location* frame) { @@ -2266,8 +2267,8 @@ break; case loc_dwarf2_location_list: WARN("Searching loclist for %s\n", func->hash_elt.name); - if (!dwarf2_lookup_loclist(module, - module->dwarf2_info->debug_loc.address + pframe->offset, + if (!dwarf2_lookup_loclist(modfmt, + modfmt->u.dwarf2_info->debug_loc.address + pframe->offset, ip, &lctx)) return loc_err_out_of_scope; if ((err = compute_location(&lctx, frame, pcs->handle, NULL)) < 0) return err; @@ -2289,7 +2290,7 @@ }
static void dwarf2_location_compute(struct process* pcs, - const struct module* module, + const struct module_format* modfmt, const struct symt_function* func, struct location* loc) { @@ -2308,14 +2309,14 @@ /* instruction pointer relative to compiland's start */ ip = pcs->ctx_frame.InstructionOffset - ((struct symt_compiland*)func->container)->address;
- if ((err = loc_compute_frame(pcs, module, func, ip, &frame)) == 0) + if ((err = loc_compute_frame(pcs, modfmt, func, ip, &frame)) == 0) { switch (loc->kind) { case loc_dwarf2_location_list: /* Then, if the variable has a location list, find it !! */ - if (dwarf2_lookup_loclist(module, - module->dwarf2_info->debug_loc.address + loc->offset, + if (dwarf2_lookup_loclist(modfmt, + modfmt->u.dwarf2_info->debug_loc.address + loc->offset, ip, &lctx)) goto do_compute; err = loc_err_out_of_scope; @@ -2350,56 +2351,115 @@ } }
+static void dwarf2_module_remove(struct process* pcs, struct module_format* modfmt) +{ + HeapFree(GetProcessHeap(), 0, modfmt->u.dwarf2_info); + HeapFree(GetProcessHeap(), 0, modfmt); +} + +static inline BOOL dwarf2_init_section(dwarf2_section_t* section, struct image_file_map* fmap, + const char* sectname, struct image_section_map* ism) +{ + struct image_section_map local_ism; + + if (!ism) ism = &local_ism; + if (!image_find_section(fmap, sectname, ism)) + { + section->address = NULL; + section->size = 0; + section->rva = 0; + return FALSE; + } + + section->address = (const BYTE*)image_map_section(ism); + section->size = image_get_map_size(ism); + section->rva = image_get_map_rva(ism); + return TRUE; +} + BOOL dwarf2_parse(struct module* module, unsigned long load_offset, const struct elf_thunk_area* thunks, - const unsigned char* debug, unsigned int debug_size, - const unsigned char* abbrev, unsigned int abbrev_size, - const unsigned char* str, unsigned int str_size, - const unsigned char* line, unsigned int line_size, - const unsigned char* loclist, unsigned int loclist_size) + struct image_file_map* fmap) { dwarf2_section_t section[section_max]; - unsigned char* ptr; dwarf2_traverse_context_t mod_ctx; - - mod_ctx.start_data = mod_ctx.data = debug; - mod_ctx.end_data = debug + debug_size; - - module->loc_compute = dwarf2_location_compute; - - section[section_debug].address = debug; - section[section_debug].size = debug_size; - section[section_abbrev].address = abbrev; - section[section_abbrev].size = abbrev_size; - section[section_string].address = str; - section[section_string].size = str_size; - section[section_line].address = line; - section[section_line].size = line_size; - - if (loclist_size) + struct image_section_map debug_sect, debug_str_sect, debug_abbrev_sect, + debug_line_sect, debug_loclist_sect; + BOOL ret = TRUE; + struct module_format* dwarf2_modfmt; + + if (!dwarf2_init_section(§ion[section_debug], fmap, ".debug_info", &debug_sect)) + { + /* no Dwarf debug info here, so there's no error */ + return TRUE; + } + dwarf2_init_section(§ion[section_abbrev], fmap, ".debug_abbrev", &debug_abbrev_sect); + dwarf2_init_section(§ion[section_string], fmap, ".debug_str", &debug_str_sect); + dwarf2_init_section(§ion[section_line], fmap, ".debug_line", &debug_line_sect); + + if (section[section_debug].address == IMAGE_NO_MAP || + section[section_abbrev].address == IMAGE_NO_MAP || + section[section_string].address == IMAGE_NO_MAP) + { + ret = FALSE; + goto leave; + } + + if (fmap->modtype == DMT_ELF) + { + /* debug info might have a different base address than .so file + * when elf file is prelinked after splitting off debug info + * adjust symbol base addresses accordingly + */ + load_offset += fmap->u.elf.elf_start - debug_sect.fmap->u.elf.elf_start; + } + + TRACE("Loading Dwarf2 information for %s\n", debugstr_w(module->module.ModuleName)); + + mod_ctx.start_data = mod_ctx.data = section[section_debug].address; + mod_ctx.end_data = mod_ctx.data + section[section_debug].size; + + + dwarf2_modfmt = HeapAlloc(GetProcessHeap(), 0, sizeof(*dwarf2_modfmt)); + if (!dwarf2_modfmt) return FALSE; + dwarf2_modfmt->module = module; + dwarf2_modfmt->remove = dwarf2_module_remove; + dwarf2_modfmt->loc_compute = dwarf2_location_compute; + dwarf2_modfmt->u.dwarf2_info = NULL; + dwarf2_modfmt->module->format_info[DFI_DWARF] = dwarf2_modfmt; + + image_find_section(fmap, ".debug_loc", &debug_loclist_sect); + if (image_get_map_size(&debug_loclist_sect)) { /* initialize the dwarf2 specific info block for this module. - * As we'll need later on the .debug_loc section content, we copy it in - * the module structure for later reuse + * As we'll need later the .debug_loc section content, we won't unmap this + * section upon existing this function */ - module->dwarf2_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*module->dwarf2_info) + loclist_size); - if (!module->dwarf2_info) return FALSE; - ptr = (unsigned char*)(module->dwarf2_info + 1); - memcpy(ptr, loclist, loclist_size); - module->dwarf2_info->debug_loc.address = ptr; - module->dwarf2_info->debug_loc.size = loclist_size; - } + dwarf2_modfmt->u.dwarf2_info = HeapAlloc(GetProcessHeap(), 0, + sizeof(*dwarf2_modfmt->u.dwarf2_info)); + if (!dwarf2_modfmt->u.dwarf2_info) goto leave; + dwarf2_modfmt->u.dwarf2_info->debug_loc.address = (const BYTE*)image_map_section(&debug_loclist_sect); + dwarf2_modfmt->u.dwarf2_info->debug_loc.size = image_get_map_size(&debug_loclist_sect); + } + else image_unmap_section(&debug_loclist_sect);
while (mod_ctx.data < mod_ctx.end_data) { - dwarf2_parse_compilation_unit(section, module, thunks, &mod_ctx, load_offset); - } - module->module.SymType = SymDia; - module->module.CVSig = 'D' | ('W' << 8) | ('A' << 16) | ('R' << 24); + dwarf2_parse_compilation_unit(section, dwarf2_modfmt->module, thunks, &mod_ctx, load_offset); + } + dwarf2_modfmt->module->module.SymType = SymDia; + dwarf2_modfmt->module->module.CVSig = 'D' | ('W' << 8) | ('A' << 16) | ('R' << 24); /* FIXME: we could have a finer grain here */ - module->module.GlobalSymbols = TRUE; - module->module.TypeInfo = TRUE; - module->module.SourceIndexed = TRUE; - module->module.Publics = TRUE; - return TRUE; -} + dwarf2_modfmt->module->module.GlobalSymbols = TRUE; + dwarf2_modfmt->module->module.TypeInfo = TRUE; + dwarf2_modfmt->module->module.SourceIndexed = TRUE; + dwarf2_modfmt->module->module.Publics = TRUE; + +leave: + image_unmap_section(&debug_sect); + image_unmap_section(&debug_abbrev_sect); + image_unmap_section(&debug_str_sect); + image_unmap_section(&debug_line_sect); + + return ret; +}
Modified: trunk/reactos/dll/win32/dbghelp/elf_module.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dbghelp/elf_modul... ============================================================================== --- trunk/reactos/dll/win32/dbghelp/elf_module.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/dbghelp/elf_module.c [iso-8859-1] Sun Mar 21 22:08:48 2010 @@ -48,39 +48,10 @@
#include "dbghelp_private.h"
-#ifdef HAVE_ELF_H -# include <elf.h> -#endif -#ifdef HAVE_SYS_ELF32_H -# include <sys/elf32.h> -#endif -#ifdef HAVE_SYS_EXEC_ELF_H -# include <sys/exec_elf.h> -#endif -#if !defined(DT_NUM) -# if defined(DT_COUNT) -# define DT_NUM DT_COUNT -# else -/* this seems to be a satisfactory value on Solaris, which doesn't support this AFAICT */ -# define DT_NUM 24 -# endif -#endif -#ifdef HAVE_LINK_H -# include <link.h> -#endif -#ifdef HAVE_SYS_LINK_H -# include <sys/link.h> -#endif +#include "image_private.h"
#include "wine/library.h" #include "wine/debug.h" - -struct elf_module_info -{ - DWORD_PTR elf_addr; - unsigned short elf_mark : 1, - elf_loader : 1; -};
#ifdef __ELF__
@@ -98,44 +69,6 @@ const WCHAR* module_name; /* OUT found module name (if ELF_INFO_NAME is set) */ };
-#ifdef _WIN64 -#define Elf_Ehdr Elf64_Ehdr -#define Elf_Shdr Elf64_Shdr -#define Elf_Phdr Elf64_Phdr -#define Elf_Dyn Elf64_Dyn -#define Elf_Sym Elf64_Sym -#else -#define Elf_Ehdr Elf32_Ehdr -#define Elf_Shdr Elf32_Shdr -#define Elf_Phdr Elf32_Phdr -#define Elf_Dyn Elf32_Dyn -#define Elf_Sym Elf32_Sym -#endif - -/* structure holding information while handling an ELF image - * allows one by one section mapping for memory savings - */ -struct elf_file_map -{ - Elf_Ehdr elfhdr; - size_t elf_size; - size_t elf_start; - struct - { - Elf_Shdr shdr; - const char* mapped; - }* sect; - int fd; - const char* shstrtab; - struct elf_file_map* alternate; /* another ELF file (linked to this one) */ -}; - -struct elf_section_map -{ - struct elf_file_map* fmap; - long sidx; -}; - struct symtab_elt { struct hash_table_elt ht_elt; @@ -152,28 +85,39 @@ unsigned long rva_end; };
+struct elf_module_info +{ + unsigned long elf_addr; + unsigned short elf_mark : 1, + elf_loader : 1; + struct image_file_map file_map; +}; + /****************************************************************** * elf_map_section * * Maps a single section into memory from an ELF file */ -static const char* elf_map_section(struct elf_section_map* esm) -{ +const char* elf_map_section(struct image_section_map* ism) +{ + struct elf_file_map* fmap = &ism->fmap->u.elf; + unsigned pgsz = getpagesize(); unsigned ofst, size;
- 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; + assert(ism->fmap->modtype == DMT_ELF); + if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.elf.elfhdr.e_shnum || + fmap->sect[ism->sidx].shdr.sh_type == SHT_NOBITS) + return IMAGE_NO_MAP;
/* align required information on page size (we assume pagesize is a power of 2) */ - 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)); + ofst = fmap->sect[ism->sidx].shdr.sh_offset & ~(pgsz - 1); + size = ((fmap->sect[ism->sidx].shdr.sh_offset + + fmap->sect[ism->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst; + fmap->sect[ism->sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE, + fmap->fd, ofst); + if (fmap->sect[ism->sidx].mapped == IMAGE_NO_MAP) return IMAGE_NO_MAP; + return fmap->sect[ism->sidx].mapped + (fmap->sect[ism->sidx].shdr.sh_offset & (pgsz - 1)); }
/****************************************************************** @@ -182,32 +126,34 @@ * 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) -{ +BOOL elf_find_section(struct image_file_map* _fmap, const char* name, + unsigned sht, struct image_section_map* ism) +{ + struct elf_file_map* fmap; unsigned i;
- while (fmap) - { - if (fmap->shstrtab == ELF_NO_MAP) - { - struct elf_section_map hdr_esm = {fmap, fmap->elfhdr.e_shstrndx}; - if ((fmap->shstrtab = elf_map_section(&hdr_esm)) == ELF_NO_MAP) break; + while (_fmap) + { + fmap = &_fmap->u.elf; + if (fmap->shstrtab == IMAGE_NO_MAP) + { + struct image_section_map hdr_ism = {_fmap, fmap->elfhdr.e_shstrndx}; + if ((fmap->shstrtab = elf_map_section(&hdr_ism)) == IMAGE_NO_MAP) break; } 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; + ism->fmap = _fmap; + ism->sidx = i; return TRUE; } } - fmap = fmap->alternate; - } - esm->fmap = NULL; - esm->sidx = -1; + _fmap = fmap->alternate; + } + ism->fmap = NULL; + ism->sidx = -1; return FALSE; }
@@ -216,34 +162,48 @@ * * Unmaps a single section from memory */ -static void elf_unmap_section(struct elf_section_map* esm) -{ - if (esm->sidx >= 0 && esm->sidx < esm->fmap->elfhdr.e_shnum && esm->fmap->sect[esm->sidx].mapped != ELF_NO_MAP) +void elf_unmap_section(struct image_section_map* ism) +{ + struct elf_file_map* fmap = &ism->fmap->u.elf; + + if (ism->sidx >= 0 && ism->sidx < fmap->elfhdr.e_shnum && fmap->sect[ism->sidx].mapped != IMAGE_NO_MAP) { unsigned pgsz = getpagesize(); unsigned ofst, size;
- 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) + ofst = fmap->sect[ism->sidx].shdr.sh_offset & ~(pgsz - 1); + size = ((fmap->sect[ism->sidx].shdr.sh_offset + + fmap->sect[ism->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst; + if (munmap((char*)fmap->sect[ism->sidx].mapped, size) < 0) WARN("Couldn't unmap the section\n"); - esm->fmap->sect[esm->sidx].mapped = ELF_NO_MAP; - } -} - -static void elf_end_find(struct elf_file_map* fmap) -{ - struct elf_section_map esm; + fmap->sect[ism->sidx].mapped = IMAGE_NO_MAP; + } +} + +static void elf_end_find(struct image_file_map* fmap) +{ + struct image_section_map ism;
while (fmap) { - esm.fmap = fmap; - esm.sidx = fmap->elfhdr.e_shstrndx; - elf_unmap_section(&esm); - fmap->shstrtab = ELF_NO_MAP; - fmap = fmap->alternate; - } + ism.fmap = fmap; + ism.sidx = fmap->u.elf.elfhdr.e_shstrndx; + elf_unmap_section(&ism); + fmap->u.elf.shstrtab = IMAGE_NO_MAP; + fmap = fmap->u.elf.alternate; + } +} + +/****************************************************************** + * elf_get_map_rva + * + * Get the RVA of an ELF section + */ +DWORD_PTR elf_get_map_rva(const struct image_section_map* ism) +{ + if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.elf.elfhdr.e_shnum) + return 0; + return ism->fmap->u.elf.sect[ism->sidx].shdr.sh_addr - ism->fmap->u.elf.elf_start; }
/****************************************************************** @@ -251,11 +211,18 @@ * * Get the size of an ELF section */ -static inline unsigned elf_get_map_size(const struct elf_section_map* esm) -{ - if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum) +unsigned elf_get_map_size(const struct image_section_map* ism) +{ + if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.elf.elfhdr.e_shnum) return 0; - return esm->fmap->sect[esm->sidx].shdr.sh_size; + return ism->fmap->u.elf.sect[ism->sidx].shdr.sh_size; +} + +static inline void elf_reset_file_map(struct image_file_map* fmap) +{ + fmap->u.elf.fd = -1; + fmap->u.elf.shstrtab = IMAGE_NO_MAP; + fmap->u.elf.alternate = NULL; }
/****************************************************************** @@ -263,7 +230,7 @@ * * Maps an ELF file into memory (and checks it's a real ELF file) */ -static BOOL elf_map_file(const WCHAR* filenameW, struct elf_file_map* fmap) +static BOOL elf_map_file(const WCHAR* filenameW, struct image_file_map* fmap) { static const BYTE elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 }; struct stat statbuf; @@ -278,56 +245,55 @@ if (!(filename = HeapAlloc(GetProcessHeap(), 0, len))) return FALSE; WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, filename, len, NULL, NULL);
- fmap->fd = -1; - fmap->shstrtab = ELF_NO_MAP; - fmap->alternate = NULL; - + elf_reset_file_map(fmap); + + fmap->modtype = DMT_ELF; /* 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;
/* Now open the file, so that we can mmap() it. */ - if ((fmap->fd = open(filename, O_RDONLY)) == -1) goto done; - - if (read(fmap->fd, &fmap->elfhdr, sizeof(fmap->elfhdr)) != sizeof(fmap->elfhdr)) + if ((fmap->u.elf.fd = open(filename, O_RDONLY)) == -1) goto done; + + if (read(fmap->u.elf.fd, &fmap->u.elf.elfhdr, sizeof(fmap->u.elf.elfhdr)) != sizeof(fmap->u.elf.elfhdr)) goto done; /* and check for an ELF header */ - if (memcmp(fmap->elfhdr.e_ident, + if (memcmp(fmap->u.elf.elfhdr.e_ident, elf_signature, sizeof(elf_signature))) goto done; /* and check 32 vs 64 size according to current machine */ #ifdef _WIN64 - if (fmap->elfhdr.e_ident[EI_CLASS] != ELFCLASS64) goto done; + if (fmap->u.elf.elfhdr.e_ident[EI_CLASS] != ELFCLASS64) goto done; #else - if (fmap->elfhdr.e_ident[EI_CLASS] != ELFCLASS32) goto done; + if (fmap->u.elf.elfhdr.e_ident[EI_CLASS] != ELFCLASS32) goto done; #endif - fmap->sect = HeapAlloc(GetProcessHeap(), 0, - fmap->elfhdr.e_shnum * sizeof(fmap->sect[0])); - if (!fmap->sect) goto done; - - lseek(fmap->fd, fmap->elfhdr.e_shoff, SEEK_SET); - for (i = 0; i < fmap->elfhdr.e_shnum; i++) - { - read(fmap->fd, &fmap->sect[i].shdr, sizeof(fmap->sect[i].shdr)); - fmap->sect[i].mapped = ELF_NO_MAP; + fmap->u.elf.sect = HeapAlloc(GetProcessHeap(), 0, + fmap->u.elf.elfhdr.e_shnum * sizeof(fmap->u.elf.sect[0])); + if (!fmap->u.elf.sect) goto done; + + lseek(fmap->u.elf.fd, fmap->u.elf.elfhdr.e_shoff, SEEK_SET); + for (i = 0; i < fmap->u.elf.elfhdr.e_shnum; i++) + { + read(fmap->u.elf.fd, &fmap->u.elf.sect[i].shdr, sizeof(fmap->u.elf.sect[i].shdr)); + fmap->u.elf.sect[i].mapped = IMAGE_NO_MAP; }
/* grab size of module once loaded in memory */ - lseek(fmap->fd, fmap->elfhdr.e_phoff, SEEK_SET); - fmap->elf_size = 0; - fmap->elf_start = ~0L; - for (i = 0; i < fmap->elfhdr.e_phnum; i++) - { - if (read(fmap->fd, &phdr, sizeof(phdr)) == sizeof(phdr) && + lseek(fmap->u.elf.fd, fmap->u.elf.elfhdr.e_phoff, SEEK_SET); + fmap->u.elf.elf_size = 0; + fmap->u.elf.elf_start = ~0L; + for (i = 0; i < fmap->u.elf.elfhdr.e_phnum; i++) + { + if (read(fmap->u.elf.fd, &phdr, sizeof(phdr)) == sizeof(phdr) && phdr.p_type == PT_LOAD) { tmp = (phdr.p_vaddr + phdr.p_memsz + page_mask) & ~page_mask; - if (fmap->elf_size < tmp) fmap->elf_size = tmp; - if (phdr.p_vaddr < fmap->elf_start) fmap->elf_start = phdr.p_vaddr; + if (fmap->u.elf.elf_size < tmp) fmap->u.elf.elf_size = tmp; + if (phdr.p_vaddr < fmap->u.elf.elf_start) fmap->u.elf.elf_start = phdr.p_vaddr; } } /* if non relocatable ELF, then remove fixed address from computation * otherwise, all addresses are zero based and start has no effect */ - fmap->elf_size -= fmap->elf_start; + fmap->u.elf.elf_size -= fmap->u.elf.elf_start; ret = TRUE; done: HeapFree(GetProcessHeap(), 0, filename); @@ -339,23 +305,29 @@ * * Unmaps an ELF file from memory (previously mapped with elf_map_file) */ -static void elf_unmap_file(struct elf_file_map* fmap) +static void elf_unmap_file(struct image_file_map* fmap) { while (fmap) { - if (fmap->fd != -1) - { - struct elf_section_map esm; - esm.fmap = fmap; - for (esm.sidx = 0; esm.sidx < fmap->elfhdr.e_shnum; esm.sidx++) + if (fmap->u.elf.fd != -1) + { + struct image_section_map ism; + ism.fmap = fmap; + for (ism.sidx = 0; ism.sidx < fmap->u.elf.elfhdr.e_shnum; ism.sidx++) { - elf_unmap_section(&esm); + elf_unmap_section(&ism); } - HeapFree(GetProcessHeap(), 0, fmap->sect); - close(fmap->fd); - } - fmap = fmap->alternate; - } + HeapFree(GetProcessHeap(), 0, fmap->u.elf.sect); + close(fmap->u.elf.fd); + } + fmap = fmap->u.elf.alternate; + } +} + +static void elf_module_remove(struct process* pcs, struct module_format* modfmt) +{ + elf_unmap_file(&modfmt->u.elf_info->file_map); + HeapFree(GetProcessHeap(), 0, modfmt); }
/****************************************************************** @@ -382,8 +354,8 @@ * * creating an internal hash table to ease use ELF symtab information lookup */ -static void elf_hash_symtab(struct module* module, struct pool* pool, - struct hash_table* ht_symtab, struct elf_file_map* fmap, +static void elf_hash_symtab(struct module* module, struct pool* pool, + struct hash_table* ht_symtab, struct image_file_map* fmap, struct elf_thunk_area* thunks) { int i, j, nsym; @@ -393,16 +365,20 @@ const char* ptr; const Elf_Sym* symp; struct symtab_elt* ste; - struct elf_section_map esm, esm_str; - - if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &esm) && - !elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &esm)) return; - if ((symp = (const Elf_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(&esm) / sizeof(*symp); + struct image_section_map ism, ism_str; + + if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &ism) && + !elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &ism)) return; + if ((symp = (const Elf_Sym*)image_map_section(&ism)) == IMAGE_NO_MAP) return; + ism_str.fmap = ism.fmap; + ism_str.sidx = fmap->u.elf.sect[ism.sidx].shdr.sh_link; + if ((strp = image_map_section(&ism_str)) == IMAGE_NO_MAP) + { + image_unmap_section(&ism); + return; + } + + nsym = image_get_map_size(&ism) / sizeof(*symp);
for (j = 0; thunks[j].symname; j++) thunks[j].rva_start = thunks[j].rva_end = 0; @@ -567,6 +543,7 @@ void* ptr; struct symt_ht* sym; const Elf_Sym* symp; + struct elf_module_info* elf_info = module->format_info[DFI_ELF]->u.elf_info;
hash_table_iter_init(&module->ht_symbols, &hti, NULL); while ((ptr = hash_table_iter_up(&hti))) @@ -575,7 +552,7 @@ switch (sym->symt.tag) { case SymTagFunction: - if (((struct symt_function*)sym)->address != module->elf_info->elf_addr && + if (((struct symt_function*)sym)->address != elf_info->elf_addr && ((struct symt_function*)sym)->size) { break; @@ -584,18 +561,17 @@ ((struct symt_function*)sym)->container); if (symp) { - if (((struct symt_function*)sym)->address != module->elf_info->elf_addr && - ((struct symt_function*)sym)->address != module->elf_info->elf_addr + symp->st_value) + if (((struct symt_function*)sym)->address != elf_info->elf_addr && + ((struct symt_function*)sym)->address != elf_info->elf_addr + symp->st_value) FIXME("Changing address for %p/%s!%s from %08lx to %08lx\n", sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name, - ((struct symt_function*)sym)->address, module->elf_info->elf_addr + symp->st_value); + ((struct symt_function*)sym)->address, elf_info->elf_addr + symp->st_value); if (((struct symt_function*)sym)->size && ((struct symt_function*)sym)->size != symp->st_size) FIXME("Changing size for %p/%s!%s from %08lx to %08x\n", sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name, ((struct symt_function*)sym)->size, (unsigned int)symp->st_size);
- ((struct symt_function*)sym)->address = module->elf_info->elf_addr + - symp->st_value; + ((struct symt_function*)sym)->address = elf_info->elf_addr + symp->st_value; ((struct symt_function*)sym)->size = symp->st_size; } else FIXME("Couldn't find %s!%s\n", @@ -606,19 +582,18 @@ { case DataIsGlobal: case DataIsFileStatic: - if (((struct symt_data*)sym)->u.var.offset != module->elf_info->elf_addr) + if (((struct symt_data*)sym)->u.var.offset != elf_info->elf_addr) break; symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, ((struct symt_data*)sym)->container); if (symp) { - if (((struct symt_data*)sym)->u.var.offset != module->elf_info->elf_addr && - ((struct symt_data*)sym)->u.var.offset != module->elf_info->elf_addr + symp->st_value) + if (((struct symt_data*)sym)->u.var.offset != elf_info->elf_addr && + ((struct symt_data*)sym)->u.var.offset != elf_info->elf_addr + symp->st_value) FIXME("Changing address for %p/%s!%s from %08lx to %08lx\n", sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name, - ((struct symt_function*)sym)->address, module->elf_info->elf_addr + symp->st_value); - ((struct symt_data*)sym)->u.var.offset = module->elf_info->elf_addr + - symp->st_value; + ((struct symt_function*)sym)->address, elf_info->elf_addr + symp->st_value); + ((struct symt_data*)sym)->u.var.offset = elf_info->elf_addr + symp->st_value; ((struct symt_data*)sym)->kind = (ELF32_ST_BIND(symp->st_info) == STB_LOCAL) ? DataIsFileStatic : DataIsGlobal; } else @@ -656,7 +631,7 @@ { if (ste->used) continue;
- addr = module->elf_info->elf_addr + ste->symp->st_value; + addr = module->format_info[DFI_ELF]->u.elf_info->elf_addr + ste->symp->st_value;
j = elf_is_in_thunk_area(ste->symp->st_value, thunks); if (j >= 0) /* thunk found */ @@ -748,20 +723,20 @@ while ((ste = hash_table_iter_up(&hti))) { symt_new_public(module, ste->compiland, ste->ht_elt.name, - module->elf_info->elf_addr + ste->symp->st_value, + module->format_info[DFI_ELF]->u.elf_info->elf_addr + ste->symp->st_value, ste->symp->st_size); } return TRUE; }
-static BOOL elf_check_debug_link(const WCHAR* file, struct elf_file_map* fmap, DWORD crc) +static BOOL elf_check_debug_link(const WCHAR* file, struct image_file_map* fmap, DWORD crc) { BOOL ret; if (!elf_map_file(file, fmap)) return FALSE; - if (!(ret = crc == calc_crc32(fmap->fd))) + if (!(ret = crc == calc_crc32(fmap->u.elf.fd))) { WARN("Bad CRC for file %s (got %08x while expecting %08x)\n", - debugstr_w(file), calc_crc32(fmap->fd), crc); + debugstr_w(file), calc_crc32(fmap->u.elf.fd), crc); elf_unmap_file(fmap); } return ret; @@ -786,7 +761,7 @@ * is the global debug file directory, and execdir has been turned * into a relative path)." (from GDB manual) */ -static BOOL elf_locate_debug_link(struct elf_file_map* fmap, const char* filename, +static BOOL elf_locate_debug_link(struct image_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','/'}; @@ -795,7 +770,7 @@ size_t filename_len; WCHAR* p = NULL; WCHAR* slash; - struct elf_file_map* fmap_link = NULL; + struct image_file_map* fmap_link = NULL;
fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link)); if (!fmap_link) return FALSE; @@ -838,7 +813,7 @@ found: TRACE("Located debug information file %s at %s\n", filename, debugstr_w(p)); HeapFree(GetProcessHeap(), 0, p); - fmap->alternate = fmap_link; + fmap->u.elf.alternate = fmap_link; return TRUE; }
@@ -848,7 +823,7 @@ * Parses a .gnu_debuglink section and loads the debug info from * the external file specified there. */ -static BOOL elf_debuglink_parse(struct elf_file_map* fmap, const struct module* module, +static BOOL elf_debuglink_parse(struct image_file_map* fmap, const struct module* module, const BYTE* debuglink) { /* The content of a debug link section is: @@ -877,8 +852,8 @@ * read or parsed) * 1 on success */ -static BOOL elf_load_debug_info_from_map(struct module* module, - struct elf_file_map* fmap, +static BOOL elf_load_debug_info_from_map(struct module* module, + struct image_file_map* fmap, struct pool* pool, struct hash_table* ht_symtab) { @@ -901,18 +876,16 @@
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) { - 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; + struct image_section_map stab_sect, stabstr_sect; + struct image_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) + dbg_link = (const BYTE*)image_map_section(&debuglink_sect); + if (dbg_link != IMAGE_NO_MAP) { lret = elf_debuglink_parse(fmap, module, dbg_link); if (!lret) @@ -920,7 +893,7 @@ debugstr_w(module->module.ModuleName)); ret = ret || lret; } - elf_unmap_section(&debuglink_sect); + image_unmap_section(&debuglink_sect); } if (elf_find_section(fmap, ".stab", SHT_NULL, &stab_sect) && elf_find_section(fmap, ".stabstr", SHT_NULL, &stabstr_sect)) @@ -928,14 +901,14 @@ const char* stab; const char* stabstr;
- stab = elf_map_section(&stab_sect); - stabstr = elf_map_section(&stabstr_sect); - if (stab != ELF_NO_MAP && stabstr != ELF_NO_MAP) + stab = image_map_section(&stab_sect); + stabstr = image_map_section(&stabstr_sect); + if (stab != IMAGE_NO_MAP && stabstr != IMAGE_NO_MAP) { /* OK, now just parse all of the stabs. */ - lret = stabs_parse(module, module->elf_info->elf_addr, - stab, elf_get_map_size(&stab_sect), - stabstr, elf_get_map_size(&stabstr_sect), + lret = stabs_parse(module, module->format_info[DFI_ELF]->u.elf_info->elf_addr, + stab, image_get_map_size(&stab_sect), + stabstr, image_get_map_size(&stabstr_sect), NULL, NULL); if (lret) /* and fill in the missing information for stabs */ @@ -945,57 +918,12 @@ ret = ret || lret; } else lret = FALSE; - elf_unmap_section(&stab_sect); - elf_unmap_section(&stabstr_sect); - } - if (elf_find_section(fmap, ".debug_info", SHT_NULL, &debug_sect)) - { - /* Dwarf 2 debug information */ - const BYTE* dw2_debug; - const BYTE* dw2_debug_abbrev; - const BYTE* dw2_debug_str; - const BYTE* dw2_debug_line; - const BYTE* dw2_debug_loclist; - - /* debug info might have a different base address than .so file - * when elf file is prelinked after splitting off debug info - * adjust symbol base addresses accordingly - */ - unsigned long load_offset = module->elf_info->elf_addr + - fmap->elf_start - debug_sect.fmap->elf_start; - - TRACE("Loading Dwarf2 information for %s\n", debugstr_w(module->module.ModuleName)); - - 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, load_offset, thunks, - 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 dwarf2\n"); - ret = ret || lret; - } - 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); - } + image_unmap_section(&stab_sect); + image_unmap_section(&stabstr_sect); + } + lret = dwarf2_parse(module, module->format_info[DFI_ELF]->u.elf_info->elf_addr, + thunks, fmap); + ret = ret || lret; } if (strstrW(module->module.ModuleName, S_ElfW) || !strcmpW(module->module.ModuleName, S_WineLoaderW)) @@ -1015,14 +943,15 @@ * * Loads ELF debugging information from the module image file. */ -BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap) -{ - BOOL ret = TRUE; - struct pool pool; - struct hash_table ht_symtab; - struct elf_file_map my_fmap; - - if (module->type != DMT_ELF || !module->elf_info) +BOOL elf_load_debug_info(struct module* module, struct image_file_map* fmap) +{ + BOOL ret = TRUE; + struct pool pool; + struct hash_table ht_symtab; + struct image_file_map my_fmap; + struct module_format* modfmt; + + if (module->type != DMT_ELF || !(modfmt = module->format_info[DFI_ELF]) || !modfmt->u.elf_info) { ERR("Bad elf module '%s'\n", debugstr_w(module->module.LoadedImageName)); return FALSE; @@ -1038,6 +967,12 @@ } if (ret) ret = elf_load_debug_info_from_map(module, fmap, &pool, &ht_symtab); + + if (ret) + { + modfmt->u.elf_info->file_map = *fmap; + elf_reset_file_map(fmap); + }
pool_destroy(&pool); if (fmap == &my_fmap) elf_unmap_file(fmap); @@ -1052,12 +987,12 @@ BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum) { - struct elf_file_map fmap; + struct image_file_map fmap;
if (!elf_map_file(name, &fmap)) return FALSE; - if (base) *base = fmap.elf_start; - *size = fmap.elf_size; - *checksum = calc_crc32(fmap.fd); + if (base) *base = fmap.u.elf.elf_start; + *size = fmap.u.elf.elf_size; + *checksum = calc_crc32(fmap.u.elf.fd); elf_unmap_file(&fmap); return TRUE; } @@ -1076,8 +1011,8 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename, unsigned long load_offset, struct elf_info* elf_info) { - BOOL ret = FALSE; - struct elf_file_map fmap; + BOOL ret = FALSE; + struct image_file_map fmap;
TRACE("Processing elf file '%s' at %08lx\n", debugstr_w(filename), load_offset);
@@ -1087,10 +1022,10 @@ * this thing. We need the main executable header, and the section * table. */ - if (!fmap.elf_start && !load_offset) + if (!fmap.u.elf.elf_start && !load_offset) ERR("Relocatable ELF %s, but no load address. Loading at 0x0000000\n", debugstr_w(filename)); - if (fmap.elf_start && load_offset) + if (fmap.u.elf.elf_start && load_offset) { WARN("Non-relocatable ELF %s, but load address of 0x%08lx supplied. " "Assuming load address is corrupt\n", debugstr_w(filename), load_offset); @@ -1099,12 +1034,12 @@
if (elf_info->flags & ELF_INFO_DEBUG_HEADER) { - struct elf_section_map esm; - - if (elf_find_section(&fmap, ".dynamic", SHT_DYNAMIC, &esm)) + struct image_section_map ism; + + if (elf_find_section(&fmap, ".dynamic", SHT_DYNAMIC, &ism)) { Elf_Dyn dyn; - char* ptr = (char*)fmap.sect[esm.sidx].shdr.sh_addr; + char* ptr = (char*)fmap.u.elf.sect[ism.sidx].shdr.sh_addr; unsigned long len;
do @@ -1126,29 +1061,40 @@
if (elf_info->flags & ELF_INFO_MODULE) { - struct elf_module_info *elf_module_info = - HeapAlloc(GetProcessHeap(), 0, sizeof(struct elf_module_info)); - if (!elf_module_info) goto leave; + struct elf_module_info *elf_module_info; + struct module_format* modfmt; + + modfmt = HeapAlloc(GetProcessHeap(), 0, + sizeof(struct module_format) + sizeof(struct elf_module_info)); + if (!modfmt) goto leave; elf_info->module = module_new(pcs, filename, DMT_ELF, FALSE, - (load_offset) ? load_offset : fmap.elf_start, - fmap.elf_size, 0, calc_crc32(fmap.fd)); + (load_offset) ? load_offset : fmap.u.elf.elf_start, + fmap.u.elf.elf_size, 0, calc_crc32(fmap.u.elf.fd)); if (!elf_info->module) { - HeapFree(GetProcessHeap(), 0, elf_module_info); + HeapFree(GetProcessHeap(), 0, modfmt); goto leave; } - elf_info->module->elf_info = elf_module_info; - elf_info->module->elf_info->elf_addr = load_offset; + elf_module_info = (void*)(modfmt + 1); + elf_info->module->format_info[DFI_ELF] = modfmt; + modfmt->module = elf_info->module; + modfmt->remove = elf_module_remove; + modfmt->loc_compute = NULL; + modfmt->u.elf_info = elf_module_info; + + elf_module_info->elf_addr = load_offset;
if (dbghelp_options & SYMOPT_DEFERRED_LOADS) { elf_info->module->module.SymType = SymDeferred; + elf_module_info->file_map = fmap; + elf_reset_file_map(&fmap); ret = TRUE; } else ret = elf_load_debug_info(elf_info->module, &fmap);
- elf_info->module->elf_info->elf_mark = 1; - elf_info->module->elf_info->elf_loader = 0; + elf_module_info->elf_mark = 1; + elf_module_info->elf_loader = 0; } else ret = TRUE;
if (elf_info->flags & ELF_INFO_NAME) @@ -1260,7 +1206,7 @@ if ((module = module_is_already_loaded(pcs, filename))) { elf_info->module = module; - module->elf_info->elf_mark = 1; + elf_info->module->format_info[DFI_ELF]->u.elf_info->elf_mark = 1; return module->module.SymType; }
@@ -1352,7 +1298,7 @@ for (module = pcs->lmodules; module; module = module->next) { if (module->type == DMT_ELF && !module->is_virtual) - module->elf_info->elf_mark = 0; + module->format_info[DFI_ELF]->u.elf_info->elf_mark = 0; }
es.pcs = pcs; @@ -1363,14 +1309,19 @@ module = pcs->lmodules; while (module) { - if (module->type == DMT_ELF && !module->is_virtual && - !module->elf_info->elf_mark && !module->elf_info->elf_loader) - { - module_remove(pcs, module); - /* restart all over */ - module = pcs->lmodules; - } - else module = module->next; + if (module->type == DMT_ELF && !module->is_virtual) + { + struct elf_module_info* elf_info = module->format_info[DFI_ELF]->u.elf_info; + + if (!elf_info->elf_mark && !elf_info->elf_loader) + { + module_remove(pcs, module); + /* restart all over */ + module = pcs->lmodules; + continue; + } + } + module = module->next; } return TRUE; } @@ -1415,7 +1366,7 @@
elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE; if (!elf_search_loader(pcs, &elf_info)) return FALSE; - elf_info.module->elf_info->elf_loader = 1; + elf_info.module->format_info[DFI_ELF]->u.elf_info->elf_loader = 1; module_set_module(elf_info.module, S_WineLoaderW); return (pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr) != 0; } @@ -1516,6 +1467,30 @@
#else /* !__ELF__ */
+BOOL elf_find_section(struct image_file_map* fmap, const char* name, + unsigned sht, struct image_section_map* ism) +{ + return FALSE; +} + +const char* elf_map_section(struct image_section_map* ism) +{ + return NULL; +} + +void elf_unmap_section(struct image_section_map* ism) +{} + +unsigned elf_get_map_size(const struct image_section_map* ism) +{ + return 0; +} + +DWORD_PTR elf_get_map_rva(const struct image_section_map* ism) +{ + return 0; +} + BOOL elf_synchronize_module_list(struct process* pcs) { return FALSE; @@ -1542,7 +1517,7 @@ return NULL; }
-BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap) +BOOL elf_load_debug_info(struct module* module, struct image_file_map* fmap) { return FALSE; }
Added: trunk/reactos/dll/win32/dbghelp/image_private.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dbghelp/image_pri... ============================================================================== --- trunk/reactos/dll/win32/dbghelp/image_private.h (added) +++ trunk/reactos/dll/win32/dbghelp/image_private.h [iso-8859-1] Sun Mar 21 22:08:48 2010 @@ -1,0 +1,182 @@ +/* + * File elf_private.h - definitions for processing of ELF files + * + * Copyright (C) 1996, Eric Youngdale. + * 1999-2007 Eric Pouech + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef HAVE_ELF_H +# include <elf.h> +#endif +#ifdef HAVE_SYS_ELF32_H +# include <sys/elf32.h> +#endif +#ifdef HAVE_SYS_EXEC_ELF_H +# include <sys/exec_elf.h> +#endif +#if !defined(DT_NUM) +# if defined(DT_COUNT) +# define DT_NUM DT_COUNT +# else +/* this seems to be a satisfactory value on Solaris, which doesn't support this AFAICT */ +# define DT_NUM 24 +# endif +#endif +#ifdef HAVE_LINK_H +# include <link.h> +#endif +#ifdef HAVE_SYS_LINK_H +# include <sys/link.h> +#endif + +#define IMAGE_NO_MAP ((void*)-1) + +#ifdef __ELF__ + +#ifdef _WIN64 +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Shdr Elf64_Shdr +#define Elf_Phdr Elf64_Phdr +#define Elf_Dyn Elf64_Dyn +#define Elf_Sym Elf64_Sym +#else +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Shdr Elf32_Shdr +#define Elf_Phdr Elf32_Phdr +#define Elf_Dyn Elf32_Dyn +#define Elf_Sym Elf32_Sym +#endif +#else +#ifndef SHT_NULL +#define SHT_NULL 0 +#endif +#endif + +/* structure holding information while handling an ELF image + * allows one by one section mapping for memory savings + */ +struct image_file_map +{ + enum module_type modtype; + union + { + struct elf_file_map + { + size_t elf_size; + size_t elf_start; + int fd; + const char* shstrtab; + struct image_file_map* alternate; /* another ELF file (linked to this one) */ +#ifdef __ELF__ + Elf_Ehdr elfhdr; + struct + { + Elf_Shdr shdr; + const char* mapped; + }* sect; +#endif + } elf; + struct pe_file_map + { + HANDLE hMap; + IMAGE_NT_HEADERS ntheader; + unsigned full_count; + void* full_map; + struct + { + IMAGE_SECTION_HEADER shdr; + const char* mapped; + }* sect; + const char* strtable; + } pe; + } u; +}; + +struct image_section_map +{ + struct image_file_map* fmap; + long sidx; +}; + +extern BOOL elf_find_section(struct image_file_map* fmap, const char* name, + unsigned sht, struct image_section_map* ism); +extern const char* elf_map_section(struct image_section_map* ism); +extern void elf_unmap_section(struct image_section_map* ism); +extern DWORD_PTR elf_get_map_rva(const struct image_section_map* ism); +extern unsigned elf_get_map_size(const struct image_section_map* ism); + +extern BOOL pe_find_section(struct image_file_map* fmap, const char* name, + struct image_section_map* ism); +extern const char* pe_map_section(struct image_section_map* psm); +extern void pe_unmap_section(struct image_section_map* psm); +extern DWORD_PTR pe_get_map_rva(const struct image_section_map* psm); +extern unsigned pe_get_map_size(const struct image_section_map* psm); + +static inline BOOL image_find_section(struct image_file_map* fmap, const char* name, + struct image_section_map* ism) +{ + switch (fmap->modtype) + { + case DMT_ELF: return elf_find_section(fmap, name, SHT_NULL, ism); + case DMT_PE: return pe_find_section(fmap, name, ism); + default: assert(0); return FALSE; + } +} + +static inline const char* image_map_section(struct image_section_map* ism) +{ + if (!ism->fmap) return NULL; + switch (ism->fmap->modtype) + { + case DMT_ELF: return elf_map_section(ism); + case DMT_PE: return pe_map_section(ism); + default: assert(0); return NULL; + } +} + +static inline void image_unmap_section(struct image_section_map* ism) +{ + if (!ism->fmap) return; + switch (ism->fmap->modtype) + { + case DMT_ELF: elf_unmap_section(ism); break; + case DMT_PE: pe_unmap_section(ism); break; + default: assert(0); return; + } +} + +static inline DWORD_PTR image_get_map_rva(struct image_section_map* ism) +{ + if (!ism->fmap) return 0; + switch (ism->fmap->modtype) + { + case DMT_ELF: return elf_get_map_rva(ism); + case DMT_PE: return pe_get_map_rva(ism); + default: assert(0); return 0; + } +} + +static inline unsigned image_get_map_size(struct image_section_map* ism) +{ + if (!ism->fmap) return 0; + switch (ism->fmap->modtype) + { + case DMT_ELF: return elf_get_map_size(ism); + case DMT_PE: return pe_get_map_size(ism); + default: assert(0); return 0; + } +}
Propchange: trunk/reactos/dll/win32/dbghelp/image_private.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/dll/win32/dbghelp/macho_module.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dbghelp/macho_mod... ============================================================================== --- trunk/reactos/dll/win32/dbghelp/macho_module.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/dbghelp/macho_module.c [iso-8859-1] Sun Mar 21 22:08:48 2010 @@ -655,9 +655,10 @@ sc->stroff, sc->strsize, (const void**)&stab, (const void**)&stabstr)) return 0;
- if (!stabs_parse(mdi->module, mdi->module->macho_info->load_addr - fmap->segs_start, - stab, sc->nsyms * sizeof(struct nlist), - stabstr, sc->strsize, macho_stabs_def_cb, mdi)) + if (!stabs_parse(mdi->module, + mdi->module->format_info[DFI_MACHO]->u.macho_info->load_addr - fmap->segs_start, + stab, sc->nsyms * sizeof(struct nlist), + stabstr, sc->strsize, macho_stabs_def_cb, mdi)) ret = -1;
macho_unmap_ranges(fmap, sc->symoff, sc->nsyms * sizeof(struct nlist), @@ -703,7 +704,7 @@ { case SymTagFunction: func = (struct symt_function*)sym; - if (func->address == module->macho_info->load_addr) + if (func->address == module->format_info[DFI_MACHO]->u.macho_info->load_addr) { TRACE("Adjusting function %p/%s!%s from 0x%08lx to 0x%08lx\n", func, debugstr_w(module->module.ModuleName), sym->hash_elt.name, @@ -720,7 +721,7 @@ { case DataIsGlobal: case DataIsFileStatic: - if (data->u.var.offset == module->macho_info->load_addr) + if (data->u.var.offset == module->format_info[DFI_MACHO]->u.macho_info->load_addr) { TRACE("Adjusting data symbol %p/%s!%s from 0x%08lx to 0x%08lx\n", data, debugstr_w(module->module.ModuleName), sym->hash_elt.name, @@ -879,7 +880,7 @@
TRACE("(%p, %p/%d)\n", module, fmap, fmap ? fmap->fd : -1);
- if (module->type != DMT_MACHO || !module->macho_info) + if (module->type != DMT_MACHO || !module->format_info[DFI_MACHO]->u.macho_info) { ERR("Bad Mach-O module '%s'\n", debugstr_w(module->module.LoadedImageName)); return FALSE; @@ -963,26 +964,34 @@
if (macho_info->flags & MACHO_INFO_MODULE) { - struct macho_module_info *macho_module_info = - HeapAlloc(GetProcessHeap(), 0, sizeof(struct macho_module_info)); - if (!macho_module_info) goto leave; + struct macho_module_info *macho_module_info; + struct module_format* modfmt = + HeapAlloc(GetProcessHeap(), 0, sizeof(struct module_format) + sizeof(struct macho_module_info)); + if (!modfmt) goto leave; macho_info->module = module_new(pcs, filename, DMT_MACHO, FALSE, load_addr, fmap.segs_size, 0, calc_crc32(fmap.fd)); if (!macho_info->module) { - HeapFree(GetProcessHeap(), 0, macho_module_info); + HeapFree(GetProcessHeap(), 0, modfmt); goto leave; } - macho_info->module->macho_info = macho_module_info; - macho_info->module->macho_info->load_addr = load_addr; + macho_module_info = (void*)(modfmt + 1); + macho_info->module->format_info[DFI_MACHO] = modfmt; + + modfmt->module = macho_info->module; + modfmt->remove = NULL; + modfmt->loc_compute = NULL; + modfmt->u.macho_info = macho_module_info; + + macho_module_info->load_addr = load_addr;
if (dbghelp_options & SYMOPT_DEFERRED_LOADS) macho_info->module->module.SymType = SymDeferred; else if (!macho_load_debug_info(macho_info->module, &fmap)) ret = FALSE;
- macho_info->module->macho_info->in_use = 1; - macho_info->module->macho_info->is_loader = 0; + macho_info->module->format_info[DFI_MACHO]->u.macho_info->in_use = 1; + macho_info->module->format_info[DFI_MACHO]->u.macho_info->is_loader = 0; TRACE("module = %p\n", macho_info->module); }
@@ -1109,7 +1118,7 @@ if ((module = module_is_already_loaded(pcs, filename))) { macho_info->module = module; - module->macho_info->in_use = 1; + module->format_info[DFI_MACHO]->u.macho_info->in_use = 1; return module->module.SymType; }
@@ -1231,7 +1240,7 @@ for (module = pcs->lmodules; module; module = module->next) { if (module->type == DMT_MACHO && !module->is_virtual) - module->macho_info->in_use = 0; + module->format_info[DFI_MACHO]->u.macho_info->in_use = 0; }
ms.pcs = pcs; @@ -1243,7 +1252,8 @@ while (module) { if (module->type == DMT_MACHO && !module->is_virtual && - !module->macho_info->in_use && !module->macho_info->is_loader) + !module->format_info[DFI_MACHO]->u.macho_info->in_use && + !module->format_info[DFI_MACHO]->u.macho_info->is_loader) { module_remove(pcs, module); /* restart all over */ @@ -1297,7 +1307,7 @@ TRACE("(%p/%p)\n", pcs, pcs->handle); macho_info.flags = MACHO_INFO_DEBUG_HEADER | MACHO_INFO_MODULE; if (!macho_search_loader(pcs, &macho_info)) return FALSE; - macho_info.module->macho_info->is_loader = 1; + macho_info.module->format_info[DFI_MACHO]->u.macho_info->is_loader = 1; module_set_module(macho_info.module, S_WineLoaderW); return (pcs->dbg_hdr_addr = macho_info.dbg_hdr_addr) != 0; }
Modified: trunk/reactos/dll/win32/dbghelp/module.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dbghelp/module.c?... ============================================================================== --- trunk/reactos/dll/win32/dbghelp/module.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/dbghelp/module.c [iso-8859-1] Sun Mar 21 22:08:48 2010 @@ -126,6 +126,7 @@ unsigned long stamp, unsigned long checksum) { struct module* module; + unsigned i;
assert(type == DMT_ELF || type == DMT_PE || type == DMT_MACHO); if (!(module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*module)))) @@ -168,6 +169,7 @@
module->type = type; module->is_virtual = virtual ? TRUE : FALSE; + for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL; module->sortlist_valid = FALSE; module->sorttab_size = 0; module->addr_sorttab = NULL; @@ -621,14 +623,21 @@ */ BOOL module_remove(struct process* pcs, struct module* module) { + struct module_format*modfmt; struct module** p; + unsigned i;
TRACE("%s (%p)\n", debugstr_w(module->module.ModuleName), module); + + for (i = 0; i < DFI_LAST; i++) + { + if ((modfmt = module->format_info[i]) && modfmt->remove) + modfmt->remove(pcs, module->format_info[i]); + } hash_table_destroy(&module->ht_symbols); hash_table_destroy(&module->ht_types); HeapFree(GetProcessHeap(), 0, module->sources); HeapFree(GetProcessHeap(), 0, module->addr_sorttab); - HeapFree(GetProcessHeap(), 0, module->dwarf2_info); pool_destroy(&module->pool); /* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here * so do we
Modified: trunk/reactos/dll/win32/dbghelp/pe_module.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dbghelp/pe_module... ============================================================================== --- trunk/reactos/dll/win32/dbghelp/pe_module.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/dbghelp/pe_module.c [iso-8859-1] Sun Mar 21 22:08:48 2010 @@ -30,10 +30,238 @@ #include <assert.h>
#include "dbghelp_private.h" +#include "image_private.h" #include "winternl.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); + +struct pe_module_info +{ + struct image_file_map fmap; +}; + +static void* pe_map_full(struct image_file_map* fmap, IMAGE_NT_HEADERS** nth) +{ + if (!fmap->u.pe.full_map) + { + fmap->u.pe.full_map = MapViewOfFile(fmap->u.pe.hMap, FILE_MAP_READ, 0, 0, 0); + } + if (fmap->u.pe.full_map) + { + if (nth) *nth = RtlImageNtHeader(fmap->u.pe.full_map); + fmap->u.pe.full_count++; + return fmap->u.pe.full_map; + } + return IMAGE_NO_MAP; +} + +static void pe_unmap_full(struct image_file_map* fmap) +{ + if (fmap->u.pe.full_count && !--fmap->u.pe.full_count) + { + UnmapViewOfFile(fmap->u.pe.full_map); + fmap->u.pe.full_map = NULL; + } +} + +/****************************************************************** + * pe_map_section + * + * Maps a single section into memory from an PE file + */ +const char* pe_map_section(struct image_section_map* ism) +{ + void* mapping; + struct pe_file_map* fmap = &ism->fmap->u.pe; + + if (ism->sidx >= 0 && ism->sidx < fmap->ntheader.FileHeader.NumberOfSections && + fmap->sect[ism->sidx].mapped == IMAGE_NO_MAP) + { + IMAGE_NT_HEADERS* nth; + /* FIXME: that's rather drastic, but that will do for now + * that's ok if the full file map exists, but we could be less agressive otherwise and + * only map the relevant section + */ + if ((mapping = pe_map_full(ism->fmap, &nth))) + { + fmap->sect[ism->sidx].mapped = RtlImageRvaToVa(nth, mapping, + fmap->sect[ism->sidx].shdr.VirtualAddress, + NULL); + return fmap->sect[ism->sidx].mapped; + } + } + return IMAGE_NO_MAP; +} + +/****************************************************************** + * pe_find_section + * + * Finds a section by name (and type) into memory from an PE file + * or its alternate if any + */ +BOOL pe_find_section(struct image_file_map* fmap, const char* name, + struct image_section_map* ism) +{ + const char* sectname; + unsigned i; + char tmp[IMAGE_SIZEOF_SHORT_NAME + 1]; + + for (i = 0; i < fmap->u.pe.ntheader.FileHeader.NumberOfSections; i++) + { + sectname = (const char*)fmap->u.pe.sect[i].shdr.Name; + /* long section names start with a '/' (at least on MinGW32) */ + if (sectname[0] == '/' && fmap->u.pe.strtable) + sectname = fmap->u.pe.strtable + atoi(sectname + 1); + else + { + /* the section name may not be null terminated */ + sectname = memcpy(tmp, sectname, IMAGE_SIZEOF_SHORT_NAME); + tmp[IMAGE_SIZEOF_SHORT_NAME] = '\0'; + } + if (!strcasecmp(sectname, name)) + { + ism->fmap = fmap; + ism->sidx = i; + return TRUE; + } + } + ism->fmap = NULL; + ism->sidx = -1; + + return FALSE; +} + +/****************************************************************** + * pe_unmap_section + * + * Unmaps a single section from memory + */ +void pe_unmap_section(struct image_section_map* ism) +{ + if (ism->sidx >= 0 && ism->sidx < ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections && + ism->fmap->u.pe.sect[ism->sidx].mapped != IMAGE_NO_MAP) + { + pe_unmap_full(ism->fmap); + ism->fmap->u.pe.sect[ism->sidx].mapped = IMAGE_NO_MAP; + } +} + +/****************************************************************** + * pe_get_map_rva + * + * Get the RVA of an PE section + */ +DWORD_PTR pe_get_map_rva(const struct image_section_map* ism) +{ + if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections) + return 0; + return ism->fmap->u.pe.sect[ism->sidx].shdr.VirtualAddress; +} + +/****************************************************************** + * pe_get_map_size + * + * Get the size of an PE section + */ +unsigned pe_get_map_size(const struct image_section_map* ism) +{ + if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections) + return 0; + return ism->fmap->u.pe.sect[ism->sidx].shdr.SizeOfRawData; +} + +/****************************************************************** + * pe_map_file + * + * Maps an PE file into memory (and checks it's a real PE file) + */ +static BOOL pe_map_file(HANDLE file, struct image_file_map* fmap, enum module_type mt) +{ + void* mapping; + + fmap->modtype = mt; + fmap->u.pe.hMap = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL); + if (fmap->u.pe.hMap == 0) return FALSE; + fmap->u.pe.full_count = 0; + fmap->u.pe.full_map = NULL; + if (!(mapping = pe_map_full(fmap, NULL))) goto error; + + switch (mt) + { + case DMT_PE: + { + IMAGE_NT_HEADERS* nthdr; + IMAGE_SECTION_HEADER* section; + unsigned i; + + if (!(nthdr = RtlImageNtHeader(mapping))) goto error; + memcpy(&fmap->u.pe.ntheader, nthdr, sizeof(fmap->u.pe.ntheader)); + section = (IMAGE_SECTION_HEADER*) + ((char*)&nthdr->OptionalHeader + nthdr->FileHeader.SizeOfOptionalHeader); + fmap->u.pe.sect = HeapAlloc(GetProcessHeap(), 0, + nthdr->FileHeader.NumberOfSections * sizeof(fmap->u.pe.sect[0])); + if (!fmap->u.pe.sect) goto error; + for (i = 0; i < nthdr->FileHeader.NumberOfSections; i++) + { + memcpy(&fmap->u.pe.sect[i].shdr, section + i, sizeof(IMAGE_SECTION_HEADER)); + fmap->u.pe.sect[i].mapped = IMAGE_NO_MAP; + } + if (nthdr->FileHeader.PointerToSymbolTable && nthdr->FileHeader.NumberOfSymbols) + { + /* FIXME ugly: should rather map the relevant content instead of copying it */ + const char* src = (const char*)mapping + + nthdr->FileHeader.PointerToSymbolTable + + nthdr->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL); + char* dst; + DWORD sz = *(DWORD*)src; + + if ((dst = HeapAlloc(GetProcessHeap(), 0, sz))) + memcpy(dst, src, sz); + fmap->u.pe.strtable = dst; + } + else fmap->u.pe.strtable = NULL; + } + break; + default: assert(0); goto error; + } + pe_unmap_full(fmap); + + return TRUE; +error: + pe_unmap_full(fmap); + CloseHandle(fmap->u.pe.hMap); + return FALSE; +} + +/****************************************************************** + * pe_unmap_file + * + * Unmaps an PE file from memory (previously mapped with pe_map_file) + */ +static void pe_unmap_file(struct image_file_map* fmap) +{ + if (fmap->u.pe.hMap != 0) + { + struct image_section_map ism; + ism.fmap = fmap; + for (ism.sidx = 0; ism.sidx < fmap->u.pe.ntheader.FileHeader.NumberOfSections; ism.sidx++) + { + pe_unmap_section(&ism); + } + while (fmap->u.pe.full_count) pe_unmap_full(fmap); + HeapFree(GetProcessHeap(), 0, fmap->u.pe.sect); + HeapFree(GetProcessHeap(), 0, (void*)fmap->u.pe.strtable); /* FIXME ugly (see pe_map_file) */ + CloseHandle(fmap->u.pe.hMap); + fmap->u.pe.hMap = NULL; + } +} + +static void pe_module_remove(struct process* pcs, struct module_format* modfmt) +{ + pe_unmap_file(&modfmt->u.pe_info->fmap); + HeapFree(GetProcessHeap(), 0, modfmt); +}
/****************************************************************** * pe_locate_with_coff_symbol_table @@ -43,37 +271,35 @@ * Mingw32 requires this for stabs debug information as address for global variables isn't filled in * (this is similar to what is done in elf_module.c when using the .symtab ELF section) */ -static BOOL pe_locate_with_coff_symbol_table(struct module* module, IMAGE_NT_HEADERS* nth, void* mapping) -{ +static BOOL pe_locate_with_coff_symbol_table(struct module* module) +{ + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; const IMAGE_SYMBOL* isym; int i, numsym, naux; - const char* strtable; char tmp[9]; const char* name; struct hash_table_iter hti; void* ptr; struct symt_data* sym; - const IMAGE_SECTION_HEADER* sect; - - numsym = nth->FileHeader.NumberOfSymbols; - if (!nth->FileHeader.PointerToSymbolTable || !numsym) + const char* mapping; + + numsym = fmap->u.pe.ntheader.FileHeader.NumberOfSymbols; + if (!fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable || !numsym) return TRUE; - isym = (const IMAGE_SYMBOL*)((char*)mapping + nth->FileHeader.PointerToSymbolTable); - /* FIXME: no way to get strtable size */ - strtable = (const char*)&isym[numsym]; - sect = IMAGE_FIRST_SECTION(nth); + if (!(mapping = pe_map_full(fmap, NULL))) return FALSE; + isym = (const IMAGE_SYMBOL*)(mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable);
for (i = 0; i < numsym; i+= naux, isym += naux) { if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL && - isym->SectionNumber > 0 && isym->SectionNumber <= nth->FileHeader.NumberOfSections) + isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.ntheader.FileHeader.NumberOfSections) { if (isym->N.Name.Short) { name = memcpy(tmp, isym->N.ShortName, 8); tmp[8] = '\0'; } - else name = strtable + isym->N.Name.Long; + else name = fmap->u.pe.strtable + isym->N.Name.Long; if (name[0] == '_') name++; hash_table_iter_init(&module->ht_symbols, &hti, name); while ((ptr = hash_table_iter_up(&hti))) @@ -86,15 +312,17 @@ TRACE("Changing absolute address for %d.%s: %lx -> %s\n", isym->SectionNumber, name, sym->u.var.offset, wine_dbgstr_longlong(module->module.BaseOfImage + - sect[isym->SectionNumber - 1].VirtualAddress + isym->Value)); + fmap->u.pe.sect[isym->SectionNumber - 1].shdr.VirtualAddress + + isym->Value)); sym->u.var.offset = module->module.BaseOfImage + - sect[isym->SectionNumber - 1].VirtualAddress + isym->Value; + fmap->u.pe.sect[isym->SectionNumber - 1].shdr.VirtualAddress + isym->Value; break; } } } naux = isym->NumberOfAuxSymbols + 1; } + pe_unmap_full(fmap); return TRUE; }
@@ -103,8 +331,9 @@ * * Load public symbols out of the COFF symbol table (if any). */ -static BOOL pe_load_coff_symbol_table(struct module* module, IMAGE_NT_HEADERS* nth, void* mapping) -{ +static BOOL pe_load_coff_symbol_table(struct module* module) +{ + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; const IMAGE_SYMBOL* isym; int i, numsym, naux; const char* strtable; @@ -113,14 +342,16 @@ const char* lastfilename = NULL; struct symt_compiland* compiland = NULL; const IMAGE_SECTION_HEADER* sect; - - numsym = nth->FileHeader.NumberOfSymbols; - if (!nth->FileHeader.PointerToSymbolTable || !numsym) + const char* mapping; + + numsym = fmap->u.pe.ntheader.FileHeader.NumberOfSymbols; + if (!fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable || !numsym) return TRUE; - isym = (const IMAGE_SYMBOL*)((char*)mapping + nth->FileHeader.PointerToSymbolTable); + if (!(mapping = pe_map_full(fmap, NULL))) return FALSE; + isym = (const IMAGE_SYMBOL*)((char*)mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable); /* FIXME: no way to get strtable size */ strtable = (const char*)&isym[numsym]; - sect = IMAGE_FIRST_SECTION(nth); + sect = IMAGE_FIRST_SECTION(&fmap->u.pe.ntheader);
for (i = 0; i < numsym; i+= naux, isym += naux) { @@ -130,7 +361,7 @@ compiland = NULL; } if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL && - isym->SectionNumber > 0 && isym->SectionNumber <= nth->FileHeader.NumberOfSections) + isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.ntheader.FileHeader.NumberOfSections) { if (isym->N.Name.Short) { @@ -143,9 +374,12 @@ if (!compiland && lastfilename) compiland = symt_new_compiland(module, 0, source_new(module, NULL, lastfilename)); - symt_new_public(module, compiland, name, - module->module.BaseOfImage + sect[isym->SectionNumber - 1].VirtualAddress + isym->Value, - 1); + + if (!(dbghelp_options & SYMOPT_NO_PUBLICS)) + symt_new_public(module, compiland, name, + module->module.BaseOfImage + sect[isym->SectionNumber - 1].VirtualAddress + + isym->Value, + 1); } naux = isym->NumberOfAuxSymbols + 1; } @@ -155,6 +389,7 @@ module->module.TypeInfo = FALSE; module->module.SourceIndexed = FALSE; module->module.Publics = TRUE; + pe_unmap_full(fmap);
return TRUE; } @@ -176,30 +411,30 @@ * look for stabs information in PE header (it's how the mingw compiler provides * its debugging information) */ -static BOOL pe_load_stabs(const struct process* pcs, struct module* module, - void* mapping, IMAGE_NT_HEADERS* nth) -{ - IMAGE_SECTION_HEADER* section; - IMAGE_SECTION_HEADER* sect_stabs = NULL; - IMAGE_SECTION_HEADER* sect_stabstr = NULL; - int i; +static BOOL pe_load_stabs(const struct process* pcs, struct module* module) +{ + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; + struct image_section_map sect_stabs, sect_stabstr; BOOL ret = FALSE;
- section = (IMAGE_SECTION_HEADER*) - ((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader); - for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++) - { - if (!strcasecmp((const char*)section->Name, ".stab")) sect_stabs = section; - else if (!strncasecmp((const char*)section->Name, ".stabstr", 8)) sect_stabstr = section; - } - if (sect_stabs && sect_stabstr) - { - ret = stabs_parse(module, - module->module.BaseOfImage - nth->OptionalHeader.ImageBase, - pe_get_sect(nth, mapping, sect_stabs), pe_get_sect_size(sect_stabs), - pe_get_sect(nth, mapping, sect_stabstr), pe_get_sect_size(sect_stabstr), - NULL, NULL); - if (ret) pe_locate_with_coff_symbol_table(module, nth, mapping); + if (pe_find_section(fmap, ".stab", §_stabs) && pe_find_section(fmap, ".stabstr", §_stabstr)) + { + const char* stab; + const char* stabstr; + + stab = image_map_section(§_stabs); + stabstr = image_map_section(§_stabstr); + if (stab != IMAGE_NO_MAP && stabstr != IMAGE_NO_MAP) + { + ret = stabs_parse(module, + module->module.BaseOfImage - fmap->u.pe.ntheader.OptionalHeader.ImageBase, + stab, image_get_map_size(§_stabs), + stabstr, image_get_map_size(§_stabstr), + NULL, NULL); + } + image_unmap_section(§_stabs); + image_unmap_section(§_stabstr); + if (ret) pe_locate_with_coff_symbol_table(module); } TRACE("%s the STABS debug info\n", ret ? "successfully loaded" : "failed to load");
@@ -212,51 +447,15 @@ * 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; +static BOOL pe_load_dwarf(struct module* module) +{ + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; BOOL ret = FALSE;
- 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)); - } + ret = dwarf2_parse(module, + module->module.BaseOfImage - fmap->u.pe.ntheader.OptionalHeader.ImageBase, + NULL, /* FIXME: some thunks to deal with ? */ + fmap); TRACE("%s the DWARF debug info\n", ret ? "successfully loaded" : "failed to load");
return ret; @@ -314,19 +513,21 @@ * * Process MSC debug information in PE file. */ -static BOOL pe_load_msc_debug_info(const struct process* pcs, - struct module* module, - void* mapping, const IMAGE_NT_HEADERS* nth) -{ +static BOOL pe_load_msc_debug_info(const struct process* pcs, struct module* module) +{ + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; BOOL ret = FALSE; const IMAGE_DATA_DIRECTORY* dir; const IMAGE_DEBUG_DIRECTORY*dbg = NULL; int nDbg; - + void* mapping; + IMAGE_NT_HEADERS* nth; + + if (!(mapping = pe_map_full(fmap, &nth))) return FALSE; /* Read in debug directory */ dir = nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG; nDbg = dir->Size / sizeof(IMAGE_DEBUG_DIRECTORY); - if (!nDbg) return FALSE; + if (!nDbg) goto done;
dbg = RtlImageRvaToVa(nth, mapping, dir->VirtualAddress, NULL);
@@ -353,26 +554,29 @@ const IMAGE_SECTION_HEADER *sectp = (const IMAGE_SECTION_HEADER*)((const char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader); /* Debug info is embedded into PE module */ ret = pe_load_debug_directory(pcs, module, mapping, sectp, - nth->FileHeader.NumberOfSections, dbg, nDbg); - } - + nth->FileHeader.NumberOfSections, dbg, nDbg); + } +done: + pe_unmap_full(fmap); return ret; }
/*********************************************************************** * pe_load_export_debug_info */ -static BOOL pe_load_export_debug_info(const struct process* pcs, - struct module* module, - void* mapping, const IMAGE_NT_HEADERS* nth) -{ +static BOOL pe_load_export_debug_info(const struct process* pcs, struct module* module) +{ + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; unsigned int i; const IMAGE_EXPORT_DIRECTORY* exports; DWORD base = module->module.BaseOfImage; DWORD size; + IMAGE_NT_HEADERS* nth; + void* mapping;
if (dbghelp_options & SYMOPT_NO_PUBLICS) return TRUE;
+ if (!(mapping = pe_map_full(fmap, &nth))) return FALSE; #if 0 /* Add start of DLL (better use the (yet unimplemented) Exe SymTag for this) */ /* FIXME: module.ModuleName isn't correctly set yet if it's passed in SymLoadModule */ @@ -435,6 +639,8 @@ /* no real debug info, only entry points */ if (module->module.SymType == SymDeferred) module->module.SymType = SymExport; + pe_unmap_full(fmap); + return TRUE; }
@@ -445,39 +651,21 @@ BOOL pe_load_debug_info(const struct process* pcs, struct module* module) { BOOL ret = FALSE; - HANDLE hFile; - HANDLE hMap; - void* mapping; - IMAGE_NT_HEADERS* nth; - - hFile = CreateFileW(module->module.LoadedImageName, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) return ret; - if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) - { - if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) - { - nth = RtlImageNtHeader(mapping); - - if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) - { - 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_coff_symbol_table(module, nth, mapping); - /* 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, - * in which case we'll rely on the export's on the ELF side - */ - } -/* FIXME shouldn't we check that? if (!module_get_debug(pcs, module))l */ - if (pe_load_export_debug_info(pcs, module, mapping, nth) && !ret) - ret = TRUE; - UnmapViewOfFile(mapping); - } - CloseHandle(hMap); - } - CloseHandle(hFile); + + if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) + { + ret = pe_load_stabs(pcs, module); + ret = pe_load_dwarf(module) || ret; + ret = pe_load_msc_debug_info(pcs, module) || ret; + ret = ret || pe_load_coff_symbol_table(module); /* FIXME */ + /* 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, + * in which case we'll rely on the export's on the ELF side + */ + } + /* FIXME shouldn't we check that? if (!module_get_debug(pcs, module)) */ + if (pe_load_export_debug_info(pcs, module) && !ret) + ret = TRUE;
return ret; } @@ -489,15 +677,14 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name, HANDLE hFile, DWORD base, DWORD size) { - struct module* module = NULL; - BOOL opened = FALSE; - HANDLE hMap; - WCHAR loaded_name[MAX_PATH]; + struct module* module = NULL; + BOOL opened = FALSE; + struct module_format* modfmt; + WCHAR loaded_name[MAX_PATH];
loaded_name[0] = '\0'; if (!hFile) { - assert(name);
if ((hFile = FindExecutableImageExW(name, pcs->search_path, loaded_name, NULL, NULL)) == NULL) @@ -507,37 +694,37 @@ else if (name) strcpyW(loaded_name, name); else if (dbghelp_options & SYMOPT_DEFERRED_LOADS) FIXME("Trouble ahead (no module name passed in deferred mode)\n"); - - if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) - { - void* mapping; - - if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) - { - IMAGE_NT_HEADERS* nth = RtlImageNtHeader(mapping); - - if (nth) - { - if (!base) base = nth->OptionalHeader.ImageBase; - if (!size) size = nth->OptionalHeader.SizeOfImage; - - module = module_new(pcs, loaded_name, DMT_PE, FALSE, base, size, - nth->FileHeader.TimeDateStamp, - nth->OptionalHeader.CheckSum); - if (module) - { - if (dbghelp_options & SYMOPT_DEFERRED_LOADS) - module->module.SymType = SymDeferred; - else - pe_load_debug_info(pcs, module); - } - else - ERR("could not load the module '%s'\n", debugstr_w(loaded_name)); - } - UnmapViewOfFile(mapping); - } - CloseHandle(hMap); - } + if (!(modfmt = HeapAlloc(GetProcessHeap(), 0, sizeof(struct module_format) + sizeof(struct pe_module_info)))) + return NULL; + modfmt->u.pe_info = (struct pe_module_info*)(modfmt + 1); + if (pe_map_file(hFile, &modfmt->u.pe_info->fmap, DMT_PE)) + { + if (!base) base = modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.ImageBase; + if (!size) size = modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.SizeOfImage; + + module = module_new(pcs, loaded_name, DMT_PE, FALSE, base, size, + modfmt->u.pe_info->fmap.u.pe.ntheader.FileHeader.TimeDateStamp, + modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.CheckSum); + if (module) + { + modfmt->module = module; + modfmt->remove = pe_module_remove; + modfmt->loc_compute = NULL; + + module->format_info[DFI_PE] = modfmt; + if (dbghelp_options & SYMOPT_DEFERRED_LOADS) + module->module.SymType = SymDeferred; + else + pe_load_debug_info(pcs, module); + } + else + { + ERR("could not load the module '%s'\n", debugstr_w(loaded_name)); + pe_unmap_file(&modfmt->u.pe_info->fmap); + } + } + if (!module) HeapFree(GetProcessHeap(), 0, modfmt); + if (opened) CloseHandle(hFile);
return module;
Modified: trunk/reactos/dll/win32/dbghelp/symbol.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dbghelp/symbol.c?... ============================================================================== --- trunk/reactos/dll/win32/dbghelp/symbol.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/dbghelp/symbol.c [iso-8859-1] Sun Mar 21 22:08:48 2010 @@ -693,8 +693,20 @@ struct location loc = data->u.var;
if (loc.kind >= loc_user) - pair->effective->loc_compute(pair->pcs, pair->effective, func, &loc); - + { + unsigned i; + struct module_format* modfmt; + + for (i = 0; i < DFI_LAST; i++) + { + modfmt = pair->effective->format_info[i]; + if (modfmt && modfmt->loc_compute) + { + modfmt->loc_compute(pair->pcs, modfmt, func, &loc); + break; + } + } + } switch (loc.kind) { case loc_error: