dbghelp: Make the ELF mapping code easier to use.

This commit is contained in:
Eric Pouech 2010-03-18 21:30:47 +01:00 committed by Alexandre Julliard
parent 6e4873691c
commit 770f0d834f
4 changed files with 130 additions and 93 deletions

View File

@ -472,7 +472,6 @@ extern DWORD calc_crc32(int fd);
typedef BOOL (*enum_modules_cb)(const WCHAR*, unsigned long addr, void* user); typedef BOOL (*enum_modules_cb)(const WCHAR*, unsigned long addr, void* user);
/* elf_module.c */ /* elf_module.c */
#define ELF_NO_MAP ((const void*)-1)
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 elf_file_map;

View File

@ -51,6 +51,7 @@
#include "oleauto.h" #include "oleauto.h"
#include "dbghelp_private.h" #include "dbghelp_private.h"
#include "image_private.h"
#include "wine/debug.h" #include "wine/debug.h"
@ -1951,7 +1952,7 @@ static BOOL dwarf2_parse_line_numbers(const dwarf2_section_t* sections,
const char** p; const char** p;
/* section with line numbers stripped */ /* section with line numbers stripped */
if (sections[section_line].address == ELF_NO_MAP) if (sections[section_line].address == IMAGE_NO_MAP)
return FALSE; return FALSE;
traverse.data = sections[section_line].address + offset; traverse.data = sections[section_line].address + offset;

View File

@ -48,29 +48,7 @@
#include "dbghelp_private.h" #include "dbghelp_private.h"
#ifdef HAVE_ELF_H #include "image_private.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 "wine/library.h" #include "wine/library.h"
#include "wine/debug.h" #include "wine/debug.h"
@ -91,44 +69,6 @@ struct elf_info
const WCHAR* module_name; /* OUT found module name (if ELF_INFO_NAME is set) */ 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 symtab_elt
{ {
struct hash_table_elt ht_elt; struct hash_table_elt ht_elt;
@ -158,14 +98,14 @@ struct elf_module_info
* *
* Maps a single section into memory from an ELF file * 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 elf_section_map* esm)
{ {
unsigned pgsz = getpagesize(); unsigned pgsz = getpagesize();
unsigned ofst, size; unsigned ofst, size;
if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum || if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum ||
esm->fmap->sect[esm->sidx].shdr.sh_type == SHT_NOBITS) esm->fmap->sect[esm->sidx].shdr.sh_type == SHT_NOBITS)
return ELF_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 = esm->fmap->sect[esm->sidx].shdr.sh_offset & ~(pgsz - 1);
@ -173,7 +113,7 @@ static const char* elf_map_section(struct elf_section_map* esm)
esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst; 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->sect[esm->sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE,
esm->fmap->fd, ofst); esm->fmap->fd, ofst);
if (esm->fmap->sect[esm->sidx].mapped == ELF_NO_MAP) return ELF_NO_MAP; if (esm->fmap->sect[esm->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 esm->fmap->sect[esm->sidx].mapped + (esm->fmap->sect[esm->sidx].shdr.sh_offset & (pgsz - 1));
} }
@ -183,17 +123,17 @@ static 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
*/ */
static BOOL elf_find_section(struct elf_file_map* fmap, const char* name, BOOL elf_find_section(struct elf_file_map* fmap, const char* name,
unsigned sht, struct elf_section_map* esm) unsigned sht, struct elf_section_map* esm)
{ {
unsigned i; unsigned i;
while (fmap) while (fmap)
{ {
if (fmap->shstrtab == ELF_NO_MAP) if (fmap->shstrtab == IMAGE_NO_MAP)
{ {
struct elf_section_map hdr_esm = {fmap, fmap->elfhdr.e_shstrndx}; struct elf_section_map hdr_esm = {fmap, fmap->elfhdr.e_shstrndx};
if ((fmap->shstrtab = elf_map_section(&hdr_esm)) == ELF_NO_MAP) break; if ((fmap->shstrtab = elf_map_section(&hdr_esm)) == IMAGE_NO_MAP) break;
} }
for (i = 0; i < fmap->elfhdr.e_shnum; i++) for (i = 0; i < fmap->elfhdr.e_shnum; i++)
{ {
@ -217,9 +157,9 @@ static BOOL elf_find_section(struct elf_file_map* fmap, const char* name,
* *
* Unmaps a single section from memory * Unmaps a single section from memory
*/ */
static void elf_unmap_section(struct elf_section_map* esm) 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) if (esm->sidx >= 0 && esm->sidx < esm->fmap->elfhdr.e_shnum && esm->fmap->sect[esm->sidx].mapped != IMAGE_NO_MAP)
{ {
unsigned pgsz = getpagesize(); unsigned pgsz = getpagesize();
unsigned ofst, size; unsigned ofst, size;
@ -229,7 +169,7 @@ static void elf_unmap_section(struct elf_section_map* esm)
esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst; esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst;
if (munmap((char*)esm->fmap->sect[esm->sidx].mapped, size) < 0) if (munmap((char*)esm->fmap->sect[esm->sidx].mapped, size) < 0)
WARN("Couldn't unmap the section\n"); WARN("Couldn't unmap the section\n");
esm->fmap->sect[esm->sidx].mapped = ELF_NO_MAP; esm->fmap->sect[esm->sidx].mapped = IMAGE_NO_MAP;
} }
} }
@ -242,7 +182,7 @@ static void elf_end_find(struct elf_file_map* fmap)
esm.fmap = fmap; esm.fmap = fmap;
esm.sidx = fmap->elfhdr.e_shstrndx; esm.sidx = fmap->elfhdr.e_shstrndx;
elf_unmap_section(&esm); elf_unmap_section(&esm);
fmap->shstrtab = ELF_NO_MAP; fmap->shstrtab = IMAGE_NO_MAP;
fmap = fmap->alternate; fmap = fmap->alternate;
} }
} }
@ -252,7 +192,7 @@ static void elf_end_find(struct elf_file_map* fmap)
* *
* Get the size of an ELF section * Get the size of an ELF section
*/ */
static inline unsigned elf_get_map_size(const struct elf_section_map* esm) unsigned elf_get_map_size(const struct elf_section_map* esm)
{ {
if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum) if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum)
return 0; return 0;
@ -262,7 +202,7 @@ static inline unsigned elf_get_map_size(const struct elf_section_map* esm)
static inline void elf_reset_file_map(struct elf_file_map* fmap) static inline void elf_reset_file_map(struct elf_file_map* fmap)
{ {
fmap->fd = -1; fmap->fd = -1;
fmap->shstrtab = ELF_NO_MAP; fmap->shstrtab = IMAGE_NO_MAP;
fmap->alternate = NULL; fmap->alternate = NULL;
} }
@ -313,7 +253,7 @@ static BOOL elf_map_file(const WCHAR* filenameW, struct elf_file_map* fmap)
for (i = 0; i < fmap->elfhdr.e_shnum; i++) for (i = 0; i < fmap->elfhdr.e_shnum; i++)
{ {
read(fmap->fd, &fmap->sect[i].shdr, sizeof(fmap->sect[i].shdr)); read(fmap->fd, &fmap->sect[i].shdr, sizeof(fmap->sect[i].shdr));
fmap->sect[i].mapped = ELF_NO_MAP; fmap->sect[i].mapped = IMAGE_NO_MAP;
} }
/* grab size of module once loaded in memory */ /* grab size of module once loaded in memory */
@ -366,6 +306,7 @@ static void elf_unmap_file(struct elf_file_map* fmap)
static void elf_module_remove(struct process* pcs, struct module* module) static void elf_module_remove(struct process* pcs, struct module* module)
{ {
elf_unmap_file(&module->elf_info->file_map);
HeapFree(GetProcessHeap(), 0, module->elf_info); HeapFree(GetProcessHeap(), 0, module->elf_info);
} }
@ -408,10 +349,10 @@ static void elf_hash_symtab(struct module* module, struct pool* pool,
if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &esm) && if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &esm) &&
!elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &esm)) return; !elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &esm)) return;
if ((symp = (const Elf_Sym*)elf_map_section(&esm)) == ELF_NO_MAP) return; if ((symp = (const Elf_Sym*)elf_map_section(&esm)) == IMAGE_NO_MAP) return;
esm_str.fmap = fmap; esm_str.fmap = esm.fmap;
esm_str.sidx = fmap->sect[esm.sidx].shdr.sh_link; esm_str.sidx = fmap->sect[esm.sidx].shdr.sh_link;
if ((strp = elf_map_section(&esm_str)) == ELF_NO_MAP) return; if ((strp = elf_map_section(&esm_str)) == IMAGE_NO_MAP) return;
nsym = elf_get_map_size(&esm) / sizeof(*symp); nsym = elf_get_map_size(&esm) / sizeof(*symp);
@ -912,10 +853,9 @@ 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 elf_section_map stab_sect, stabstr_sect;
struct elf_section_map debug_sect, debug_str_sect, debug_abbrev_sect, struct elf_section_map debuglink_sect;
debug_line_sect, debug_loclist_sect; struct elf_section_map debug_sect;
struct elf_section_map debuglink_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))
@ -923,7 +863,7 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
const BYTE* dbg_link; const BYTE* dbg_link;
dbg_link = (const BYTE*)elf_map_section(&debuglink_sect); dbg_link = (const BYTE*)elf_map_section(&debuglink_sect);
if (dbg_link != ELF_NO_MAP) if (dbg_link != IMAGE_NO_MAP)
{ {
lret = elf_debuglink_parse(fmap, module, dbg_link); lret = elf_debuglink_parse(fmap, module, dbg_link);
if (!lret) if (!lret)
@ -941,7 +881,7 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
stab = elf_map_section(&stab_sect); stab = elf_map_section(&stab_sect);
stabstr = elf_map_section(&stabstr_sect); stabstr = elf_map_section(&stabstr_sect);
if (stab != ELF_NO_MAP && stabstr != ELF_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,
@ -959,8 +899,9 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
elf_unmap_section(&stab_sect); elf_unmap_section(&stab_sect);
elf_unmap_section(&stabstr_sect); elf_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;
/* 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;
@ -973,21 +914,21 @@ 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->elf_start - debug_sect.fmap->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));
elf_find_section(fmap, ".debug_str", SHT_NULL, &debug_str_sect); elf_find_section(fmap, ".debug_str", SHT_NULL, &debug_str_sect);
elf_find_section(fmap, ".debug_abbrev", SHT_NULL, &debug_abbrev_sect); elf_find_section(fmap, ".debug_abbrev", SHT_NULL, &debug_abbrev_sect);
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*)elf_map_section(&debug_sect);
dw2_debug_abbrev = (const BYTE*)elf_map_section(&debug_abbrev_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_str = (const BYTE*)elf_map_section(&debug_str_sect);
dw2_debug_line = (const BYTE*)elf_map_section(&debug_line_sect); dw2_debug_line = (const BYTE*)elf_map_section(&debug_line_sect);
dw2_debug_loclist = (const BYTE*)elf_map_section(&debug_loclist_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) 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,
@ -1161,6 +1102,8 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
if (dbghelp_options & SYMOPT_DEFERRED_LOADS) if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
{ {
elf_info->module->module.SymType = SymDeferred; elf_info->module->module.SymType = SymDeferred;
elf_info->module->elf_info->file_map = fmap;
elf_reset_file_map(&fmap);
ret = TRUE; ret = TRUE;
} }
else ret = elf_load_debug_info(elf_info->module, &fmap); else ret = elf_load_debug_info(elf_info->module, &fmap);

View File

@ -0,0 +1,94 @@
/*
* 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
/* structure holding information while handling an ELF image
* allows one by one section mapping for memory savings
*/
struct elf_file_map
{
size_t elf_size;
size_t elf_start;
int fd;
const char* shstrtab;
struct elf_file_map* alternate; /* another ELF file (linked to this one) */
Elf_Ehdr elfhdr;
struct
{
Elf_Shdr shdr;
const char* mapped;
}* sect;
};
struct elf_section_map
{
struct elf_file_map* fmap;
long sidx;
};
extern BOOL elf_find_section(struct elf_file_map* fmap, const char* name,
unsigned sht, struct elf_section_map* esm);
extern const char* elf_map_section(struct elf_section_map* esm);
extern void elf_unmap_section(struct elf_section_map* esm);
extern unsigned elf_get_map_size(const struct elf_section_map* esm);
#endif