Eric Pouech : dbghelp: Extend elf_map_file so that it can also handle ELF maps directly from debuggee address space .
Alexandre Julliard
julliard at winehq.org
Tue Dec 28 10:48:18 CST 2010
Module: wine
Branch: master
Commit: 749dafd987111543279a62f8a480c904f8b04667
URL: http://source.winehq.org/git/wine.git/?a=commit;h=749dafd987111543279a62f8a480c904f8b04667
Author: Eric Pouech <eric.pouech at 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
More information about the wine-cvs
mailing list