diff options
author | Søren Sandmann Pedersen <ssp@src.gnome.org> | 2008-04-20 20:58:11 +0000 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@src.gnome.org> | 2008-04-20 20:58:11 +0000 |
commit | 90d1fa1de5b92650f8afce07fe84c56829425b5f (patch) | |
tree | e85fd954bdee49f40b9a61bb6d082ef9c3317ce4 | |
parent | 12de20b938a28c309642180f84781e2e339a641c (diff) |
Initial build id support
svn path=/trunk/; revision=410
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | binfile.c | 27 | ||||
-rw-r--r-- | binparser.c | 1 | ||||
-rw-r--r-- | elfparser.c | 73 | ||||
-rw-r--r-- | elfparser.h | 2 | ||||
-rw-r--r-- | testelf.c | 15 |
7 files changed, 114 insertions, 11 deletions
@@ -1,3 +1,7 @@ +Sun Apr 20 16:55:47 2008 Søren Sandmann <sandmann@redhat.com> + + * elfparser.c (elf_parser_new_from_data): Initial build-id support + 2008-04-01 Owen Taylor <otaylor@redhat.com> * sysprof.c (on_samples_label_size_request): Constrain the @@ -169,6 +169,9 @@ Before 1.2: - "native endian" is probably not useful. Maybe go back to just having big/little endian. + Should probably rethink the whole thing. It's just not very convenient to use, even + for simple things like ELF files. + * Rename stack_stash_foreach_by_address() to stack_stash_foreach_unique(), or maybe not ... @@ -127,9 +127,9 @@ separate_debug_file_exists (const char *name, guint32 crc) static const char *const debug_file_directory = DEBUGDIR; static ElfParser * -get_debug_file (ElfParser *elf, - const char *filename, - char **new_name) +get_debuglink_file (ElfParser *elf, + const char *filename, + char **new_name) { #define N_TRIES 4 const char *basename; @@ -184,6 +184,27 @@ get_debug_file (ElfParser *elf, } static ElfParser * +get_build_id_file (ElfParser *elf, + const char *filename, + char **new_name) +{ + return NULL; +} + +static ElfParser * +get_debug_file (ElfParser *elf, + const char *filename, + char **new_name) +{ + ElfParser *t; + + if ((t = get_build_id_file (elf, filename, new_name))) + return t; + else + return get_debuglink_file (elf, filename, new_name); +} + +static ElfParser * find_separate_debug_file (ElfParser *elf, const char *filename) { diff --git a/binparser.c b/binparser.c index 0a24981..152315f 100644 --- a/binparser.c +++ b/binparser.c @@ -324,7 +324,6 @@ bin_parser_get_string (BinParser *parser) parser->offset += strlen (result) + 1; return result; - } static const Field * diff --git a/elfparser.c b/elfparser.c index 5224618..b404eca 100644 --- a/elfparser.c +++ b/elfparser.c @@ -48,6 +48,7 @@ struct ElfParser BinRecord * strtab_format; BinRecord * shn_entry; BinRecord * sym_format; + BinRecord * note_format; int n_sections; Section ** sections; @@ -59,6 +60,9 @@ struct ElfParser GMappedFile * file; char * filename; + + gboolean checked_build_id; + char * build_id; const Section * text_section; }; @@ -217,6 +221,7 @@ elf_parser_new_from_data (const guchar *data, parser->text_section = find_section (parser, ".text", SHT_NOBITS); parser->filename = NULL; + parser->build_id = NULL; return parser; } @@ -365,6 +370,9 @@ elf_parser_free (ElfParser *parser) if (parser->filename) g_free (parser->filename); + + if (parser->build_id) + g_free (parser->build_id); g_free (parser); } @@ -468,7 +476,7 @@ read_table (ElfParser *parser, parser->symbols[n_functions].offset = offset; n_functions++; - + #if 0 g_print (" symbol: %s: %lx\n", get_string_indirect (parser->parser, @@ -634,6 +642,53 @@ elf_parser_get_text_offset (ElfParser *parser) return parser->text_section->offset; } +const gchar * +elf_parser_get_build_id (ElfParser *parser) +{ + if (!parser->checked_build_id) + { + const Section *build_id = find_section (parser, ".note.gnu.build-id", SHT_NOTE); + guint64 name_size; + guint64 desc_size; + guint64 type; + const char *name; + const char *desc; + GString *string; + int i; + const char hex_digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', + 'a', 'b', 'c', 'd', 'e', 'f' }; + + parser->checked_build_id = TRUE; + + if (!build_id) + return NULL; + + bin_parser_set_offset (parser->parser, build_id->offset); + + name_size = bin_parser_get_uint_field (parser->parser, parser->note_format, "name_size"); + desc_size = bin_parser_get_uint_field (parser->parser, parser->note_format, "desc_size"); + type = bin_parser_get_uint_field (parser->parser, parser->note_format, "type"); + + name = bin_parser_get_string (parser->parser); + + bin_parser_align (parser->parser, 4); + + desc = bin_parser_get_string (parser->parser); + + string = g_string_new (NULL); + + for (i = 0; i < desc_size; ++i) + { + g_string_append_c (string, hex_digits[desc[i] & 0xf0]); + g_string_append_c (string, hex_digits[desc[i] & 0x0f]); + } + + parser->build_id = g_string_free (string, FALSE); + } + + return parser->build_id; +} + const char * elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32) { @@ -745,7 +800,8 @@ static void get_formats (gboolean is_64, const BinField **elf_header, const BinField **shn_entry, - const BinField **sym_format) + const BinField **sym_format, + const BinField **note_format_out) { static const BinField elf64_header[] = { { "e_ident", BIN_UNINTERPRETED, EI_NIDENT }, @@ -831,6 +887,12 @@ get_formats (gboolean is_64, { "" }, }; + static const BinField note_format[] = { + { "name_size", BIN_UINT, 4 }, + { "desc_size", BIN_UINT, 4 }, + { "type", BIN_UINT, 4 }, + }; + if (is_64) { *elf_header = elf64_header; @@ -843,17 +905,20 @@ get_formats (gboolean is_64, *shn_entry = shn32_entry; *sym_format = sym32_format; } + + *note_format_out = note_format; } static void make_formats (ElfParser *parser, gboolean is_64) { - const BinField *elf_header, *shn_entry, *sym_format; + const BinField *elf_header, *shn_entry, *sym_format, *note_format; - get_formats (is_64, &elf_header, &shn_entry, &sym_format); + get_formats (is_64, &elf_header, &shn_entry, &sym_format, ¬e_format); parser->header = bin_parser_create_record (parser->parser, elf_header); parser->shn_entry = bin_parser_create_record (parser->parser, shn_entry); parser->sym_format = bin_parser_create_record (parser->parser, sym_format); + parser->note_format = bin_parser_create_record (parser->parser, note_format); } diff --git a/elfparser.h b/elfparser.h index 10ba62b..842f85c 100644 --- a/elfparser.h +++ b/elfparser.h @@ -27,11 +27,11 @@ ElfParser * elf_parser_new (const char *filename, void elf_parser_free (ElfParser *parser); const char * elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32); +const gchar *elf_parser_get_build_id (ElfParser *parser); const guchar *elf_parser_get_eh_frame (ElfParser *parser); const guchar *elf_parser_get_debug_frame (ElfParser *parser); gulong elf_parser_get_text_offset (ElfParser *parser); - /* Lookup a symbol in the file. * * The symbol returned is const, so don't free it it or anything. It @@ -31,12 +31,19 @@ check (ElfParser *elf, gulong addr) } int -main () +main (int argc, char **argv) { ElfParser *elf; int i; + const char *build_id; + const char *filename; - elf = elf_parser_new ("/usr/lib/libgtk-x11-2.0.so", NULL); + if (argc == 1) + filename = "/usr/lib/libgtk-x11-2.0.so"; + else + filename = argv[0]; + + elf = elf_parser_new (filename, NULL); if (!elf) { @@ -44,6 +51,10 @@ main () return -1; } + build_id = elf_parser_get_build_id (elf); + + g_print ("build ID: %s\n", build_id); + elf_parser_get_crc32 (elf); for (i = 0; i < 5000000; ++i) |