dbghelp: Create the notion of image (PE, ELF modules) to uniformize some handlings.
This commit is contained in:
parent
fb169502a5
commit
cbff4f063f
|
@ -474,8 +474,8 @@ typedef BOOL (*enum_modules_cb)(const WCHAR*, unsigned long addr, void* user);
|
||||||
/* elf_module.c */
|
/* elf_module.c */
|
||||||
extern BOOL elf_enum_modules(HANDLE hProc, enum_modules_cb, void*);
|
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);
|
extern BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum);
|
||||||
struct elf_file_map;
|
struct image_file_map;
|
||||||
extern BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap);
|
extern BOOL elf_load_debug_info(struct module* module, struct image_file_map* fmap);
|
||||||
extern struct module*
|
extern struct module*
|
||||||
elf_load_module(struct process* pcs, const WCHAR* name, unsigned long);
|
elf_load_module(struct process* pcs, const WCHAR* name, unsigned long);
|
||||||
extern BOOL elf_read_wine_loader_dbg_info(struct process* pcs);
|
extern BOOL elf_read_wine_loader_dbg_info(struct process* pcs);
|
||||||
|
|
|
@ -90,7 +90,7 @@ struct elf_module_info
|
||||||
unsigned long elf_addr;
|
unsigned long elf_addr;
|
||||||
unsigned short elf_mark : 1,
|
unsigned short elf_mark : 1,
|
||||||
elf_loader : 1;
|
elf_loader : 1;
|
||||||
struct elf_file_map file_map;
|
struct image_file_map file_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
|
@ -98,23 +98,26 @@ struct elf_module_info
|
||||||
*
|
*
|
||||||
* Maps a single section into memory from an ELF file
|
* Maps a single section into memory from an ELF file
|
||||||
*/
|
*/
|
||||||
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 pgsz = getpagesize();
|
||||||
unsigned ofst, size;
|
unsigned ofst, size;
|
||||||
|
|
||||||
if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum ||
|
assert(ism->fmap->modtype == DMT_ELF);
|
||||||
esm->fmap->sect[esm->sidx].shdr.sh_type == SHT_NOBITS)
|
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;
|
return IMAGE_NO_MAP;
|
||||||
|
|
||||||
/* align required information on page size (we assume pagesize is a power of 2) */
|
/* 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);
|
ofst = fmap->sect[ism->sidx].shdr.sh_offset & ~(pgsz - 1);
|
||||||
size = ((esm->fmap->sect[esm->sidx].shdr.sh_offset +
|
size = ((fmap->sect[ism->sidx].shdr.sh_offset +
|
||||||
esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst;
|
fmap->sect[ism->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst;
|
||||||
esm->fmap->sect[esm->sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE,
|
fmap->sect[ism->sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE,
|
||||||
esm->fmap->fd, ofst);
|
fmap->fd, ofst);
|
||||||
if (esm->fmap->sect[esm->sidx].mapped == IMAGE_NO_MAP) return IMAGE_NO_MAP;
|
if (fmap->sect[ism->sidx].mapped == IMAGE_NO_MAP) return IMAGE_NO_MAP;
|
||||||
return esm->fmap->sect[esm->sidx].mapped + (esm->fmap->sect[esm->sidx].shdr.sh_offset & (pgsz - 1));
|
return fmap->sect[ism->sidx].mapped + (fmap->sect[ism->sidx].shdr.sh_offset & (pgsz - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
|
@ -123,32 +126,34 @@ const char* elf_map_section(struct elf_section_map* esm)
|
||||||
* Finds a section by name (and type) into memory from an ELF file
|
* Finds a section by name (and type) into memory from an ELF file
|
||||||
* or its alternate if any
|
* or its alternate if any
|
||||||
*/
|
*/
|
||||||
BOOL elf_find_section(struct elf_file_map* fmap, const char* name,
|
BOOL elf_find_section(struct image_file_map* _fmap, const char* name,
|
||||||
unsigned sht, struct elf_section_map* esm)
|
unsigned sht, struct image_section_map* ism)
|
||||||
{
|
{
|
||||||
|
struct elf_file_map* fmap;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
while (fmap)
|
while (_fmap)
|
||||||
{
|
{
|
||||||
|
fmap = &_fmap->u.elf;
|
||||||
if (fmap->shstrtab == IMAGE_NO_MAP)
|
if (fmap->shstrtab == IMAGE_NO_MAP)
|
||||||
{
|
{
|
||||||
struct elf_section_map hdr_esm = {fmap, fmap->elfhdr.e_shstrndx};
|
struct image_section_map hdr_ism = {_fmap, fmap->elfhdr.e_shstrndx};
|
||||||
if ((fmap->shstrtab = elf_map_section(&hdr_esm)) == IMAGE_NO_MAP) break;
|
if ((fmap->shstrtab = elf_map_section(&hdr_ism)) == IMAGE_NO_MAP) break;
|
||||||
}
|
}
|
||||||
for (i = 0; i < fmap->elfhdr.e_shnum; i++)
|
for (i = 0; i < fmap->elfhdr.e_shnum; i++)
|
||||||
{
|
{
|
||||||
if (strcmp(fmap->shstrtab + fmap->sect[i].shdr.sh_name, name) == 0 &&
|
if (strcmp(fmap->shstrtab + fmap->sect[i].shdr.sh_name, name) == 0 &&
|
||||||
(sht == SHT_NULL || sht == fmap->sect[i].shdr.sh_type))
|
(sht == SHT_NULL || sht == fmap->sect[i].shdr.sh_type))
|
||||||
{
|
{
|
||||||
esm->fmap = fmap;
|
ism->fmap = _fmap;
|
||||||
esm->sidx = i;
|
ism->sidx = i;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmap = fmap->alternate;
|
_fmap = fmap->alternate;
|
||||||
}
|
}
|
||||||
esm->fmap = NULL;
|
ism->fmap = NULL;
|
||||||
esm->sidx = -1;
|
ism->sidx = -1;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,33 +162,35 @@ BOOL elf_find_section(struct elf_file_map* fmap, const char* name,
|
||||||
*
|
*
|
||||||
* Unmaps a single section from memory
|
* Unmaps a single section from memory
|
||||||
*/
|
*/
|
||||||
void elf_unmap_section(struct elf_section_map* esm)
|
void elf_unmap_section(struct image_section_map* ism)
|
||||||
{
|
{
|
||||||
if (esm->sidx >= 0 && esm->sidx < esm->fmap->elfhdr.e_shnum && esm->fmap->sect[esm->sidx].mapped != IMAGE_NO_MAP)
|
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 pgsz = getpagesize();
|
||||||
unsigned ofst, size;
|
unsigned ofst, size;
|
||||||
|
|
||||||
ofst = esm->fmap->sect[esm->sidx].shdr.sh_offset & ~(pgsz - 1);
|
ofst = fmap->sect[ism->sidx].shdr.sh_offset & ~(pgsz - 1);
|
||||||
size = ((esm->fmap->sect[esm->sidx].shdr.sh_offset +
|
size = ((fmap->sect[ism->sidx].shdr.sh_offset +
|
||||||
esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst;
|
fmap->sect[ism->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst;
|
||||||
if (munmap((char*)esm->fmap->sect[esm->sidx].mapped, size) < 0)
|
if (munmap((char*)fmap->sect[ism->sidx].mapped, size) < 0)
|
||||||
WARN("Couldn't unmap the section\n");
|
WARN("Couldn't unmap the section\n");
|
||||||
esm->fmap->sect[esm->sidx].mapped = IMAGE_NO_MAP;
|
fmap->sect[ism->sidx].mapped = IMAGE_NO_MAP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void elf_end_find(struct elf_file_map* fmap)
|
static void elf_end_find(struct image_file_map* fmap)
|
||||||
{
|
{
|
||||||
struct elf_section_map esm;
|
struct image_section_map ism;
|
||||||
|
|
||||||
while (fmap)
|
while (fmap)
|
||||||
{
|
{
|
||||||
esm.fmap = fmap;
|
ism.fmap = fmap;
|
||||||
esm.sidx = fmap->elfhdr.e_shstrndx;
|
ism.sidx = fmap->u.elf.elfhdr.e_shstrndx;
|
||||||
elf_unmap_section(&esm);
|
elf_unmap_section(&ism);
|
||||||
fmap->shstrtab = IMAGE_NO_MAP;
|
fmap->u.elf.shstrtab = IMAGE_NO_MAP;
|
||||||
fmap = fmap->alternate;
|
fmap = fmap->u.elf.alternate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,18 +199,18 @@ static void elf_end_find(struct elf_file_map* fmap)
|
||||||
*
|
*
|
||||||
* Get the size of an ELF section
|
* Get the size of an ELF section
|
||||||
*/
|
*/
|
||||||
unsigned elf_get_map_size(const struct elf_section_map* esm)
|
unsigned elf_get_map_size(const struct image_section_map* ism)
|
||||||
{
|
{
|
||||||
if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum)
|
if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.elf.elfhdr.e_shnum)
|
||||||
return 0;
|
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 elf_file_map* fmap)
|
static inline void elf_reset_file_map(struct image_file_map* fmap)
|
||||||
{
|
{
|
||||||
fmap->fd = -1;
|
fmap->u.elf.fd = -1;
|
||||||
fmap->shstrtab = IMAGE_NO_MAP;
|
fmap->u.elf.shstrtab = IMAGE_NO_MAP;
|
||||||
fmap->alternate = NULL;
|
fmap->u.elf.alternate = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
|
@ -211,7 +218,7 @@ static inline void elf_reset_file_map(struct elf_file_map* fmap)
|
||||||
*
|
*
|
||||||
* Maps an ELF file into memory (and checks it's a real ELF file)
|
* 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 };
|
static const BYTE elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 };
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
@ -228,52 +235,53 @@ static BOOL elf_map_file(const WCHAR* filenameW, struct elf_file_map* fmap)
|
||||||
|
|
||||||
elf_reset_file_map(fmap);
|
elf_reset_file_map(fmap);
|
||||||
|
|
||||||
|
fmap->modtype = DMT_ELF;
|
||||||
/* check that the file exists, and that the module hasn't been loaded yet */
|
/* 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;
|
if (stat(filename, &statbuf) == -1 || S_ISDIR(statbuf.st_mode)) goto done;
|
||||||
|
|
||||||
/* Now open the file, so that we can mmap() it. */
|
/* Now open the file, so that we can mmap() it. */
|
||||||
if ((fmap->fd = open(filename, O_RDONLY)) == -1) goto done;
|
if ((fmap->u.elf.fd = open(filename, O_RDONLY)) == -1) goto done;
|
||||||
|
|
||||||
if (read(fmap->fd, &fmap->elfhdr, sizeof(fmap->elfhdr)) != sizeof(fmap->elfhdr))
|
if (read(fmap->u.elf.fd, &fmap->u.elf.elfhdr, sizeof(fmap->u.elf.elfhdr)) != sizeof(fmap->u.elf.elfhdr))
|
||||||
goto done;
|
goto done;
|
||||||
/* and check for an ELF header */
|
/* 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;
|
elf_signature, sizeof(elf_signature))) goto done;
|
||||||
/* and check 32 vs 64 size according to current machine */
|
/* and check 32 vs 64 size according to current machine */
|
||||||
#ifdef _WIN64
|
#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
|
#else
|
||||||
if (fmap->elfhdr.e_ident[EI_CLASS] != ELFCLASS32) goto done;
|
if (fmap->u.elf.elfhdr.e_ident[EI_CLASS] != ELFCLASS32) goto done;
|
||||||
#endif
|
#endif
|
||||||
fmap->sect = HeapAlloc(GetProcessHeap(), 0,
|
fmap->u.elf.sect = HeapAlloc(GetProcessHeap(), 0,
|
||||||
fmap->elfhdr.e_shnum * sizeof(fmap->sect[0]));
|
fmap->u.elf.elfhdr.e_shnum * sizeof(fmap->u.elf.sect[0]));
|
||||||
if (!fmap->sect) goto done;
|
if (!fmap->u.elf.sect) goto done;
|
||||||
|
|
||||||
lseek(fmap->fd, fmap->elfhdr.e_shoff, SEEK_SET);
|
lseek(fmap->u.elf.fd, fmap->u.elf.elfhdr.e_shoff, SEEK_SET);
|
||||||
for (i = 0; i < fmap->elfhdr.e_shnum; i++)
|
for (i = 0; i < fmap->u.elf.elfhdr.e_shnum; i++)
|
||||||
{
|
{
|
||||||
read(fmap->fd, &fmap->sect[i].shdr, sizeof(fmap->sect[i].shdr));
|
read(fmap->u.elf.fd, &fmap->u.elf.sect[i].shdr, sizeof(fmap->u.elf.sect[i].shdr));
|
||||||
fmap->sect[i].mapped = IMAGE_NO_MAP;
|
fmap->u.elf.sect[i].mapped = IMAGE_NO_MAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* grab size of module once loaded in memory */
|
/* grab size of module once loaded in memory */
|
||||||
lseek(fmap->fd, fmap->elfhdr.e_phoff, SEEK_SET);
|
lseek(fmap->u.elf.fd, fmap->u.elf.elfhdr.e_phoff, SEEK_SET);
|
||||||
fmap->elf_size = 0;
|
fmap->u.elf.elf_size = 0;
|
||||||
fmap->elf_start = ~0L;
|
fmap->u.elf.elf_start = ~0L;
|
||||||
for (i = 0; i < fmap->elfhdr.e_phnum; i++)
|
for (i = 0; i < fmap->u.elf.elfhdr.e_phnum; i++)
|
||||||
{
|
{
|
||||||
if (read(fmap->fd, &phdr, sizeof(phdr)) == sizeof(phdr) &&
|
if (read(fmap->u.elf.fd, &phdr, sizeof(phdr)) == sizeof(phdr) &&
|
||||||
phdr.p_type == PT_LOAD)
|
phdr.p_type == PT_LOAD)
|
||||||
{
|
{
|
||||||
tmp = (phdr.p_vaddr + phdr.p_memsz + page_mask) & ~page_mask;
|
tmp = (phdr.p_vaddr + phdr.p_memsz + page_mask) & ~page_mask;
|
||||||
if (fmap->elf_size < tmp) fmap->elf_size = tmp;
|
if (fmap->u.elf.elf_size < tmp) fmap->u.elf.elf_size = tmp;
|
||||||
if (phdr.p_vaddr < fmap->elf_start) fmap->elf_start = phdr.p_vaddr;
|
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
|
/* if non relocatable ELF, then remove fixed address from computation
|
||||||
* otherwise, all addresses are zero based and start has no effect
|
* 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;
|
ret = TRUE;
|
||||||
done:
|
done:
|
||||||
HeapFree(GetProcessHeap(), 0, filename);
|
HeapFree(GetProcessHeap(), 0, filename);
|
||||||
|
@ -285,22 +293,22 @@ done:
|
||||||
*
|
*
|
||||||
* Unmaps an ELF file from memory (previously mapped with elf_map_file)
|
* 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)
|
while (fmap)
|
||||||
{
|
{
|
||||||
if (fmap->fd != -1)
|
if (fmap->u.elf.fd != -1)
|
||||||
{
|
{
|
||||||
struct elf_section_map esm;
|
struct image_section_map ism;
|
||||||
esm.fmap = fmap;
|
ism.fmap = fmap;
|
||||||
for (esm.sidx = 0; esm.sidx < fmap->elfhdr.e_shnum; esm.sidx++)
|
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);
|
HeapFree(GetProcessHeap(), 0, fmap->u.elf.sect);
|
||||||
close(fmap->fd);
|
close(fmap->u.elf.fd);
|
||||||
}
|
}
|
||||||
fmap = fmap->alternate;
|
fmap = fmap->u.elf.alternate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +343,7 @@ int elf_is_in_thunk_area(unsigned long addr,
|
||||||
* creating an internal hash table to ease use ELF symtab information lookup
|
* creating an internal hash table to ease use ELF symtab information lookup
|
||||||
*/
|
*/
|
||||||
static void elf_hash_symtab(struct module* module, struct pool* pool,
|
static void elf_hash_symtab(struct module* module, struct pool* pool,
|
||||||
struct hash_table* ht_symtab, struct elf_file_map* fmap,
|
struct hash_table* ht_symtab, struct image_file_map* fmap,
|
||||||
struct elf_thunk_area* thunks)
|
struct elf_thunk_area* thunks)
|
||||||
{
|
{
|
||||||
int i, j, nsym;
|
int i, j, nsym;
|
||||||
|
@ -345,16 +353,20 @@ static void elf_hash_symtab(struct module* module, struct pool* pool,
|
||||||
const char* ptr;
|
const char* ptr;
|
||||||
const Elf_Sym* symp;
|
const Elf_Sym* symp;
|
||||||
struct symtab_elt* ste;
|
struct symtab_elt* ste;
|
||||||
struct elf_section_map esm, esm_str;
|
struct image_section_map ism, ism_str;
|
||||||
|
|
||||||
if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &esm) &&
|
if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &ism) &&
|
||||||
!elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &esm)) return;
|
!elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &ism)) return;
|
||||||
if ((symp = (const Elf_Sym*)elf_map_section(&esm)) == IMAGE_NO_MAP) return;
|
if ((symp = (const Elf_Sym*)image_map_section(&ism)) == IMAGE_NO_MAP) return;
|
||||||
esm_str.fmap = esm.fmap;
|
ism_str.fmap = ism.fmap;
|
||||||
esm_str.sidx = fmap->sect[esm.sidx].shdr.sh_link;
|
ism_str.sidx = fmap->u.elf.sect[ism.sidx].shdr.sh_link;
|
||||||
if ((strp = elf_map_section(&esm_str)) == IMAGE_NO_MAP) return;
|
if ((strp = image_map_section(&ism_str)) == IMAGE_NO_MAP)
|
||||||
|
{
|
||||||
|
image_unmap_section(&ism);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nsym = elf_get_map_size(&esm) / sizeof(*symp);
|
nsym = image_get_map_size(&ism) / sizeof(*symp);
|
||||||
|
|
||||||
for (j = 0; thunks[j].symname; j++)
|
for (j = 0; thunks[j].symname; j++)
|
||||||
thunks[j].rva_start = thunks[j].rva_end = 0;
|
thunks[j].rva_start = thunks[j].rva_end = 0;
|
||||||
|
@ -706,14 +718,14 @@ static int elf_new_public_symbols(struct module* module, const struct hash_table
|
||||||
return TRUE;
|
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;
|
BOOL ret;
|
||||||
if (!elf_map_file(file, fmap)) return FALSE;
|
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",
|
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);
|
elf_unmap_file(fmap);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -738,7 +750,7 @@ static BOOL elf_check_debug_link(const WCHAR* file, struct elf_file_map* fmap, D
|
||||||
* is the global debug file directory, and execdir has been turned
|
* is the global debug file directory, and execdir has been turned
|
||||||
* into a relative path)." (from GDB manual)
|
* 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)
|
const WCHAR* loaded_file, DWORD crc)
|
||||||
{
|
{
|
||||||
static const WCHAR globalDebugDirW[] = {'/','u','s','r','/','l','i','b','/','d','e','b','u','g','/'};
|
static const WCHAR globalDebugDirW[] = {'/','u','s','r','/','l','i','b','/','d','e','b','u','g','/'};
|
||||||
|
@ -747,7 +759,7 @@ static BOOL elf_locate_debug_link(struct elf_file_map* fmap, const char* filenam
|
||||||
size_t filename_len;
|
size_t filename_len;
|
||||||
WCHAR* p = NULL;
|
WCHAR* p = NULL;
|
||||||
WCHAR* slash;
|
WCHAR* slash;
|
||||||
struct elf_file_map* fmap_link = NULL;
|
struct image_file_map* fmap_link = NULL;
|
||||||
|
|
||||||
fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link));
|
fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link));
|
||||||
if (!fmap_link) return FALSE;
|
if (!fmap_link) return FALSE;
|
||||||
|
@ -790,7 +802,7 @@ static BOOL elf_locate_debug_link(struct elf_file_map* fmap, const char* filenam
|
||||||
found:
|
found:
|
||||||
TRACE("Located debug information file %s at %s\n", filename, debugstr_w(p));
|
TRACE("Located debug information file %s at %s\n", filename, debugstr_w(p));
|
||||||
HeapFree(GetProcessHeap(), 0, p);
|
HeapFree(GetProcessHeap(), 0, p);
|
||||||
fmap->alternate = fmap_link;
|
fmap->u.elf.alternate = fmap_link;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,7 +812,7 @@ found:
|
||||||
* Parses a .gnu_debuglink section and loads the debug info from
|
* Parses a .gnu_debuglink section and loads the debug info from
|
||||||
* the external file specified there.
|
* 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)
|
const BYTE* debuglink)
|
||||||
{
|
{
|
||||||
/* The content of a debug link section is:
|
/* The content of a debug link section is:
|
||||||
|
@ -830,7 +842,7 @@ static BOOL elf_debuglink_parse(struct elf_file_map* fmap, const struct module*
|
||||||
* 1 on success
|
* 1 on success
|
||||||
*/
|
*/
|
||||||
static BOOL elf_load_debug_info_from_map(struct module* module,
|
static BOOL elf_load_debug_info_from_map(struct module* module,
|
||||||
struct elf_file_map* fmap,
|
struct image_file_map* fmap,
|
||||||
struct pool* pool,
|
struct pool* pool,
|
||||||
struct hash_table* ht_symtab)
|
struct hash_table* ht_symtab)
|
||||||
{
|
{
|
||||||
|
@ -853,16 +865,16 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
|
||||||
|
|
||||||
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
|
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
|
||||||
{
|
{
|
||||||
struct elf_section_map stab_sect, stabstr_sect;
|
struct image_section_map stab_sect, stabstr_sect;
|
||||||
struct elf_section_map debuglink_sect;
|
struct image_section_map debuglink_sect;
|
||||||
struct elf_section_map debug_sect;
|
struct image_section_map debug_sect;
|
||||||
|
|
||||||
/* if present, add the .gnu_debuglink file as an alternate to current one */
|
/* if present, add the .gnu_debuglink file as an alternate to current one */
|
||||||
if (elf_find_section(fmap, ".gnu_debuglink", SHT_NULL, &debuglink_sect))
|
if (elf_find_section(fmap, ".gnu_debuglink", SHT_NULL, &debuglink_sect))
|
||||||
{
|
{
|
||||||
const BYTE* dbg_link;
|
const BYTE* dbg_link;
|
||||||
|
|
||||||
dbg_link = (const BYTE*)elf_map_section(&debuglink_sect);
|
dbg_link = (const BYTE*)image_map_section(&debuglink_sect);
|
||||||
if (dbg_link != IMAGE_NO_MAP)
|
if (dbg_link != IMAGE_NO_MAP)
|
||||||
{
|
{
|
||||||
lret = elf_debuglink_parse(fmap, module, dbg_link);
|
lret = elf_debuglink_parse(fmap, module, dbg_link);
|
||||||
|
@ -871,7 +883,7 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
|
||||||
debugstr_w(module->module.ModuleName));
|
debugstr_w(module->module.ModuleName));
|
||||||
ret = ret || lret;
|
ret = ret || lret;
|
||||||
}
|
}
|
||||||
elf_unmap_section(&debuglink_sect);
|
image_unmap_section(&debuglink_sect);
|
||||||
}
|
}
|
||||||
if (elf_find_section(fmap, ".stab", SHT_NULL, &stab_sect) &&
|
if (elf_find_section(fmap, ".stab", SHT_NULL, &stab_sect) &&
|
||||||
elf_find_section(fmap, ".stabstr", SHT_NULL, &stabstr_sect))
|
elf_find_section(fmap, ".stabstr", SHT_NULL, &stabstr_sect))
|
||||||
|
@ -879,14 +891,14 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
|
||||||
const char* stab;
|
const char* stab;
|
||||||
const char* stabstr;
|
const char* stabstr;
|
||||||
|
|
||||||
stab = elf_map_section(&stab_sect);
|
stab = image_map_section(&stab_sect);
|
||||||
stabstr = elf_map_section(&stabstr_sect);
|
stabstr = image_map_section(&stabstr_sect);
|
||||||
if (stab != IMAGE_NO_MAP && stabstr != IMAGE_NO_MAP)
|
if (stab != IMAGE_NO_MAP && stabstr != IMAGE_NO_MAP)
|
||||||
{
|
{
|
||||||
/* OK, now just parse all of the stabs. */
|
/* OK, now just parse all of the stabs. */
|
||||||
lret = stabs_parse(module, module->elf_info->elf_addr,
|
lret = stabs_parse(module, module->elf_info->elf_addr,
|
||||||
stab, elf_get_map_size(&stab_sect),
|
stab, image_get_map_size(&stab_sect),
|
||||||
stabstr, elf_get_map_size(&stabstr_sect),
|
stabstr, image_get_map_size(&stabstr_sect),
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
if (lret)
|
if (lret)
|
||||||
/* and fill in the missing information for stabs */
|
/* and fill in the missing information for stabs */
|
||||||
|
@ -896,12 +908,12 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
|
||||||
ret = ret || lret;
|
ret = ret || lret;
|
||||||
}
|
}
|
||||||
else lret = FALSE;
|
else lret = FALSE;
|
||||||
elf_unmap_section(&stab_sect);
|
image_unmap_section(&stab_sect);
|
||||||
elf_unmap_section(&stabstr_sect);
|
image_unmap_section(&stabstr_sect);
|
||||||
}
|
}
|
||||||
if (elf_find_section(fmap, ".debug_info", SHT_NULL, &debug_sect))
|
if (elf_find_section(fmap, ".debug_info", SHT_NULL, &debug_sect))
|
||||||
{
|
{
|
||||||
struct elf_section_map debug_str_sect, debug_abbrev_sect, debug_line_sect, debug_loclist_sect;
|
struct image_section_map debug_str_sect, debug_abbrev_sect, debug_line_sect, debug_loclist_sect;
|
||||||
/* Dwarf 2 debug information */
|
/* Dwarf 2 debug information */
|
||||||
const BYTE* dw2_debug;
|
const BYTE* dw2_debug;
|
||||||
const BYTE* dw2_debug_abbrev;
|
const BYTE* dw2_debug_abbrev;
|
||||||
|
@ -914,7 +926,7 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
|
||||||
* adjust symbol base addresses accordingly
|
* adjust symbol base addresses accordingly
|
||||||
*/
|
*/
|
||||||
unsigned long load_offset = module->elf_info->elf_addr +
|
unsigned long load_offset = module->elf_info->elf_addr +
|
||||||
fmap->elf_start - debug_sect.fmap->elf_start;
|
fmap->u.elf.elf_start - debug_sect.fmap->u.elf.elf_start;
|
||||||
|
|
||||||
TRACE("Loading Dwarf2 information for %s\n", debugstr_w(module->module.ModuleName));
|
TRACE("Loading Dwarf2 information for %s\n", debugstr_w(module->module.ModuleName));
|
||||||
|
|
||||||
|
@ -923,30 +935,30 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
|
||||||
elf_find_section(fmap, ".debug_line", SHT_NULL, &debug_line_sect);
|
elf_find_section(fmap, ".debug_line", SHT_NULL, &debug_line_sect);
|
||||||
elf_find_section(fmap, ".debug_loc", SHT_NULL, &debug_loclist_sect);
|
elf_find_section(fmap, ".debug_loc", SHT_NULL, &debug_loclist_sect);
|
||||||
|
|
||||||
dw2_debug = (const BYTE*)elf_map_section(&debug_sect);
|
dw2_debug = (const BYTE*)image_map_section(&debug_sect);
|
||||||
dw2_debug_abbrev = (const BYTE*)elf_map_section(&debug_abbrev_sect);
|
dw2_debug_abbrev = (const BYTE*)image_map_section(&debug_abbrev_sect);
|
||||||
dw2_debug_str = (const BYTE*)elf_map_section(&debug_str_sect);
|
dw2_debug_str = (const BYTE*)image_map_section(&debug_str_sect);
|
||||||
dw2_debug_line = (const BYTE*)elf_map_section(&debug_line_sect);
|
dw2_debug_line = (const BYTE*)image_map_section(&debug_line_sect);
|
||||||
dw2_debug_loclist = (const BYTE*)elf_map_section(&debug_loclist_sect);
|
dw2_debug_loclist = (const BYTE*)image_map_section(&debug_loclist_sect);
|
||||||
if (dw2_debug != IMAGE_NO_MAP && dw2_debug_abbrev != IMAGE_NO_MAP && dw2_debug_str != IMAGE_NO_MAP)
|
if (dw2_debug != IMAGE_NO_MAP && dw2_debug_abbrev != IMAGE_NO_MAP && dw2_debug_str != IMAGE_NO_MAP)
|
||||||
{
|
{
|
||||||
/* OK, now just parse dwarf2 debug infos. */
|
/* OK, now just parse dwarf2 debug infos. */
|
||||||
lret = dwarf2_parse(module, load_offset, thunks,
|
lret = dwarf2_parse(module, load_offset, thunks,
|
||||||
dw2_debug, elf_get_map_size(&debug_sect),
|
dw2_debug, image_get_map_size(&debug_sect),
|
||||||
dw2_debug_abbrev, elf_get_map_size(&debug_abbrev_sect),
|
dw2_debug_abbrev, image_get_map_size(&debug_abbrev_sect),
|
||||||
dw2_debug_str, elf_get_map_size(&debug_str_sect),
|
dw2_debug_str, image_get_map_size(&debug_str_sect),
|
||||||
dw2_debug_line, elf_get_map_size(&debug_line_sect),
|
dw2_debug_line, image_get_map_size(&debug_line_sect),
|
||||||
dw2_debug_loclist, elf_get_map_size(&debug_loclist_sect));
|
dw2_debug_loclist, image_get_map_size(&debug_loclist_sect));
|
||||||
|
|
||||||
if (!lret)
|
if (!lret)
|
||||||
WARN("Couldn't correctly read dwarf2\n");
|
WARN("Couldn't correctly read dwarf2\n");
|
||||||
ret = ret || lret;
|
ret = ret || lret;
|
||||||
}
|
}
|
||||||
elf_unmap_section(&debug_sect);
|
image_unmap_section(&debug_sect);
|
||||||
elf_unmap_section(&debug_abbrev_sect);
|
image_unmap_section(&debug_abbrev_sect);
|
||||||
elf_unmap_section(&debug_str_sect);
|
image_unmap_section(&debug_str_sect);
|
||||||
elf_unmap_section(&debug_line_sect);
|
image_unmap_section(&debug_line_sect);
|
||||||
elf_unmap_section(&debug_loclist_sect);
|
image_unmap_section(&debug_loclist_sect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (strstrW(module->module.ModuleName, S_ElfW) ||
|
if (strstrW(module->module.ModuleName, S_ElfW) ||
|
||||||
|
@ -967,12 +979,12 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
|
||||||
*
|
*
|
||||||
* Loads ELF debugging information from the module image file.
|
* Loads ELF debugging information from the module image file.
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
{
|
{
|
||||||
BOOL ret = TRUE;
|
BOOL ret = TRUE;
|
||||||
struct pool pool;
|
struct pool pool;
|
||||||
struct hash_table ht_symtab;
|
struct hash_table ht_symtab;
|
||||||
struct elf_file_map my_fmap;
|
struct image_file_map my_fmap;
|
||||||
|
|
||||||
if (module->type != DMT_ELF || !module->elf_info)
|
if (module->type != DMT_ELF || !module->elf_info)
|
||||||
{
|
{
|
||||||
|
@ -1010,12 +1022,12 @@ BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap)
|
||||||
BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base,
|
BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base,
|
||||||
DWORD* size, DWORD* checksum)
|
DWORD* size, DWORD* checksum)
|
||||||
{
|
{
|
||||||
struct elf_file_map fmap;
|
struct image_file_map fmap;
|
||||||
|
|
||||||
if (!elf_map_file(name, &fmap)) return FALSE;
|
if (!elf_map_file(name, &fmap)) return FALSE;
|
||||||
if (base) *base = fmap.elf_start;
|
if (base) *base = fmap.u.elf.elf_start;
|
||||||
*size = fmap.elf_size;
|
*size = fmap.u.elf.elf_size;
|
||||||
*checksum = calc_crc32(fmap.fd);
|
*checksum = calc_crc32(fmap.u.elf.fd);
|
||||||
elf_unmap_file(&fmap);
|
elf_unmap_file(&fmap);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1035,7 +1047,7 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
|
||||||
unsigned long load_offset, struct elf_info* elf_info)
|
unsigned long load_offset, struct elf_info* elf_info)
|
||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
struct elf_file_map fmap;
|
struct image_file_map fmap;
|
||||||
|
|
||||||
TRACE("Processing elf file '%s' at %08lx\n", debugstr_w(filename), load_offset);
|
TRACE("Processing elf file '%s' at %08lx\n", debugstr_w(filename), load_offset);
|
||||||
|
|
||||||
|
@ -1045,10 +1057,10 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
|
||||||
* this thing. We need the main executable header, and the section
|
* this thing. We need the main executable header, and the section
|
||||||
* table.
|
* 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",
|
ERR("Relocatable ELF %s, but no load address. Loading at 0x0000000\n",
|
||||||
debugstr_w(filename));
|
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. "
|
WARN("Non-relocatable ELF %s, but load address of 0x%08lx supplied. "
|
||||||
"Assuming load address is corrupt\n", debugstr_w(filename), load_offset);
|
"Assuming load address is corrupt\n", debugstr_w(filename), load_offset);
|
||||||
|
@ -1057,12 +1069,12 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
|
||||||
|
|
||||||
if (elf_info->flags & ELF_INFO_DEBUG_HEADER)
|
if (elf_info->flags & ELF_INFO_DEBUG_HEADER)
|
||||||
{
|
{
|
||||||
struct elf_section_map esm;
|
struct image_section_map ism;
|
||||||
|
|
||||||
if (elf_find_section(&fmap, ".dynamic", SHT_DYNAMIC, &esm))
|
if (elf_find_section(&fmap, ".dynamic", SHT_DYNAMIC, &ism))
|
||||||
{
|
{
|
||||||
Elf_Dyn dyn;
|
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;
|
unsigned long len;
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -1088,8 +1100,8 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
|
||||||
HeapAlloc(GetProcessHeap(), 0, sizeof(struct elf_module_info));
|
HeapAlloc(GetProcessHeap(), 0, sizeof(struct elf_module_info));
|
||||||
if (!elf_module_info) goto leave;
|
if (!elf_module_info) goto leave;
|
||||||
elf_info->module = module_new(pcs, filename, DMT_ELF, FALSE,
|
elf_info->module = module_new(pcs, filename, DMT_ELF, FALSE,
|
||||||
(load_offset) ? load_offset : fmap.elf_start,
|
(load_offset) ? load_offset : fmap.u.elf.elf_start,
|
||||||
fmap.elf_size, 0, calc_crc32(fmap.fd));
|
fmap.u.elf.elf_size, 0, calc_crc32(fmap.u.elf.fd));
|
||||||
elf_info->module->module_remove = elf_module_remove;
|
elf_info->module->module_remove = elf_module_remove;
|
||||||
if (!elf_info->module)
|
if (!elf_info->module)
|
||||||
{
|
{
|
||||||
|
@ -1477,6 +1489,25 @@ struct module* elf_load_module(struct process* pcs, const WCHAR* name, unsigned
|
||||||
|
|
||||||
#else /* !__ELF__ */
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL elf_synchronize_module_list(struct process* pcs)
|
BOOL elf_synchronize_module_list(struct process* pcs)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -1503,7 +1534,7 @@ struct module* elf_load_module(struct process* pcs, const WCHAR* name, unsigned
|
||||||
return NULL;
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,26 +60,36 @@
|
||||||
#define Elf_Dyn Elf32_Dyn
|
#define Elf_Dyn Elf32_Dyn
|
||||||
#define Elf_Sym Elf32_Sym
|
#define Elf_Sym Elf32_Sym
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
#ifndef SHT_NULL
|
||||||
|
#define SHT_NULL 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* structure holding information while handling an ELF image
|
/* structure holding information while handling an ELF image
|
||||||
* allows one by one section mapping for memory savings
|
* allows one by one section mapping for memory savings
|
||||||
*/
|
*/
|
||||||
|
struct image_file_map
|
||||||
|
{
|
||||||
|
enum module_type modtype;
|
||||||
|
union
|
||||||
|
{
|
||||||
struct elf_file_map
|
struct elf_file_map
|
||||||
{
|
{
|
||||||
size_t elf_size;
|
size_t elf_size;
|
||||||
size_t elf_start;
|
size_t elf_start;
|
||||||
int fd;
|
int fd;
|
||||||
const char* shstrtab;
|
const char* shstrtab;
|
||||||
struct elf_file_map* alternate; /* another ELF file (linked to this one) */
|
struct image_file_map* alternate; /* another ELF file (linked to this one) */
|
||||||
|
#ifdef __ELF__
|
||||||
Elf_Ehdr elfhdr;
|
Elf_Ehdr elfhdr;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
Elf_Shdr shdr;
|
Elf_Shdr shdr;
|
||||||
const char* mapped;
|
const char* mapped;
|
||||||
}* sect;
|
}* sect;
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
|
} elf;
|
||||||
struct pe_file_map
|
struct pe_file_map
|
||||||
{
|
{
|
||||||
HANDLE hMap;
|
HANDLE hMap;
|
||||||
|
@ -92,28 +102,68 @@ struct pe_file_map
|
||||||
const char* mapped;
|
const char* mapped;
|
||||||
}* sect;
|
}* sect;
|
||||||
const char* strtable;
|
const char* strtable;
|
||||||
|
} pe;
|
||||||
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct elf_section_map
|
struct image_section_map
|
||||||
{
|
{
|
||||||
struct elf_file_map* fmap;
|
struct image_file_map* fmap;
|
||||||
long sidx;
|
long sidx;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pe_section_map
|
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 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 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)
|
||||||
{
|
{
|
||||||
struct pe_file_map* fmap;
|
switch (fmap->modtype)
|
||||||
long sidx;
|
{
|
||||||
};
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern BOOL elf_find_section(struct elf_file_map* fmap, const char* name,
|
static inline const char* image_map_section(struct image_section_map* ism)
|
||||||
unsigned sht, struct elf_section_map* esm);
|
{
|
||||||
extern const char* elf_map_section(struct elf_section_map* esm);
|
if (!ism->fmap) return NULL;
|
||||||
extern void elf_unmap_section(struct elf_section_map* esm);
|
switch (ism->fmap->modtype)
|
||||||
extern unsigned elf_get_map_size(const struct elf_section_map* esm);
|
{
|
||||||
|
case DMT_ELF: return elf_map_section(ism);
|
||||||
|
case DMT_PE: return pe_map_section(ism);
|
||||||
|
default: assert(0); return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern BOOL pe_find_section(struct pe_file_map* fmap, const char* name,
|
static inline void image_unmap_section(struct image_section_map* ism)
|
||||||
struct pe_section_map* psm);
|
{
|
||||||
extern const char* pe_map_section(struct pe_section_map* psm);
|
if (!ism->fmap) return;
|
||||||
extern void pe_unmap_section(struct pe_section_map* psm);
|
switch (ism->fmap->modtype)
|
||||||
extern unsigned pe_get_map_size(const struct pe_section_map* psm);
|
{
|
||||||
|
case DMT_ELF: elf_unmap_section(ism); break;
|
||||||
|
case DMT_PE: pe_unmap_section(ism); break;
|
||||||
|
default: assert(0); return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -36,27 +36,27 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
||||||
|
|
||||||
static void* pe_map_full(struct pe_file_map* fmap, IMAGE_NT_HEADERS** nth)
|
static void* pe_map_full(struct image_file_map* fmap, IMAGE_NT_HEADERS** nth)
|
||||||
{
|
{
|
||||||
if (!fmap->full_map)
|
if (!fmap->u.pe.full_map)
|
||||||
{
|
{
|
||||||
fmap->full_map = MapViewOfFile(fmap->hMap, FILE_MAP_READ, 0, 0, 0);
|
fmap->u.pe.full_map = MapViewOfFile(fmap->u.pe.hMap, FILE_MAP_READ, 0, 0, 0);
|
||||||
}
|
}
|
||||||
if (fmap->full_map)
|
if (fmap->u.pe.full_map)
|
||||||
{
|
{
|
||||||
if (nth) *nth = RtlImageNtHeader(fmap->full_map);
|
if (nth) *nth = RtlImageNtHeader(fmap->u.pe.full_map);
|
||||||
fmap->full_count++;
|
fmap->u.pe.full_count++;
|
||||||
return fmap->full_map;
|
return fmap->u.pe.full_map;
|
||||||
}
|
}
|
||||||
return IMAGE_NO_MAP;
|
return IMAGE_NO_MAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pe_unmap_full(struct pe_file_map* fmap)
|
static void pe_unmap_full(struct image_file_map* fmap)
|
||||||
{
|
{
|
||||||
if (fmap->full_count && !--fmap->full_count)
|
if (fmap->u.pe.full_count && !--fmap->u.pe.full_count)
|
||||||
{
|
{
|
||||||
UnmapViewOfFile(fmap->full_map);
|
UnmapViewOfFile(fmap->u.pe.full_map);
|
||||||
fmap->full_map = NULL;
|
fmap->u.pe.full_map = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,24 +65,25 @@ static void pe_unmap_full(struct pe_file_map* fmap)
|
||||||
*
|
*
|
||||||
* Maps a single section into memory from an PE file
|
* Maps a single section into memory from an PE file
|
||||||
*/
|
*/
|
||||||
const char* pe_map_section(struct pe_section_map* psm)
|
const char* pe_map_section(struct image_section_map* ism)
|
||||||
{
|
{
|
||||||
void* mapping;
|
void* mapping;
|
||||||
|
struct pe_file_map* fmap = &ism->fmap->u.pe;
|
||||||
|
|
||||||
if (psm->sidx >= 0 && psm->sidx < psm->fmap->ntheader.FileHeader.NumberOfSections &&
|
if (ism->sidx >= 0 && ism->sidx < fmap->ntheader.FileHeader.NumberOfSections &&
|
||||||
psm->fmap->sect[psm->sidx].mapped == IMAGE_NO_MAP)
|
fmap->sect[ism->sidx].mapped == IMAGE_NO_MAP)
|
||||||
{
|
{
|
||||||
IMAGE_NT_HEADERS* nth;
|
IMAGE_NT_HEADERS* nth;
|
||||||
/* FIXME: that's rather drastic, but that will do for now
|
/* 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
|
* that's ok if the full file map exists, but we could be less agressive otherwise and
|
||||||
* only map the relevant section
|
* only map the relevant section
|
||||||
*/
|
*/
|
||||||
if ((mapping = pe_map_full(psm->fmap, &nth)))
|
if ((mapping = pe_map_full(ism->fmap, &nth)))
|
||||||
{
|
{
|
||||||
psm->fmap->sect[psm->sidx].mapped = RtlImageRvaToVa(nth, mapping,
|
fmap->sect[ism->sidx].mapped = RtlImageRvaToVa(nth, mapping,
|
||||||
psm->fmap->sect[psm->sidx].shdr.VirtualAddress,
|
fmap->sect[ism->sidx].shdr.VirtualAddress,
|
||||||
NULL);
|
NULL);
|
||||||
return psm->fmap->sect[psm->sidx].mapped;
|
return fmap->sect[ism->sidx].mapped;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return IMAGE_NO_MAP;
|
return IMAGE_NO_MAP;
|
||||||
|
@ -94,19 +95,19 @@ const char* pe_map_section(struct pe_section_map* psm)
|
||||||
* Finds a section by name (and type) into memory from an PE file
|
* Finds a section by name (and type) into memory from an PE file
|
||||||
* or its alternate if any
|
* or its alternate if any
|
||||||
*/
|
*/
|
||||||
BOOL pe_find_section(struct pe_file_map* fmap, const char* name,
|
BOOL pe_find_section(struct image_file_map* fmap, const char* name,
|
||||||
struct pe_section_map* psm)
|
struct image_section_map* ism)
|
||||||
{
|
{
|
||||||
const char* sectname;
|
const char* sectname;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
char tmp[IMAGE_SIZEOF_SHORT_NAME + 1];
|
char tmp[IMAGE_SIZEOF_SHORT_NAME + 1];
|
||||||
|
|
||||||
for (i = 0; i < fmap->ntheader.FileHeader.NumberOfSections; i++)
|
for (i = 0; i < fmap->u.pe.ntheader.FileHeader.NumberOfSections; i++)
|
||||||
{
|
{
|
||||||
sectname = (const char*)fmap->sect[i].shdr.Name;
|
sectname = (const char*)fmap->u.pe.sect[i].shdr.Name;
|
||||||
/* long section names start with a '/' (at least on MinGW32) */
|
/* long section names start with a '/' (at least on MinGW32) */
|
||||||
if (sectname[0] == '/' && fmap->strtable)
|
if (sectname[0] == '/' && fmap->u.pe.strtable)
|
||||||
sectname = fmap->strtable + atoi(sectname + 1);
|
sectname = fmap->u.pe.strtable + atoi(sectname + 1);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* the section name may not be null terminated */
|
/* the section name may not be null terminated */
|
||||||
|
@ -115,13 +116,14 @@ BOOL pe_find_section(struct pe_file_map* fmap, const char* name,
|
||||||
}
|
}
|
||||||
if (!strcasecmp(sectname, name))
|
if (!strcasecmp(sectname, name))
|
||||||
{
|
{
|
||||||
psm->fmap = fmap;
|
ism->fmap = fmap;
|
||||||
psm->sidx = i;
|
ism->sidx = i;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
psm->fmap = NULL;
|
ism->fmap = NULL;
|
||||||
psm->sidx = -1;
|
ism->sidx = -1;
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,13 +132,13 @@ BOOL pe_find_section(struct pe_file_map* fmap, const char* name,
|
||||||
*
|
*
|
||||||
* Unmaps a single section from memory
|
* Unmaps a single section from memory
|
||||||
*/
|
*/
|
||||||
void pe_unmap_section(struct pe_section_map* psm)
|
void pe_unmap_section(struct image_section_map* ism)
|
||||||
{
|
{
|
||||||
if (psm->sidx >= 0 && psm->sidx < psm->fmap->ntheader.FileHeader.NumberOfSections &&
|
if (ism->sidx >= 0 && ism->sidx < ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections &&
|
||||||
psm->fmap->sect[psm->sidx].mapped != IMAGE_NO_MAP)
|
ism->fmap->u.pe.sect[ism->sidx].mapped != IMAGE_NO_MAP)
|
||||||
{
|
{
|
||||||
pe_unmap_full(psm->fmap);
|
pe_unmap_full(ism->fmap);
|
||||||
psm->fmap->sect[psm->sidx].mapped = IMAGE_NO_MAP;
|
ism->fmap->u.pe.sect[ism->sidx].mapped = IMAGE_NO_MAP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,11 +147,11 @@ void pe_unmap_section(struct pe_section_map* psm)
|
||||||
*
|
*
|
||||||
* Get the size of an PE section
|
* Get the size of an PE section
|
||||||
*/
|
*/
|
||||||
unsigned pe_get_map_size(const struct pe_section_map* psm)
|
unsigned pe_get_map_size(const struct image_section_map* ism)
|
||||||
{
|
{
|
||||||
if (psm->sidx < 0 || psm->sidx >= psm->fmap->ntheader.FileHeader.NumberOfSections)
|
if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections)
|
||||||
return 0;
|
return 0;
|
||||||
return psm->fmap->sect[psm->sidx].shdr.SizeOfRawData;
|
return ism->fmap->u.pe.sect[ism->sidx].shdr.SizeOfRawData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
|
@ -157,14 +159,15 @@ unsigned pe_get_map_size(const struct pe_section_map* psm)
|
||||||
*
|
*
|
||||||
* Maps an PE file into memory (and checks it's a real PE file)
|
* Maps an PE file into memory (and checks it's a real PE file)
|
||||||
*/
|
*/
|
||||||
static BOOL pe_map_file(HANDLE file, struct pe_file_map* fmap, enum module_type mt)
|
static BOOL pe_map_file(HANDLE file, struct image_file_map* fmap, enum module_type mt)
|
||||||
{
|
{
|
||||||
void* mapping;
|
void* mapping;
|
||||||
|
|
||||||
fmap->hMap = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
|
fmap->modtype = mt;
|
||||||
if (fmap->hMap == 0) return FALSE;
|
fmap->u.pe.hMap = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||||
fmap->full_count = 0;
|
if (fmap->u.pe.hMap == 0) return FALSE;
|
||||||
fmap->full_map = NULL;
|
fmap->u.pe.full_count = 0;
|
||||||
|
fmap->u.pe.full_map = NULL;
|
||||||
if (!(mapping = pe_map_full(fmap, NULL))) goto error;
|
if (!(mapping = pe_map_full(fmap, NULL))) goto error;
|
||||||
|
|
||||||
switch (mt)
|
switch (mt)
|
||||||
|
@ -176,16 +179,16 @@ static BOOL pe_map_file(HANDLE file, struct pe_file_map* fmap, enum module_type
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
if (!(nthdr = RtlImageNtHeader(mapping))) goto error;
|
if (!(nthdr = RtlImageNtHeader(mapping))) goto error;
|
||||||
memcpy(&fmap->ntheader, nthdr, sizeof(fmap->ntheader));
|
memcpy(&fmap->u.pe.ntheader, nthdr, sizeof(fmap->u.pe.ntheader));
|
||||||
section = (IMAGE_SECTION_HEADER*)
|
section = (IMAGE_SECTION_HEADER*)
|
||||||
((char*)&nthdr->OptionalHeader + nthdr->FileHeader.SizeOfOptionalHeader);
|
((char*)&nthdr->OptionalHeader + nthdr->FileHeader.SizeOfOptionalHeader);
|
||||||
fmap->sect = HeapAlloc(GetProcessHeap(), 0,
|
fmap->u.pe.sect = HeapAlloc(GetProcessHeap(), 0,
|
||||||
nthdr->FileHeader.NumberOfSections * sizeof(fmap->sect[0]));
|
nthdr->FileHeader.NumberOfSections * sizeof(fmap->u.pe.sect[0]));
|
||||||
if (!fmap->sect) goto error;
|
if (!fmap->u.pe.sect) goto error;
|
||||||
for (i = 0; i < nthdr->FileHeader.NumberOfSections; i++)
|
for (i = 0; i < nthdr->FileHeader.NumberOfSections; i++)
|
||||||
{
|
{
|
||||||
memcpy(&fmap->sect[i].shdr, section + i, sizeof(IMAGE_SECTION_HEADER));
|
memcpy(&fmap->u.pe.sect[i].shdr, section + i, sizeof(IMAGE_SECTION_HEADER));
|
||||||
fmap->sect[i].mapped = IMAGE_NO_MAP;
|
fmap->u.pe.sect[i].mapped = IMAGE_NO_MAP;
|
||||||
}
|
}
|
||||||
if (nthdr->FileHeader.PointerToSymbolTable && nthdr->FileHeader.NumberOfSymbols)
|
if (nthdr->FileHeader.PointerToSymbolTable && nthdr->FileHeader.NumberOfSymbols)
|
||||||
{
|
{
|
||||||
|
@ -198,9 +201,9 @@ static BOOL pe_map_file(HANDLE file, struct pe_file_map* fmap, enum module_type
|
||||||
|
|
||||||
if ((dst = HeapAlloc(GetProcessHeap(), 0, sz)))
|
if ((dst = HeapAlloc(GetProcessHeap(), 0, sz)))
|
||||||
memcpy(dst, src, sz);
|
memcpy(dst, src, sz);
|
||||||
fmap->strtable = dst;
|
fmap->u.pe.strtable = dst;
|
||||||
}
|
}
|
||||||
else fmap->strtable = NULL;
|
else fmap->u.pe.strtable = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: assert(0); goto error;
|
default: assert(0); goto error;
|
||||||
|
@ -210,7 +213,7 @@ static BOOL pe_map_file(HANDLE file, struct pe_file_map* fmap, enum module_type
|
||||||
return TRUE;
|
return TRUE;
|
||||||
error:
|
error:
|
||||||
pe_unmap_full(fmap);
|
pe_unmap_full(fmap);
|
||||||
CloseHandle(fmap->hMap);
|
CloseHandle(fmap->u.pe.hMap);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,20 +222,20 @@ error:
|
||||||
*
|
*
|
||||||
* Unmaps an PE file from memory (previously mapped with pe_map_file)
|
* Unmaps an PE file from memory (previously mapped with pe_map_file)
|
||||||
*/
|
*/
|
||||||
static void pe_unmap_file(struct pe_file_map* fmap)
|
static void pe_unmap_file(struct image_file_map* fmap)
|
||||||
{
|
{
|
||||||
if (fmap->hMap != 0)
|
if (fmap->u.pe.hMap != 0)
|
||||||
{
|
{
|
||||||
struct pe_section_map psm;
|
struct image_section_map ism;
|
||||||
psm.fmap = fmap;
|
ism.fmap = fmap;
|
||||||
for (psm.sidx = 0; psm.sidx < fmap->ntheader.FileHeader.NumberOfSections; psm.sidx++)
|
for (ism.sidx = 0; ism.sidx < fmap->u.pe.ntheader.FileHeader.NumberOfSections; ism.sidx++)
|
||||||
{
|
{
|
||||||
pe_unmap_section(&psm);
|
pe_unmap_section(&ism);
|
||||||
}
|
}
|
||||||
while (fmap->full_count) pe_unmap_full(fmap);
|
while (fmap->u.pe.full_count) pe_unmap_full(fmap);
|
||||||
HeapFree(GetProcessHeap(), 0, fmap->sect);
|
HeapFree(GetProcessHeap(), 0, fmap->u.pe.sect);
|
||||||
HeapFree(GetProcessHeap(), 0, (void*)fmap->strtable); /* FIXME ugly (see pe_map_file) */
|
HeapFree(GetProcessHeap(), 0, (void*)fmap->u.pe.strtable); /* FIXME ugly (see pe_map_file) */
|
||||||
CloseHandle(fmap->hMap);
|
CloseHandle(fmap->u.pe.hMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +247,7 @@ static void pe_unmap_file(struct pe_file_map* fmap)
|
||||||
* Mingw32 requires this for stabs debug information as address for global variables isn't filled in
|
* 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)
|
* (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, struct pe_file_map* fmap)
|
static BOOL pe_locate_with_coff_symbol_table(struct module* module, struct image_file_map* fmap)
|
||||||
{
|
{
|
||||||
const IMAGE_SYMBOL* isym;
|
const IMAGE_SYMBOL* isym;
|
||||||
int i, numsym, naux;
|
int i, numsym, naux;
|
||||||
|
@ -255,23 +258,23 @@ static BOOL pe_locate_with_coff_symbol_table(struct module* module, struct pe_fi
|
||||||
struct symt_data* sym;
|
struct symt_data* sym;
|
||||||
const char* mapping;
|
const char* mapping;
|
||||||
|
|
||||||
numsym = fmap->ntheader.FileHeader.NumberOfSymbols;
|
numsym = fmap->u.pe.ntheader.FileHeader.NumberOfSymbols;
|
||||||
if (!fmap->ntheader.FileHeader.PointerToSymbolTable || !numsym)
|
if (!fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable || !numsym)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (!(mapping = pe_map_full(fmap, NULL))) return FALSE;
|
if (!(mapping = pe_map_full(fmap, NULL))) return FALSE;
|
||||||
isym = (const IMAGE_SYMBOL*)(mapping + fmap->ntheader.FileHeader.PointerToSymbolTable);
|
isym = (const IMAGE_SYMBOL*)(mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable);
|
||||||
|
|
||||||
for (i = 0; i < numsym; i+= naux, isym += naux)
|
for (i = 0; i < numsym; i+= naux, isym += naux)
|
||||||
{
|
{
|
||||||
if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
|
if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
|
||||||
isym->SectionNumber > 0 && isym->SectionNumber <= fmap->ntheader.FileHeader.NumberOfSections)
|
isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.ntheader.FileHeader.NumberOfSections)
|
||||||
{
|
{
|
||||||
if (isym->N.Name.Short)
|
if (isym->N.Name.Short)
|
||||||
{
|
{
|
||||||
name = memcpy(tmp, isym->N.ShortName, 8);
|
name = memcpy(tmp, isym->N.ShortName, 8);
|
||||||
tmp[8] = '\0';
|
tmp[8] = '\0';
|
||||||
}
|
}
|
||||||
else name = fmap->strtable + isym->N.Name.Long;
|
else name = fmap->u.pe.strtable + isym->N.Name.Long;
|
||||||
if (name[0] == '_') name++;
|
if (name[0] == '_') name++;
|
||||||
hash_table_iter_init(&module->ht_symbols, &hti, name);
|
hash_table_iter_init(&module->ht_symbols, &hti, name);
|
||||||
while ((ptr = hash_table_iter_up(&hti)))
|
while ((ptr = hash_table_iter_up(&hti)))
|
||||||
|
@ -284,10 +287,10 @@ static BOOL pe_locate_with_coff_symbol_table(struct module* module, struct pe_fi
|
||||||
TRACE("Changing absolute address for %d.%s: %lx -> %s\n",
|
TRACE("Changing absolute address for %d.%s: %lx -> %s\n",
|
||||||
isym->SectionNumber, name, sym->u.var.offset,
|
isym->SectionNumber, name, sym->u.var.offset,
|
||||||
wine_dbgstr_longlong(module->module.BaseOfImage +
|
wine_dbgstr_longlong(module->module.BaseOfImage +
|
||||||
fmap->sect[isym->SectionNumber - 1].shdr.VirtualAddress +
|
fmap->u.pe.sect[isym->SectionNumber - 1].shdr.VirtualAddress +
|
||||||
isym->Value));
|
isym->Value));
|
||||||
sym->u.var.offset = module->module.BaseOfImage +
|
sym->u.var.offset = module->module.BaseOfImage +
|
||||||
fmap->sect[isym->SectionNumber - 1].shdr.VirtualAddress + isym->Value;
|
fmap->u.pe.sect[isym->SectionNumber - 1].shdr.VirtualAddress + isym->Value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,7 +306,7 @@ static BOOL pe_locate_with_coff_symbol_table(struct module* module, struct pe_fi
|
||||||
*
|
*
|
||||||
* Load public symbols out of the COFF symbol table (if any).
|
* Load public symbols out of the COFF symbol table (if any).
|
||||||
*/
|
*/
|
||||||
static BOOL pe_load_coff_symbol_table(struct module* module, struct pe_file_map* fmap)
|
static BOOL pe_load_coff_symbol_table(struct module* module, struct image_file_map* fmap)
|
||||||
{
|
{
|
||||||
const IMAGE_SYMBOL* isym;
|
const IMAGE_SYMBOL* isym;
|
||||||
int i, numsym, naux;
|
int i, numsym, naux;
|
||||||
|
@ -315,14 +318,14 @@ static BOOL pe_load_coff_symbol_table(struct module* module, struct pe_file_map*
|
||||||
const IMAGE_SECTION_HEADER* sect;
|
const IMAGE_SECTION_HEADER* sect;
|
||||||
const char* mapping;
|
const char* mapping;
|
||||||
|
|
||||||
numsym = fmap->ntheader.FileHeader.NumberOfSymbols;
|
numsym = fmap->u.pe.ntheader.FileHeader.NumberOfSymbols;
|
||||||
if (!fmap->ntheader.FileHeader.PointerToSymbolTable || !numsym)
|
if (!fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable || !numsym)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (!(mapping = pe_map_full(fmap, NULL))) return FALSE;
|
if (!(mapping = pe_map_full(fmap, NULL))) return FALSE;
|
||||||
isym = (const IMAGE_SYMBOL*)((char*)mapping + fmap->ntheader.FileHeader.PointerToSymbolTable);
|
isym = (const IMAGE_SYMBOL*)((char*)mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable);
|
||||||
/* FIXME: no way to get strtable size */
|
/* FIXME: no way to get strtable size */
|
||||||
strtable = (const char*)&isym[numsym];
|
strtable = (const char*)&isym[numsym];
|
||||||
sect = IMAGE_FIRST_SECTION(&fmap->ntheader);
|
sect = IMAGE_FIRST_SECTION(&fmap->u.pe.ntheader);
|
||||||
|
|
||||||
for (i = 0; i < numsym; i+= naux, isym += naux)
|
for (i = 0; i < numsym; i+= naux, isym += naux)
|
||||||
{
|
{
|
||||||
|
@ -332,7 +335,7 @@ static BOOL pe_load_coff_symbol_table(struct module* module, struct pe_file_map*
|
||||||
compiland = NULL;
|
compiland = NULL;
|
||||||
}
|
}
|
||||||
if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
|
if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
|
||||||
isym->SectionNumber > 0 && isym->SectionNumber <= fmap->ntheader.FileHeader.NumberOfSections)
|
isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.ntheader.FileHeader.NumberOfSections)
|
||||||
{
|
{
|
||||||
if (isym->N.Name.Short)
|
if (isym->N.Name.Short)
|
||||||
{
|
{
|
||||||
|
@ -379,9 +382,9 @@ static inline DWORD pe_get_sect_size(IMAGE_SECTION_HEADER* sect)
|
||||||
* look for stabs information in PE header (it's how the mingw compiler provides
|
* look for stabs information in PE header (it's how the mingw compiler provides
|
||||||
* its debugging information)
|
* its debugging information)
|
||||||
*/
|
*/
|
||||||
static BOOL pe_load_stabs(const struct process* pcs, struct module* module, struct pe_file_map* fmap)
|
static BOOL pe_load_stabs(const struct process* pcs, struct module* module, struct image_file_map* fmap)
|
||||||
{
|
{
|
||||||
struct pe_section_map sect_stabs, sect_stabstr;
|
struct image_section_map sect_stabs, sect_stabstr;
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
if (pe_find_section(fmap, ".stab", §_stabs) && pe_find_section(fmap, ".stabstr", §_stabstr))
|
if (pe_find_section(fmap, ".stab", §_stabs) && pe_find_section(fmap, ".stabstr", §_stabstr))
|
||||||
|
@ -389,18 +392,18 @@ static BOOL pe_load_stabs(const struct process* pcs, struct module* module, stru
|
||||||
const char* stab;
|
const char* stab;
|
||||||
const char* stabstr;
|
const char* stabstr;
|
||||||
|
|
||||||
stab = pe_map_section(§_stabs);
|
stab = image_map_section(§_stabs);
|
||||||
stabstr = pe_map_section(§_stabstr);
|
stabstr = image_map_section(§_stabstr);
|
||||||
if (stab != IMAGE_NO_MAP && stabstr != IMAGE_NO_MAP)
|
if (stab != IMAGE_NO_MAP && stabstr != IMAGE_NO_MAP)
|
||||||
{
|
{
|
||||||
ret = stabs_parse(module,
|
ret = stabs_parse(module,
|
||||||
module->module.BaseOfImage - fmap->ntheader.OptionalHeader.ImageBase,
|
module->module.BaseOfImage - fmap->u.pe.ntheader.OptionalHeader.ImageBase,
|
||||||
stab, pe_get_map_size(§_stabs),
|
stab, image_get_map_size(§_stabs),
|
||||||
stabstr, pe_get_map_size(§_stabstr),
|
stabstr, image_get_map_size(§_stabstr),
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
pe_unmap_section(§_stabs);
|
image_unmap_section(§_stabs);
|
||||||
pe_unmap_section(§_stabstr);
|
image_unmap_section(§_stabstr);
|
||||||
if (ret) pe_locate_with_coff_symbol_table(module, fmap);
|
if (ret) pe_locate_with_coff_symbol_table(module, fmap);
|
||||||
}
|
}
|
||||||
TRACE("%s the STABS debug info\n", ret ? "successfully loaded" : "failed to load");
|
TRACE("%s the STABS debug info\n", ret ? "successfully loaded" : "failed to load");
|
||||||
|
@ -415,9 +418,9 @@ static BOOL pe_load_stabs(const struct process* pcs, struct module* module, stru
|
||||||
* to provide its debugging information)
|
* to provide its debugging information)
|
||||||
*/
|
*/
|
||||||
static BOOL pe_load_dwarf(const struct process* pcs, struct module* module,
|
static BOOL pe_load_dwarf(const struct process* pcs, struct module* module,
|
||||||
struct pe_file_map* fmap)
|
struct image_file_map* fmap)
|
||||||
{
|
{
|
||||||
struct pe_section_map sect_debuginfo, sect_debugstr, sect_debugabbrev, sect_debugline, sect_debugloc;
|
struct image_section_map sect_debuginfo, sect_debugstr, sect_debugabbrev, sect_debugline, sect_debugloc;
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
if (pe_find_section(fmap, ".debug_info", §_debuginfo))
|
if (pe_find_section(fmap, ".debug_info", §_debuginfo))
|
||||||
|
@ -433,28 +436,28 @@ static BOOL pe_load_dwarf(const struct process* pcs, struct module* module,
|
||||||
pe_find_section(fmap, ".debug_line", §_debugline);
|
pe_find_section(fmap, ".debug_line", §_debugline);
|
||||||
pe_find_section(fmap, ".debug_loc", §_debugloc);
|
pe_find_section(fmap, ".debug_loc", §_debugloc);
|
||||||
|
|
||||||
dw2_debuginfo = (const BYTE*)pe_map_section(§_debuginfo);
|
dw2_debuginfo = (const BYTE*)image_map_section(§_debuginfo);
|
||||||
dw2_debugabbrev = (const BYTE*)pe_map_section(§_debugabbrev);
|
dw2_debugabbrev = (const BYTE*)image_map_section(§_debugabbrev);
|
||||||
dw2_debugstr = (const BYTE*)pe_map_section(§_debugstr);
|
dw2_debugstr = (const BYTE*)image_map_section(§_debugstr);
|
||||||
dw2_debugline = (const BYTE*)pe_map_section(§_debugline);
|
dw2_debugline = (const BYTE*)image_map_section(§_debugline);
|
||||||
dw2_debugloc = (const BYTE*)pe_map_section(§_debugloc);
|
dw2_debugloc = (const BYTE*)image_map_section(§_debugloc);
|
||||||
|
|
||||||
if (dw2_debuginfo != IMAGE_NO_MAP && dw2_debugabbrev != IMAGE_NO_MAP && dw2_debugstr != IMAGE_NO_MAP)
|
if (dw2_debuginfo != IMAGE_NO_MAP && dw2_debugabbrev != IMAGE_NO_MAP && dw2_debugstr != IMAGE_NO_MAP)
|
||||||
{
|
{
|
||||||
ret = dwarf2_parse(module,
|
ret = dwarf2_parse(module,
|
||||||
module->module.BaseOfImage - fmap->ntheader.OptionalHeader.ImageBase,
|
module->module.BaseOfImage - fmap->u.pe.ntheader.OptionalHeader.ImageBase,
|
||||||
NULL, /* FIXME: some thunks to deal with ? */
|
NULL, /* FIXME: some thunks to deal with ? */
|
||||||
dw2_debuginfo, pe_get_map_size(§_debuginfo),
|
dw2_debuginfo, image_get_map_size(§_debuginfo),
|
||||||
dw2_debugabbrev, pe_get_map_size(§_debugabbrev),
|
dw2_debugabbrev, image_get_map_size(§_debugabbrev),
|
||||||
dw2_debugstr, pe_get_map_size(§_debugstr),
|
dw2_debugstr, image_get_map_size(§_debugstr),
|
||||||
dw2_debugline, pe_get_map_size(§_debugline),
|
dw2_debugline, image_get_map_size(§_debugline),
|
||||||
dw2_debugloc, pe_get_map_size(§_debugloc));
|
dw2_debugloc, image_get_map_size(§_debugloc));
|
||||||
}
|
}
|
||||||
pe_unmap_section(§_debuginfo);
|
image_unmap_section(§_debuginfo);
|
||||||
pe_unmap_section(§_debugabbrev);
|
image_unmap_section(§_debugabbrev);
|
||||||
pe_unmap_section(§_debugstr);
|
image_unmap_section(§_debugstr);
|
||||||
pe_unmap_section(§_debugline);
|
image_unmap_section(§_debugline);
|
||||||
pe_unmap_section(§_debugloc);
|
image_unmap_section(§_debugloc);
|
||||||
}
|
}
|
||||||
TRACE("%s the DWARF debug info\n", ret ? "successfully loaded" : "failed to load");
|
TRACE("%s the DWARF debug info\n", ret ? "successfully loaded" : "failed to load");
|
||||||
|
|
||||||
|
@ -513,7 +516,7 @@ static BOOL pe_load_dbg_file(const struct process* pcs, struct module* module,
|
||||||
*
|
*
|
||||||
* Process MSC debug information in PE file.
|
* Process MSC debug information in PE file.
|
||||||
*/
|
*/
|
||||||
static BOOL pe_load_msc_debug_info(const struct process* pcs, struct module* module, struct pe_file_map* fmap)
|
static BOOL pe_load_msc_debug_info(const struct process* pcs, struct module* module, struct image_file_map* fmap)
|
||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
const IMAGE_DATA_DIRECTORY* dir;
|
const IMAGE_DATA_DIRECTORY* dir;
|
||||||
|
@ -563,7 +566,7 @@ done:
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* pe_load_export_debug_info
|
* pe_load_export_debug_info
|
||||||
*/
|
*/
|
||||||
static BOOL pe_load_export_debug_info(const struct process* pcs, struct module* module, struct pe_file_map* fmap)
|
static BOOL pe_load_export_debug_info(const struct process* pcs, struct module* module, struct image_file_map* fmap)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
const IMAGE_EXPORT_DIRECTORY* exports;
|
const IMAGE_EXPORT_DIRECTORY* exports;
|
||||||
|
@ -647,7 +650,7 @@ static BOOL pe_load_export_debug_info(const struct process* pcs, struct module*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
BOOL pe_load_debug_info_internal(const struct process* pcs, struct module* module,
|
BOOL pe_load_debug_info_internal(const struct process* pcs, struct module* module,
|
||||||
struct pe_file_map* fmap)
|
struct image_file_map* fmap)
|
||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
|
@ -673,7 +676,7 @@ BOOL pe_load_debug_info(const struct process* pcs, struct module* module)
|
||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
HANDLE hFile;
|
HANDLE hFile;
|
||||||
struct pe_file_map fmap;
|
struct image_file_map fmap;
|
||||||
|
|
||||||
hFile = CreateFileW(module->module.LoadedImageName, GENERIC_READ, FILE_SHARE_READ,
|
hFile = CreateFileW(module->module.LoadedImageName, GENERIC_READ, FILE_SHARE_READ,
|
||||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
@ -697,7 +700,7 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name,
|
||||||
{
|
{
|
||||||
struct module* module = NULL;
|
struct module* module = NULL;
|
||||||
BOOL opened = FALSE;
|
BOOL opened = FALSE;
|
||||||
struct pe_file_map fmap;
|
struct image_file_map fmap;
|
||||||
WCHAR loaded_name[MAX_PATH];
|
WCHAR loaded_name[MAX_PATH];
|
||||||
|
|
||||||
loaded_name[0] = '\0';
|
loaded_name[0] = '\0';
|
||||||
|
@ -715,12 +718,12 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name,
|
||||||
|
|
||||||
if (pe_map_file(hFile, &fmap, DMT_PE))
|
if (pe_map_file(hFile, &fmap, DMT_PE))
|
||||||
{
|
{
|
||||||
if (!base) base = fmap.ntheader.OptionalHeader.ImageBase;
|
if (!base) base = fmap.u.pe.ntheader.OptionalHeader.ImageBase;
|
||||||
if (!size) size = fmap.ntheader.OptionalHeader.SizeOfImage;
|
if (!size) size = fmap.u.pe.ntheader.OptionalHeader.SizeOfImage;
|
||||||
|
|
||||||
module = module_new(pcs, loaded_name, DMT_PE, FALSE, base, size,
|
module = module_new(pcs, loaded_name, DMT_PE, FALSE, base, size,
|
||||||
fmap.ntheader.FileHeader.TimeDateStamp,
|
fmap.u.pe.ntheader.FileHeader.TimeDateStamp,
|
||||||
fmap.ntheader.OptionalHeader.CheckSum);
|
fmap.u.pe.ntheader.OptionalHeader.CheckSum);
|
||||||
if (module)
|
if (module)
|
||||||
{
|
{
|
||||||
if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
|
if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
|
||||||
|
|
Loading…
Reference in New Issue