Eliminate more BinParser stuff

This commit is contained in:
Søren Sandmann Pedersen
2009-10-08 19:17:24 -04:00
parent 4f9903b913
commit ca14021fb3

View File

@ -26,6 +26,7 @@ typedef struct Section Section;
struct ElfSym struct ElfSym
{ {
gulong table;
gulong offset; gulong offset;
gulong address; gulong address;
}; };
@ -75,13 +76,27 @@ static gboolean parse_elf_signature (const guchar *data, gsize length,
gboolean *is_64, gboolean *is_be); gboolean *is_64, gboolean *is_be);
static void make_formats (ElfParser *parser, gboolean is_64); static void make_formats (ElfParser *parser, gboolean is_64);
/* FIXME: All of these should in principle do endian swapping,
* but sysprof never has to deal with binaries of a different
* endianness than sysprof itself
*/
#define GET_FIELD(parser, offset, struct_name, idx, field_name) \
(((parser))->is_64? \
((Elf64_ ## struct_name *)(((parser)->data + offset)) + (idx))->field_name : \
((Elf32_ ## struct_name *)(((parser)->data + offset)) + (idx))->field_name)
#define GET_UINT32(parser, offset) \
*((uint32_t *)(parser->data + offset)) \
#define GET_SIZE(parser, struct_name) \
(((parser)->is_64? \
sizeof (Elf64_ ## struct_name) : \
sizeof (Elf32_ ## struct_name)))
#define MAKE_ELF_UINT_ACCESSOR(field_name) \ #define MAKE_ELF_UINT_ACCESSOR(field_name) \
static uint64_t field_name (ElfParser *parser) \ static uint64_t field_name (ElfParser *parser) \
{ \ { \
if (parser->is_64) \ return GET_FIELD (parser, 0, Ehdr, 0, field_name); \
return ((Elf64_Ehdr *)parser->data)->field_name; \
else \
return ((Elf32_Ehdr *)parser->data)->field_name; \
} }
MAKE_ELF_UINT_ACCESSOR (e_type) MAKE_ELF_UINT_ACCESSOR (e_type)
@ -101,11 +116,9 @@ MAKE_ELF_UINT_ACCESSOR (e_shstrndx)
#define MAKE_SECTION_HEADER_ACCESSOR(field_name) \ #define MAKE_SECTION_HEADER_ACCESSOR(field_name) \
static uint64_t field_name (ElfParser *parser, int nth_section) \ static uint64_t field_name (ElfParser *parser, int nth_section) \
{ \ { \
const char *data = parser->data + e_shoff (parser); \ gsize offset = e_shoff (parser); \
if (parser->is_64) \ \
return (((Elf64_Shdr *)data) + nth_section)->field_name; \ return GET_FIELD (parser, offset, Shdr, nth_section, field_name); \
else \
return (((Elf32_Shdr *)data) + nth_section)->field_name; \
} }
MAKE_SECTION_HEADER_ACCESSOR (sh_name); MAKE_SECTION_HEADER_ACCESSOR (sh_name);
@ -120,39 +133,17 @@ MAKE_SECTION_HEADER_ACCESSOR (sh_addralign);
MAKE_SECTION_HEADER_ACCESSOR (sh_entsize); MAKE_SECTION_HEADER_ACCESSOR (sh_entsize);
#define MAKE_SYMBOL_ACCESSOR(field_name) \ #define MAKE_SYMBOL_ACCESSOR(field_name) \
static uint64_t field_name (ElfParser *parser, gsize offset) \ static uint64_t field_name (ElfParser *parser, gulong offset, gulong nth) \
{ \ { \
const char *data = parser->data + offset; \ return GET_FIELD (parser, offset, Sym, nth, field_name); \
if (parser->is_64) \
return (((Elf64_Sym *)data)->field_name); \
else \
return (((Elf32_Sym *)data)->field_name); \
} }
MAKE_SYMBOL_ACCESSOR(st_name); MAKE_SYMBOL_ACCESSOR(st_name);
MAKE_SYMBOL_ACCESSOR(st_info);
MAKE_SYMBOL_ACCESSOR(st_value);
static const char * MAKE_SYMBOL_ACCESSOR(st_size);
get_string_indirect (BinParser *parser, MAKE_SYMBOL_ACCESSOR(st_other);
BinRecord *record, MAKE_SYMBOL_ACCESSOR(st_shndx);
const char *name,
gsize str_table)
{
const char *result = NULL;
gsize index;
bin_parser_save (parser);
index = bin_parser_get_uint_field (parser, record, name);
bin_parser_set_offset (parser, str_table + index);
result = bin_parser_get_string (parser);
bin_parser_restore (parser);
return result;
}
static void static void
section_free (Section *section) section_free (Section *section)
@ -487,8 +478,6 @@ read_table (ElfParser *parser,
g_print ("sym table offset: %d\n", sym_table->offset); g_print ("sym table offset: %d\n", sym_table->offset);
#endif #endif
bin_parser_set_offset (parser->parser, sym_table->offset);
n_symbols = 0; n_symbols = 0;
#if 0 #if 0
g_print ("n syms: %d\n", parser->n_symbols); g_print ("n syms: %d\n", parser->n_symbols);
@ -497,16 +486,11 @@ read_table (ElfParser *parser,
{ {
guint info; guint info;
gulong addr; gulong addr;
gulong offset;
gulong shndx; gulong shndx;
info = bin_parser_get_uint_field ( info = st_info (parser, sym_table->offset, i);
parser->parser, parser->sym_format, "st_info"); addr = st_value (parser, sym_table->offset, i);
addr = bin_parser_get_uint_field ( shndx = st_shndx (parser, sym_table->offset, i);
parser->parser, parser->sym_format, "st_value");
shndx = bin_parser_get_uint_field (
parser->parser, parser->sym_format, "st_shndx");
offset = bin_parser_get_offset (parser->parser);
#if 0 #if 0
g_print ("read symbol: %s (section: %d)\n", get_string_indirct (parser->parser, g_print ("read symbol: %s (section: %d)\n", get_string_indirct (parser->parser,
@ -518,14 +502,14 @@ read_table (ElfParser *parser,
if (addr != 0 && if (addr != 0 &&
shndx < parser->n_sections && shndx < parser->n_sections &&
parser->sections[shndx] == parser->text_section && parser->sections[shndx] == parser->text_section &&
(info & 0xf) == STT_FUNC && (info & 0xf) == STT_FUNC &&
((info >> 4) == STB_GLOBAL || ((info >> 4) == STB_GLOBAL ||
(info >> 4) == STB_LOCAL || (info >> 4) == STB_LOCAL ||
(info >> 4) == STB_WEAK) (info >> 4) == STB_WEAK))
)
{ {
parser->symbols[n_symbols].address = addr; parser->symbols[n_symbols].address = addr;
parser->symbols[n_symbols].offset = offset; parser->symbols[n_symbols].table = sym_table->offset;
parser->symbols[n_symbols].offset = i;
n_symbols++; n_symbols++;
@ -546,8 +530,6 @@ read_table (ElfParser *parser,
addr, parser, info & 0xf, info >> 4, STT_FUNC, STB_GLOBAL); addr, parser, info & 0xf, info >> 4, STT_FUNC, STB_GLOBAL);
#endif #endif
} }
bin_parser_seek_record (parser->parser, parser->sym_format, 1);
} }
parser->sym_strings = str_table->offset; parser->sym_strings = str_table->offset;
@ -667,12 +649,7 @@ elf_parser_lookup_symbol (ElfParser *parser,
if (result) if (result)
{ {
gulong size; gulong size = st_size (parser, result->table, result->offset);
bin_parser_set_offset (parser->parser, result->offset);
size = bin_parser_get_uint_field (
parser->parser, parser->sym_format, "st_size");
if (size > 0 && result->address + size <= address) if (size > 0 && result->address + size <= address)
{ {
@ -731,32 +708,37 @@ elf_parser_get_build_id (ElfParser *parser)
{ {
if (!parser->checked_build_id) if (!parser->checked_build_id)
{ {
const Section *build_id = find_section (parser, ".note.gnu.build-id", SHT_NOTE); const Section *build_id =
find_section (parser, ".note.gnu.build-id", SHT_NOTE);
guint64 name_size; guint64 name_size;
guint64 desc_size; guint64 desc_size;
guint64 type; guint64 type;
const char *name; const char *name;
const gchar *desc; guint64 offset;
parser->checked_build_id = TRUE; parser->checked_build_id = TRUE;
if (!build_id) if (!build_id)
return NULL; return NULL;
bin_parser_set_offset (parser->parser, build_id->offset); offset = build_id->offset;
name_size = bin_parser_get_uint_field (parser->parser, parser->note_format, "name_size"); name_size = GET_FIELD (parser, offset, Nhdr, 0, n_namesz);
desc_size = bin_parser_get_uint_field (parser->parser, parser->note_format, "desc_size"); desc_size = GET_FIELD (parser, offset, Nhdr, 0, n_descsz);
type = bin_parser_get_uint_field (parser->parser, parser->note_format, "type"); type = GET_FIELD (parser, offset, Nhdr, 0, n_type);
bin_parser_seek_record (parser->parser, parser->note_format, 1); offset += GET_SIZE (parser, Nhdr);
name = bin_parser_get_string (parser->parser);
bin_parser_align (parser->parser, 4); name = parser->data + offset;
desc = bin_parser_get_string (parser->parser); if (strncmp (name, ELF_NOTE_GNU, name_size) != 0 || type != NT_GNU_BUILD_ID)
return NULL;
parser->build_id = make_hex_string (desc, desc_size); offset += strlen (parser->data + offset);
offset = (offset + 3) & (~0x3);
parser->build_id = make_hex_string (parser->data + offset, desc_size);
} }
return parser->build_id; return parser->build_id;
@ -765,6 +747,7 @@ elf_parser_get_build_id (ElfParser *parser)
const char * const char *
elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32) elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
{ {
guint64 offset;
const Section *debug_link = find_section (parser, ".gnu_debuglink", const Section *debug_link = find_section (parser, ".gnu_debuglink",
SHT_PROGBITS); SHT_PROGBITS);
const gchar *result; const gchar *result;
@ -772,14 +755,16 @@ elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
if (!debug_link) if (!debug_link)
return NULL; return NULL;
bin_parser_set_offset (parser->parser, debug_link->offset); offset = debug_link->offset;
result = bin_parser_get_string (parser->parser); result = parser->data + offset;
bin_parser_align (parser->parser, 4);
if (crc32) if (crc32)
*crc32 = bin_parser_get_uint (parser->parser, 4); {
offset = (offset + 3) & ~0x3;
*crc32 = GET_UINT32 (parser, offset);
}
return result; return result;
} }
@ -791,7 +776,7 @@ get_section (ElfParser *parser,
const Section *section = find_section (parser, name, SHT_PROGBITS); const Section *section = find_section (parser, name, SHT_PROGBITS);
if (section) if (section)
return bin_parser_get_data (parser->parser) + section->offset; return parser->data + section->offset;
else else
return NULL; return NULL;
} }
@ -814,7 +799,8 @@ elf_parser_get_sym_name (ElfParser *parser,
{ {
g_return_val_if_fail (parser != NULL, NULL); g_return_val_if_fail (parser != NULL, NULL);
return (char *)(parser->data + parser->sym_strings + st_name (parser, sym->offset)); return (char *)(parser->data + parser->sym_strings +
st_name (parser, sym->table, sym->offset));
} }
gboolean gboolean