From 49e1fabe463069567ec788070d1fab283f9282ef Mon Sep 17 00:00:00 2001 From: Soren Sandmann Date: Sun, 20 Aug 2006 06:26:54 +0000 Subject: [PATCH] Read the name out of the file instead of out of the struct. 2006-08-20 Soren Sandmann * elfparser.c (elf_sym_get_name): Read the name out of the file instead of out of the struct. * elfparser.c (struct ElfSym): Store an offset instead of the name. * elfparser.c (all_elf_parsers): Keep track of all elf parsers created. --- ChangeLog | 11 +++++++++++ binparser.c | 9 +++++++++ binparser.h | 1 + demangle.c | 6 ++++++ elfparser.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++------ elfparser.h | 1 + testelf.c | 25 +++++++++++++++++++------ 7 files changed, 96 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 240ee03..a92e696 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2006-08-20 Soren Sandmann + * elfparser.c (elf_sym_get_name): Read the name out of the file + instead of out of the struct. + + * elfparser.c (struct ElfSym): Store an offset instead of the + name. + + * elfparser.c (all_elf_parsers): Keep track of all elf parsers + created. + +2006-08-20 Soren Sandmann + * Makefile.am, demangle.c: New file, made out of files from libiberty in binutils. diff --git a/binparser.c b/binparser.c index 5c70e97..6527323 100644 --- a/binparser.c +++ b/binparser.c @@ -324,6 +324,15 @@ bin_parser_index (BinParser *parser, parser->frame->index = index; } +gsize +bin_parser_get_offset (BinParser *parser) +{ + g_return_val_if_fail (parser != NULL, 0); + g_return_val_if_fail (parser->frame != NULL, 0); + + return parser->frame->offset; +} + BinField * bin_field_new_fixed_array (int n_elements, int element_size) diff --git a/binparser.h b/binparser.h index af1d505..26a545e 100644 --- a/binparser.h +++ b/binparser.h @@ -8,6 +8,7 @@ BinParser *bin_parser_new (const guchar *data, BinFormat *bin_format_new (gboolean big_endian, const char *name, BinField *field, ...); +gsize bin_parser_get_offset (BinParser *parser); gsize bin_format_get_size (BinFormat *format); void bin_parser_index (BinParser *parser, int index); void bin_parser_begin (BinParser *parser, diff --git a/demangle.c b/demangle.c index 4426261..54188de 100644 --- a/demangle.c +++ b/demangle.c @@ -14,6 +14,12 @@ * in sysprof were made static or removed. * * Let's hope that no bugs are ever found in this file! + * + * Maybe someday look at what can be deleted from this file + * + * - "mini string library" can be replaced with GString + * - "option" parameter to cplus_demangle can be deleted + * - demangling is always "auto" */ /* Copyright notices: diff --git a/elfparser.c b/elfparser.c index 051e894..6bad324 100644 --- a/elfparser.c +++ b/elfparser.c @@ -13,7 +13,7 @@ struct SymbolTable struct ElfSym { - const char *name; + gulong offset; gulong address; }; @@ -38,6 +38,7 @@ struct ElfParser int n_symbols; ElfSym * symbols; + gsize sym_strings; }; static gboolean parse_elf_signature (const guchar *data, gsize length, @@ -102,6 +103,8 @@ find_section (ElfParser *parser, return NULL; } +static GList *all_elf_parsers = NULL; + ElfParser * elf_parser_new (const guchar *data, gsize length) { @@ -149,6 +152,8 @@ elf_parser_new (const guchar *data, gsize length) } bin_parser_end (parser->parser); + + all_elf_parsers = g_list_prepend (all_elf_parsers, parser); return parser; } @@ -157,6 +162,8 @@ void elf_parser_free (ElfParser *parser) { int i; + + all_elf_parsers = g_list_remove (all_elf_parsers, parser); for (i = 0; i < parser->n_sections; ++i) section_free (parser->sections[i]); @@ -218,8 +225,8 @@ read_table (ElfParser *parser, parser->n_symbols = sym_table->size / sym_size; parser->symbols = g_new (ElfSym, parser->n_symbols); - g_print ("\nreading %d symbols from %s\n", - parser->n_symbols, sym_table->name); + g_print ("\nreading %d symbols (@%d bytes) from %s\n", + parser->n_symbols, sym_size, sym_table->name); bin_parser_begin (parser->parser, parser->sym_format, sym_table->offset); @@ -229,20 +236,22 @@ read_table (ElfParser *parser, guint info; gulong addr; const char *name; + gulong offset; bin_parser_index (parser->parser, i); info = bin_parser_get_uint (parser->parser, "st_info"); addr = bin_parser_get_uint (parser->parser, "st_value"); name = get_string (parser->parser, str_table->offset, "st_name"); + offset = bin_parser_get_offset (parser->parser); if (addr != 0 && (info & 0xf) == STT_FUNC && ((info >> 4) == STB_GLOBAL || (info >> 4) == STB_LOCAL)) { - parser->symbols[n_functions].name = name; parser->symbols[n_functions].address = addr; + parser->symbols[n_functions].offset = offset; n_functions++; } @@ -251,7 +260,8 @@ read_table (ElfParser *parser, bin_parser_end (parser->parser); g_print ("found %d functions\n", n_functions); - + + parser->sym_strings = str_table->offset; parser->n_symbols = n_functions; parser->symbols = g_renew (ElfSym, parser->symbols, parser->n_symbols); @@ -331,10 +341,43 @@ elf_parser_lookup_symbol (ElfParser *parser, return do_lookup (parser->symbols, address, 0, parser->n_symbols - 1); } +static ElfParser * +parser_from_sym (const ElfSym *sym) +{ + GList *list; + + /* FIXME: This is gross, but the alternatives I can think of + * are all worse. + */ + for (list = all_elf_parsers; list != NULL; list = list->next) + { + ElfParser *parser = list->data; + + if (sym >= parser->symbols && + sym < parser->symbols + parser->n_symbols) + { + return parser; + } + } + + return NULL; +} + const char * elf_sym_get_name (const ElfSym *sym) { - return sym->name; + ElfParser *parser = parser_from_sym (sym); + const char *result; + + g_return_val_if_fail (parser != NULL, NULL); + + bin_parser_begin (parser->parser, parser->sym_format, sym->offset); + + result = get_string (parser->parser, parser->sym_strings, "st_name"); + + bin_parser_end (parser->parser); + + return result; } gulong diff --git a/elfparser.h b/elfparser.h index 2f4ce4a..15da42f 100644 --- a/elfparser.h +++ b/elfparser.h @@ -5,6 +5,7 @@ typedef struct ElfParser ElfParser; ElfParser *elf_parser_new (const guchar *data, gsize length); +void elf_parser_free (ElfParser *parser); /* Lookup a symbol in the file. * diff --git a/testelf.c b/testelf.c index 665b532..d4b0d46 100644 --- a/testelf.c +++ b/testelf.c @@ -1,22 +1,31 @@ #include #include "elfparser.h" +const char *n; + static void check (ElfParser *elf, gulong addr) { const ElfSym *sym = elf_parser_lookup_symbol (elf, addr); + n = elf_sym_get_name (sym); - g_print ("%p => ", addr); +#if 0 + g_print ("%p => ", (void *)addr); +#endif if (sym) { +#if 0 g_print ("found: %s (%p)\n", elf_sym_get_name (sym), - elf_sym_get_address (sym)); + (void *)elf_sym_get_address (sym)); +#endif } else { - g_print ("not found\n"); +#if 0 + g_print ("not found\n"); +#endif } } @@ -28,10 +37,14 @@ main () ElfParser *elf = elf_parser_new ( g_mapped_file_get_contents (libgtk), g_mapped_file_get_length (libgtk)); - - check (elf, 0x3e7ef20); /* gtk_handle_box_end_drag */ - check (elf, 0x3e7ef25); /* same */ + int i; + + for (i = 0; i < 5000000; ++i) + { + check (elf, 0x3e7ef20); /* gtk_handle_box_end_drag */ + check (elf, 0x3e7ef25); /* same (but in the middle of the function */ + } return 0; } -- 2.7.4