mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
Beginning of the end for BinParser.
Instead of the clunky BinParser, we are moving to a scheme where the ELF accessors are defined by macros. This is the first step towards getting rid of it.
This commit is contained in:
145
elfparser.c
145
elfparser.c
@ -49,6 +49,10 @@ struct ElfParser
|
||||
BinRecord * shn_entry;
|
||||
BinRecord * sym_format;
|
||||
BinRecord * note_format;
|
||||
|
||||
gboolean is_64;
|
||||
const char * data;
|
||||
gsize length;
|
||||
|
||||
int n_sections;
|
||||
Section ** sections;
|
||||
@ -71,6 +75,63 @@ static gboolean parse_elf_signature (const guchar *data, gsize length,
|
||||
gboolean *is_64, gboolean *is_be);
|
||||
static void make_formats (ElfParser *parser, gboolean is_64);
|
||||
|
||||
#define MAKE_ELF_UINT_ACCESSOR(field_name) \
|
||||
static uint64_t field_name (ElfParser *parser) \
|
||||
{ \
|
||||
if (parser->is_64) \
|
||||
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_machine)
|
||||
MAKE_ELF_UINT_ACCESSOR (e_version)
|
||||
MAKE_ELF_UINT_ACCESSOR (e_entry)
|
||||
MAKE_ELF_UINT_ACCESSOR (e_phoff)
|
||||
MAKE_ELF_UINT_ACCESSOR (e_shoff)
|
||||
MAKE_ELF_UINT_ACCESSOR (e_flags)
|
||||
MAKE_ELF_UINT_ACCESSOR (e_ehsize)
|
||||
MAKE_ELF_UINT_ACCESSOR (e_phentsize)
|
||||
MAKE_ELF_UINT_ACCESSOR (e_phnum)
|
||||
MAKE_ELF_UINT_ACCESSOR (e_shentsize)
|
||||
MAKE_ELF_UINT_ACCESSOR (e_shnum)
|
||||
MAKE_ELF_UINT_ACCESSOR (e_shstrndx)
|
||||
|
||||
#define MAKE_SECTION_HEADER_ACCESSOR(field_name) \
|
||||
static uint64_t field_name (ElfParser *parser, int nth_section) \
|
||||
{ \
|
||||
const char *data = parser->data + e_shoff (parser); \
|
||||
if (parser->is_64) \
|
||||
return (((Elf64_Shdr *)data) + nth_section)->field_name; \
|
||||
else \
|
||||
return (((Elf32_Shdr *)data) + nth_section)->field_name; \
|
||||
}
|
||||
|
||||
MAKE_SECTION_HEADER_ACCESSOR (sh_name);
|
||||
MAKE_SECTION_HEADER_ACCESSOR (sh_type);
|
||||
MAKE_SECTION_HEADER_ACCESSOR (sh_flags);
|
||||
MAKE_SECTION_HEADER_ACCESSOR (sh_addr);
|
||||
MAKE_SECTION_HEADER_ACCESSOR (sh_offset);
|
||||
MAKE_SECTION_HEADER_ACCESSOR (sh_size);
|
||||
MAKE_SECTION_HEADER_ACCESSOR (sh_link);
|
||||
MAKE_SECTION_HEADER_ACCESSOR (sh_info);
|
||||
MAKE_SECTION_HEADER_ACCESSOR (sh_addralign);
|
||||
MAKE_SECTION_HEADER_ACCESSOR (sh_entsize);
|
||||
|
||||
#define MAKE_SYMBOL_ACCESSOR(field_name) \
|
||||
static uint64_t field_name (ElfParser *parser, gsize offset) \
|
||||
{ \
|
||||
const char *data = parser->data + offset; \
|
||||
if (parser->is_64) \
|
||||
return (((Elf64_Sym *)data)->field_name); \
|
||||
else \
|
||||
return (((Elf32_Sym *)data)->field_name); \
|
||||
}
|
||||
|
||||
MAKE_SYMBOL_ACCESSOR(st_name);
|
||||
|
||||
|
||||
static const char *
|
||||
get_string_indirect (BinParser *parser,
|
||||
BinRecord *record,
|
||||
@ -93,36 +154,6 @@ get_string_indirect (BinParser *parser,
|
||||
return result;
|
||||
}
|
||||
|
||||
static Section *
|
||||
section_new (BinParser *parser,
|
||||
BinRecord *record,
|
||||
gsize name_table)
|
||||
{
|
||||
Section *section = g_new (Section, 1);
|
||||
guint64 flags;
|
||||
|
||||
section->name = get_string_indirect (parser, record, "sh_name", name_table);
|
||||
section->size = bin_parser_get_uint_field (parser, record, "sh_size");
|
||||
section->offset = bin_parser_get_uint_field (parser, record, "sh_offset");
|
||||
|
||||
flags = bin_parser_get_uint_field (parser, record, "sh_flags");
|
||||
section->allocated = !!(flags & SHF_ALLOC);
|
||||
|
||||
if (section->allocated)
|
||||
{
|
||||
section->load_address = bin_parser_get_uint_field (
|
||||
parser, record, "sh_addr");
|
||||
}
|
||||
else
|
||||
{
|
||||
section->load_address = 0;
|
||||
}
|
||||
|
||||
section->type = bin_parser_get_uint_field (parser, record, "sh_type");
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
static void
|
||||
section_free (Section *section)
|
||||
{
|
||||
@ -154,7 +185,7 @@ elf_parser_new_from_data (const guchar *data,
|
||||
ElfParser *parser;
|
||||
gboolean is_64, is_big_endian;
|
||||
int section_names_idx;
|
||||
gsize section_names;
|
||||
const char *section_names;
|
||||
gsize section_headers;
|
||||
int i;
|
||||
|
||||
@ -165,6 +196,10 @@ elf_parser_new_from_data (const guchar *data,
|
||||
}
|
||||
|
||||
parser = g_new0 (ElfParser, 1);
|
||||
|
||||
parser->is_64 = is_64;
|
||||
parser->data = (const char *)data;
|
||||
parser->length = length;
|
||||
|
||||
#if 0
|
||||
g_print (" new parser : %p\n", parser);
|
||||
@ -184,16 +219,15 @@ elf_parser_new_from_data (const guchar *data,
|
||||
|
||||
bin_parser_set_offset (parser->parser, 0);
|
||||
|
||||
parser->n_sections = bin_parser_get_uint_field (
|
||||
parser->parser, parser->header, "e_shnum");
|
||||
section_names_idx = bin_parser_get_uint_field (
|
||||
parser->parser, parser->header, "e_shstrndx");
|
||||
section_headers = bin_parser_get_uint_field (
|
||||
parser->parser, parser->header, "e_shoff");
|
||||
parser->n_sections = e_shnum (parser);
|
||||
section_names_idx = e_shstrndx (parser);
|
||||
section_headers = e_shoff (parser);
|
||||
|
||||
/* Read section headers */
|
||||
parser->sections = g_new0 (Section *, parser->n_sections);
|
||||
|
||||
|
||||
|
||||
bin_parser_set_offset (parser->parser, section_headers);
|
||||
|
||||
bin_parser_save (parser->parser);
|
||||
@ -201,18 +235,27 @@ elf_parser_new_from_data (const guchar *data,
|
||||
bin_parser_seek_record (parser->parser, parser->shn_entry,
|
||||
section_names_idx);
|
||||
|
||||
section_names = bin_parser_get_uint_field (
|
||||
parser->parser, parser->shn_entry, "sh_offset");
|
||||
section_names = parser->data + sh_offset (parser, section_names_idx);
|
||||
|
||||
bin_parser_restore (parser->parser);
|
||||
|
||||
for (i = 0; i < parser->n_sections; ++i)
|
||||
{
|
||||
parser->sections[i] = section_new (parser->parser,
|
||||
parser->shn_entry,
|
||||
section_names);
|
||||
Section *section = g_new (Section, 1);
|
||||
|
||||
section->name = (char *)(section_names + sh_name (parser, i));
|
||||
section->size = sh_size (parser, i);
|
||||
section->offset = sh_offset (parser, i);
|
||||
section->allocated = !!(sh_flags (parser, i) & SHF_ALLOC);
|
||||
|
||||
if (section->allocated)
|
||||
section->load_address = sh_addr (parser, i);
|
||||
else
|
||||
section->load_address = 0;
|
||||
|
||||
section->type = sh_type (parser, i);
|
||||
|
||||
bin_parser_seek_record (parser->parser, parser->shn_entry, 1);
|
||||
parser->sections[i] = section;
|
||||
}
|
||||
|
||||
/* Cache the text section */
|
||||
@ -330,8 +373,8 @@ elf_parser_get_crc32 (ElfParser *parser)
|
||||
gulong crc;
|
||||
gsize i;
|
||||
|
||||
data = bin_parser_get_data (parser->parser);
|
||||
length = bin_parser_get_length (parser->parser);
|
||||
data = parser->data;
|
||||
length = parser->length;
|
||||
|
||||
crc = 0xffffffff;
|
||||
|
||||
@ -466,7 +509,7 @@ read_table (ElfParser *parser,
|
||||
offset = bin_parser_get_offset (parser->parser);
|
||||
|
||||
#if 0
|
||||
g_print ("read symbol: %s (section: %d)\n", get_string_indirect (parser->parser,
|
||||
g_print ("read symbol: %s (section: %d)\n", get_string_indirct (parser->parser,
|
||||
parser->sym_format, "st_name",
|
||||
str_table->offset),
|
||||
shndx);
|
||||
@ -769,15 +812,9 @@ const char *
|
||||
elf_parser_get_sym_name (ElfParser *parser,
|
||||
const ElfSym *sym)
|
||||
{
|
||||
const char *result;
|
||||
|
||||
g_return_val_if_fail (parser != NULL, NULL);
|
||||
|
||||
bin_parser_set_offset (parser->parser, sym->offset);
|
||||
result = get_string_indirect (
|
||||
parser->parser, parser->sym_format, "st_name", parser->sym_strings);
|
||||
|
||||
return result;
|
||||
|
||||
return (char *)(parser->data + parser->sym_strings + st_name (parser, sym->offset));
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
||||
Reference in New Issue
Block a user