From 1f4dd13cd33954835d67c2439e20ad476d1f9e51 Mon Sep 17 00:00:00 2001 From: Soren Sandmann Date: Wed, 16 Aug 2006 17:21:54 +0000 Subject: [PATCH] Really add this file. 2006-08-16 Soren Sandmann * testelf.c: Really add this file. --- ChangeLog | 4 ++ binparser.c | 11 +++++ elfparser.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++----- testelf.c | 24 +++++++++++ 4 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 testelf.c diff --git a/ChangeLog b/ChangeLog index a2836438..ff67d547 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2006-08-16 Soren Sandmann + + * testelf.c: Really add this file. + 2006-08-15 Soren Sandmann Add beginning of an ELF parser. diff --git a/binparser.c b/binparser.c index 30947af9..5c70e97e 100644 --- a/binparser.c +++ b/binparser.c @@ -78,6 +78,13 @@ read_varargs (va_list args, static guint64 align (guint64 offset, int alignment) { + /* Note that we can speed this up by assuming alignment' + * is a power of two, since + * + * offset % alignment == offset & (alignemnt - 1) + * + */ + if (offset % alignment != 0) offset += (alignment - (offset % alignment)); @@ -229,7 +236,9 @@ bin_parser_get_uint (BinParser *parser, return r64; } +#if 0 g_print ("width: %d\n", field->width); +#endif g_assert_not_reached(); return 0; @@ -456,11 +465,13 @@ parse_elf (const guchar *data, section_header = data + bin_parser_get_uint (parser, "e_shoff"); +#if 0 g_print ("section header offset: %u\n", section_header - data); g_print ("There are %llu sections\n", bin_parser_get_uint (parser, "e_shnum")); +#endif /* should think through how to deal with offsets, and whether parsers * are always considered parsers of an array. If yes, then it diff --git a/elfparser.c b/elfparser.c index 5616e425..f8c43bcf 100644 --- a/elfparser.c +++ b/elfparser.c @@ -117,9 +117,11 @@ find_elf_type (const guchar *data, gsize length, return FALSE; } +#if 0 g_print ("This elf file is %s %s\n", *is_64? "64 bit" : "32 bit", *is_be? "big endiann" : "little endian"); +#endif return TRUE; } @@ -145,11 +147,13 @@ dump_symbol_table (ElfParser *parser, return; } +#if 0 g_print ("dumping symbol table at %d\n", offset); +#endif bin_parser_begin (parser->parser, parser->sym_format, offset); - for (i = 0; i < 200; ++i) + for (i = 0; i < 2000; ++i) { guint64 idx; @@ -157,6 +161,8 @@ dump_symbol_table (ElfParser *parser, idx = bin_parser_get_uint (parser->parser, "st_name"); const char *result; gsize size; + gulong addr; + guint info; #if 0 g_print ("addr: %p\n", bin_parser_get_address (parser->parser, "st_name")); @@ -166,16 +172,22 @@ dump_symbol_table (ElfParser *parser, #endif size = bin_parser_get_uint (parser->parser, "st_size"); - - bin_parser_begin (parser->parser, - NULL, parser->str_table + idx); - - result = bin_parser_get_string (parser->parser); + info = bin_parser_get_uint (parser->parser, "st_info"); - bin_parser_end (parser->parser); - - g_print ("%d symbol: size: %d, %s.\n", - i, size, result); + if (info == STT_FUNC) + { + addr = bin_parser_get_uint (parser->parser, "st_value"); + + bin_parser_begin (parser->parser, + NULL, parser->str_table + idx); + + result = bin_parser_get_string (parser->parser); + + bin_parser_end (parser->parser); + + g_print ("%d %p: symbol: size: %d, %s\n", + i, (void *)addr, size, result); + } } bin_parser_end (parser->parser); @@ -223,7 +235,7 @@ elf_parser_new (const guchar *data, gsize length) { const char *name; int offset; - + bin_parser_index (parser->parser, i); offset = bin_parser_get_uint (parser->parser, "sh_name"); name = elf_lookup_string (parser, offset); @@ -378,11 +390,80 @@ find_section (ElfParser *parser, out: bin_parser_end (bparser); +#if 0 g_print ("found %s at %d\n", name, result); +#endif return result; } +static gboolean +check_symbol (ElfParser *parser, + int index, + gulong address) +{ + bin_parser_index (parser, index); + + /* FIXME */ + + return FALSE; +} + +void +lookup_function_symbol (ElfParser *parser, + int begin, + int end, + gulong address) +{ + g_assert (end - begin > 0); + + if (end - begin < 10) + { + int i; + + for (i = 0; i < end - begin; ++i) + { + bin_parser_index (parser, i); + if (check_symbol (parser, i, address)) + return; + } + } + else + { + int mid1 = (end - begin) / 2; + int mid2 = ((end - begin) / 2 - 1); + + while (mid1 >= begin && + mid2 < end) + { + /* + + if mid1 is a function, + then check the address. + if higher than input address, + recurse on (begin, mid1). + else + recurse on (mid2 - 1, end) + + + similar for mid2, only the other way around. + + of course, if one of them matches + */ + + + if (check_symbol (parser, mid1, address)) + return; + + if (check_symbol (parser, mid2, address)) + return; + + mid1--; + mid2++; + } + } +} + const ElfSym * elf_parser_lookup_symbol (ElfParser *parser, gulong address) @@ -392,6 +473,16 @@ elf_parser_lookup_symbol (ElfParser *parser, gssize dynsym_offset = find_section (parser, ".dynsym"); gssize dynstr_offset = find_section (parser, ".dynstr"); + if (symtab_offset != -1 && strtab_offset != -1) + { + /* lookup in normal symbol table */ + } + + if (dynsym_offset != -1 && dynstr_offset != -1) + { + /* lookup in dynsym table */ + } + return NULL; } diff --git a/testelf.c b/testelf.c new file mode 100644 index 00000000..fa3bcb56 --- /dev/null +++ b/testelf.c @@ -0,0 +1,24 @@ +#include +#include "elfparser.h" + +int +main () +{ + int i; + + GMappedFile *libgtk = g_mapped_file_new ("/usr/lib/libgtk-x11-2.0.so", + FALSE, NULL); + + +#if 0 + for (i = 0; i < 50000; ++i) +#endif + { + ElfParser *elf = elf_parser_new ( + g_mapped_file_get_contents (libgtk), + g_mapped_file_get_length (libgtk)); + + elf_parser_lookup_symbol (elf, 1000); + } +} +