diff --git a/ChangeLog b/ChangeLog index 08a796a5..5f68a653 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Mon Apr 21 15:54:24 2008 Søren Sandmann + + * binfile.c: More build-id support + Sun Apr 20 16:55:47 2008 Søren Sandmann * elfparser.c (elf_parser_new_from_data): Initial build-id support diff --git a/binfile.c b/binfile.c index d6ccab42..fd6dd23a 100644 --- a/binfile.c +++ b/binfile.c @@ -88,42 +88,6 @@ already_warned (const char *name) return FALSE; } -static ElfParser * -separate_debug_file_exists (const char *name, guint32 crc) -{ - guint32 file_crc; - ElfParser *parser = elf_parser_new (name, NULL); - -#if 0 - g_print (" trying %s: ", name); -#endif - if (!parser) - { -#if 0 - g_print ("no.\n"); -#endif - return NULL; - } - - file_crc = elf_parser_get_crc32 (parser); - - if (file_crc != crc) - { - if (!already_warned (name)) - g_print ("warning: %s has wrong crc \n", name); - - elf_parser_free (parser); - - return NULL; - } - -#if 0 - g_print ("found\n"); -#endif - - return parser; -} - static const char *const debug_file_directory = DEBUGDIR; static ElfParser * @@ -135,9 +99,8 @@ get_debuglink_file (ElfParser *elf, const char *basename; char *dir; guint32 crc32; - char *tries[N_TRIES]; - int i; - ElfParser *result; + GList *tries = NULL, *list; + ElfParser *result = NULL; if (!elf) return NULL; @@ -153,32 +116,41 @@ get_debuglink_file (ElfParser *elf, dir = g_path_get_dirname (filename); - tries[0] = g_build_filename (dir, basename, NULL); - tries[1] = g_build_filename (dir, ".debug", basename, NULL); - tries[2] = g_build_filename ("/usr", "lib", "debug", dir, basename, NULL); - tries[3] = g_build_filename (debug_file_directory, dir, basename, NULL); + tries = g_list_append (tries, g_build_filename (dir, basename, NULL)); + tries = g_list_append (tries, g_build_filename (dir, ".debug", basename, NULL)); + tries = g_list_append (tries, g_build_filename ("/usr", "lib", "debug", dir, basename, NULL)); + tries = g_list_append (tries, g_build_filename (debug_file_directory, dir, basename, NULL)); - for (i = 0; i < N_TRIES; ++i) + for (list = tries; list != NULL; list = list->next) { -#if 0 - g_print ("trying: %s\n", tries[i]); -#endif - result = separate_debug_file_exists (tries[i], crc32); - if (result) + const char *name = list->data; + ElfParser *parser = elf_parser_new (name, NULL); + guint32 file_crc; + + if (parser) { -#if 0 - g_print (" found debug binary for %s: %s\n", filename, tries[i]); -#endif - if (new_name) - *new_name = g_strdup (tries[i]); - break; + file_crc = elf_parser_get_crc32 (parser); + + if (file_crc == crc32) + { + result = parser; + *new_name = g_strdup (name); + break; + } + else + { + if (!already_warned (name)) + g_print ("warning: %s has wrong crc \n", name); + } + + elf_parser_free (parser); } } - + g_free (dir); - for (i = 0; i < N_TRIES; ++i) - g_free (tries[i]); + g_list_foreach (tries, (GFunc)g_free, NULL); + g_list_free (tries); return result; } @@ -188,7 +160,50 @@ get_build_id_file (ElfParser *elf, const char *filename, char **new_name) { - return NULL; + const char *build_id = elf_parser_get_build_id (elf); + GList *tries = NULL, *list; + char *init, *rest; + ElfParser *result = NULL; + + if (!build_id) + return NULL; + + if (strlen (build_id) < 4) + return NULL; + + init = g_strndup (build_id, 2); + rest = g_strdup_printf (build_id + 2, ".debug"); + + tries = g_list_append (tries, g_build_filename ("/usr", "lib", "debug", ".build-id", init, rest, NULL)); + tries = g_list_append (tries, g_build_filename (debug_file_directory, ".build-id", init, rest, NULL)); + + for (list = tries; list != NULL; list = list->next) + { + const char *name = list->data; + ElfParser *parser = elf_parser_new (name, NULL); + + if (parser) + { + const char *file_id = elf_parser_get_build_id (parser); + + if (file_id && strcmp (build_id, file_id) == 0) + { + *new_name = g_strdup (filename); + result = parser; + break; + } + + elf_parser_free (parser); + } + } + + g_list_foreach (tries, (GFunc)g_free, NULL); + g_list_free (tries); + + g_free (init); + g_free (rest); + + return result; } static ElfParser * diff --git a/elfparser.c b/elfparser.c index b404eca1..5a777a4e 100644 --- a/elfparser.c +++ b/elfparser.c @@ -642,6 +642,27 @@ elf_parser_get_text_offset (ElfParser *parser) return parser->text_section->offset; } +static gchar * +make_hex_string (const guchar *data, int n_bytes) +{ + GString *string = g_string_new (NULL); + const char hex_digits[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + int i; + + for (i = 0; i < n_bytes; ++i) + { + char c = data[i]; + + g_string_append_c (string, hex_digits[(c & 0xf0) >> 4]); + g_string_append_c (string, hex_digits[(c & 0x0f)]); + } + + return g_string_free (string, FALSE); +} + const gchar * elf_parser_get_build_id (ElfParser *parser) { @@ -652,11 +673,7 @@ elf_parser_get_build_id (ElfParser *parser) 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' }; + const gchar *desc; parser->checked_build_id = TRUE; @@ -668,22 +685,15 @@ elf_parser_get_build_id (ElfParser *parser) 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"); - + + bin_parser_seek_record (parser->parser, parser->note_format, 1); 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); + + parser->build_id = make_hex_string (desc, desc_size); } return parser->build_id; diff --git a/testelf.c b/testelf.c index 9a96e80b..fac5c925 100644 --- a/testelf.c +++ b/testelf.c @@ -41,7 +41,7 @@ main (int argc, char **argv) if (argc == 1) filename = "/usr/lib/libgtk-x11-2.0.so"; else - filename = argv[0]; + filename = argv[1]; elf = elf_parser_new (filename, NULL); @@ -57,7 +57,9 @@ main (int argc, char **argv) elf_parser_get_crc32 (elf); +#if 0 for (i = 0; i < 5000000; ++i) +#endif { elf_parser_get_crc32 (elf); check (elf, 0x077c80f0 - (0x07787000 - 0)); /* gtk_about_dialog_set_artists (add - (map - offset)) */