Module: wine Branch: master Commit: 749dafd987111543279a62f8a480c904f8b04667 URL: http://source.winehq.org/git/wine.git/?a=commit;h=749dafd987111543279a62f8a4...
Author: Eric Pouech eric.pouech@orange.fr Date: Mon Dec 27 15:03:30 2010 +0100
dbghelp: Extend elf_map_file so that it can also handle ELF maps directly from debuggee address space.
---
dlls/dbghelp/elf_module.c | 126 ++++++++++++++++++++++++++++++++++++------ dlls/dbghelp/image_private.h | 1 + 2 files changed, 109 insertions(+), 18 deletions(-)
diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index 1b8ba70..305f420 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -110,6 +110,10 @@ const char* elf_map_section(struct image_section_map* ism) fmap->sect[ism->sidx].shdr.sh_type == SHT_NOBITS) return IMAGE_NO_MAP;
+ if (fmap->target_copy) + { + return fmap->target_copy + fmap->sect[ism->sidx].shdr.sh_offset; + } /* align required information on page size (we assume pagesize is a power of 2) */ ofst = fmap->sect[ism->sidx].shdr.sh_offset & ~(pgsz - 1); size = ((fmap->sect[ism->sidx].shdr.sh_offset + @@ -166,7 +170,8 @@ 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) + if (ism->sidx >= 0 && ism->sidx < fmap->elfhdr.e_shnum && !fmap->target_copy && + fmap->sect[ism->sidx].mapped != IMAGE_NO_MAP) { unsigned long pgsz = getpagesize(); unsigned long ofst, size; @@ -223,6 +228,41 @@ 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; + fmap->u.elf.target_copy = NULL; +} + +struct elf_map_file_data +{ + enum {from_file, from_process} kind; + union + { + struct + { + const WCHAR* filename; + } file; + struct + { + HANDLE handle; + void* load_addr; + } process; + } u; +}; + +static BOOL elf_map_file_read(struct image_file_map* fmap, struct elf_map_file_data* emfd, + void* buf, size_t len, off_t off) +{ + SIZE_T dw; + + switch (emfd->kind) + { + case from_file: + return pread(fmap->u.elf.fd, buf, len, off) == len; + case from_process: + return ReadProcessMemory(emfd->u.process.handle, + (void*)((unsigned long)emfd->u.process.load_addr + (unsigned long)off), + buf, len, &dw) && dw == len; + default: assert(0); + } }
/****************************************************************** @@ -230,7 +270,7 @@ static inline void elf_reset_file_map(struct image_file_map* fmap) * * Maps an ELF file into memory (and checks it's a real ELF file) */ -static BOOL elf_map_file(const WCHAR* filenameW, struct image_file_map* fmap) +static BOOL elf_map_file(struct elf_map_file_data* emfd, struct image_file_map* fmap) { static const BYTE elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 }; struct stat statbuf; @@ -241,21 +281,40 @@ static BOOL elf_map_file(const WCHAR* filenameW, struct image_file_map* fmap) unsigned len; BOOL ret = FALSE;
- len = WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, NULL, 0, NULL, NULL); - if (!(filename = HeapAlloc(GetProcessHeap(), 0, len))) return FALSE; - WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, filename, len, NULL, NULL); + switch (emfd->kind) + { + case from_file: + len = WideCharToMultiByte(CP_UNIXCP, 0, emfd->u.file.filename, -1, NULL, 0, NULL, NULL); + if (!(filename = HeapAlloc(GetProcessHeap(), 0, len))) return FALSE; + WideCharToMultiByte(CP_UNIXCP, 0, emfd->u.file.filename, -1, filename, len, NULL, NULL); + break; + case from_process: + filename = NULL; + break; + default: assert(0); + }
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->u.elf.fd = open(filename, O_RDONLY)) == -1) goto done; + fmap->u.elf.fd = -1; + fmap->u.elf.target_copy = NULL;
- if (read(fmap->u.elf.fd, &fmap->u.elf.elfhdr, sizeof(fmap->u.elf.elfhdr)) != sizeof(fmap->u.elf.elfhdr)) + switch (emfd->kind) + { + case from_file: + /* 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->u.elf.fd = open(filename, O_RDONLY)) == -1) goto done; + break; + case from_process: + break; + } + if (!elf_map_file_read(fmap, emfd, &fmap->u.elf.elfhdr, sizeof(fmap->u.elf.elfhdr), 0)) goto done; + /* and check for an ELF header */ if (memcmp(fmap->u.elf.elfhdr.e_ident, elf_signature, sizeof(elf_signature))) goto done; @@ -271,8 +330,8 @@ static BOOL elf_map_file(const WCHAR* filenameW, struct image_file_map* fmap)
for (i = 0; i < fmap->u.elf.elfhdr.e_shnum; i++) { - if (pread(fmap->u.elf.fd, &fmap->u.elf.sect[i].shdr, sizeof(fmap->u.elf.sect[i].shdr), - fmap->u.elf.elfhdr.e_shoff + i * sizeof(fmap->u.elf.sect[i].shdr)) != sizeof(fmap->u.elf.sect[i].shdr)) + if (!elf_map_file_read(fmap, emfd, &fmap->u.elf.sect[i].shdr, sizeof(fmap->u.elf.sect[i].shdr), + fmap->u.elf.elfhdr.e_shoff + i * sizeof(fmap->u.elf.sect[i].shdr))) { HeapFree(GetProcessHeap(), 0, fmap->u.elf.sect); fmap->u.elf.sect = NULL; @@ -286,8 +345,8 @@ static BOOL elf_map_file(const WCHAR* filenameW, struct image_file_map* fmap) fmap->u.elf.elf_start = ~0L; for (i = 0; i < fmap->u.elf.elfhdr.e_phnum; i++) { - if (pread(fmap->u.elf.fd, &phdr, sizeof(phdr), - fmap->u.elf.elfhdr.e_phoff + i * sizeof(phdr)) == sizeof(phdr) && + if (elf_map_file_read(fmap, emfd, &phdr, sizeof(phdr), + fmap->u.elf.elfhdr.e_phoff + i * sizeof(phdr)) && phdr.p_type == PT_LOAD) { tmp = (phdr.p_vaddr + phdr.p_memsz + page_mask) & ~page_mask; @@ -299,6 +358,25 @@ static BOOL elf_map_file(const WCHAR* filenameW, struct image_file_map* fmap) * otherwise, all addresses are zero based and start has no effect */ fmap->u.elf.elf_size -= fmap->u.elf.elf_start; + + switch (emfd->kind) + { + case from_file: break; + case from_process: + if (!(fmap->u.elf.target_copy = HeapAlloc(GetProcessHeap(), 0, fmap->u.elf.elf_size))) + { + HeapFree(GetProcessHeap(), 0, fmap->u.elf.sect); + goto done; + } + if (!ReadProcessMemory(emfd->u.process.handle, emfd->u.process.load_addr, fmap->u.elf.target_copy, + fmap->u.elf.elf_size, NULL)) + { + HeapFree(GetProcessHeap(), 0, fmap->u.elf.target_copy); + HeapFree(GetProcessHeap(), 0, fmap->u.elf.sect); + goto done; + } + break; + } ret = TRUE; done: HeapFree(GetProcessHeap(), 0, filename); @@ -325,6 +403,7 @@ static void elf_unmap_file(struct image_file_map* fmap) HeapFree(GetProcessHeap(), 0, fmap->u.elf.sect); close(fmap->u.elf.fd); } + HeapFree(GetProcessHeap(), 0, fmap->u.elf.target_copy); fmap = fmap->u.elf.alternate; } } @@ -737,7 +816,11 @@ static int elf_new_public_symbols(struct module* module, const struct hash_table 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; + struct elf_map_file_data emfd; + + emfd.kind = from_file; + emfd.u.file.filename = file; + if (!elf_map_file(&emfd, fmap)) return FALSE; if (!(ret = crc == calc_crc32(fmap->u.elf.fd))) { WARN("Bad CRC for file %s (got %08x while expecting %08x)\n", @@ -979,7 +1062,11 @@ BOOL elf_fetch_file_info(const WCHAR* name, DWORD_PTR* base, { struct image_file_map fmap;
- if (!elf_map_file(name, &fmap)) return FALSE; + struct elf_map_file_data emfd; + + emfd.kind = from_file; + emfd.u.file.filename = name; + if (!elf_map_file(&emfd, &fmap)) return FALSE; if (base) *base = fmap.u.elf.elf_start; *size = fmap.u.elf.elf_size; *checksum = calc_crc32(fmap.u.elf.fd); @@ -1110,10 +1197,13 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename, { BOOL ret = FALSE; struct image_file_map fmap; + struct elf_map_file_data emfd;
TRACE("Processing elf file '%s' at %08lx\n", debugstr_w(filename), load_offset);
- if (!elf_map_file(filename, &fmap)) return ret; + emfd.kind = from_file; + emfd.u.file.filename = filename; + if (!elf_map_file(&emfd, &fmap)) return ret;
/* Next, we need to find a few of the internal ELF headers within * this thing. We need the main executable header, and the section diff --git a/dlls/dbghelp/image_private.h b/dlls/dbghelp/image_private.h index 808f6a1..34e2c18 100644 --- a/dlls/dbghelp/image_private.h +++ b/dlls/dbghelp/image_private.h @@ -81,6 +81,7 @@ struct image_file_map int fd; const char* shstrtab; struct image_file_map* alternate; /* another ELF file (linked to this one) */ + char* target_copy; #ifdef __ELF__ Elf_Ehdr elfhdr; struct