static ElfParser * get_build_id_file (ElfParser *elf) { const char *build_id; GList *tries = NULL, *list; char *init, *rest; ElfParser *result = NULL; char *tmp; build_id = elf_parser_get_build_id (elf); if (!build_id) return NULL; if (strlen (build_id) < 4) return NULL; init = g_strndup (build_id, 2); rest = g_strdup_printf ("%s%s", build_id + 2, ".debug"); tmp = g_build_filename ( "/usr", "lib", "debug", ".build-id", init, rest, NULL); tries = g_list_append (tries, tmp); tmp = g_build_filename ( debug_file_directory, ".build-id", init, rest, NULL); tries = g_list_append (tries, tmp); for (list = tries; list != NULL; list = list->next) { 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) { 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; }
int main (int argc, char **argv) { ElfParser *elf; const char *build_id; const char *filename; if (argc == 1) filename = "/usr/lib/libgtk-x11-2.0.so"; else filename = argv[1]; elf = elf_parser_new (filename, NULL); if (!elf) { g_print ("NO ELF!!!!\n"); return -1; } build_id = elf_parser_get_build_id (elf); g_print ("build ID: %s\n", build_id); 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)) */ check (elf, 0x077c80f0 - (0x07787000 - 0)); /* same (but in the middle of the function */ } return 0; }
static ElfParser * get_debuglink_file (ElfParser *elf, const char *filename, char **new_name) { #define N_TRIES 4 const char *basename; char *dir; guint32 crc32; GList *tries = NULL, *list; ElfParser *result = NULL; const char *build_id; if (!elf) return NULL; basename = elf_parser_get_debug_link (elf, &crc32); build_id = elf_parser_get_build_id (elf); #if 0 g_print (" debug link for %s is %s\n", filename, basename); #endif if (!basename) return NULL; dir = g_path_get_dirname (filename); 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 (list = tries; list != NULL; list = list->next) { const char *name = list->data; ElfParser *parser = elf_parser_new (name, NULL); guint32 file_crc; const char *file_build_id; if (parser) { /* If both files have build ids, and they don't match, * there is no point computing a CRC32 that we know * will fail */ file_build_id = elf_parser_get_build_id (parser); if (build_id && file_build_id && strcmp (build_id, file_build_id) != 0) goto skip; 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 %x, %s has crc %x)\n", name, file_crc, filename, crc32); } } skip: elf_parser_free (parser); } } g_free (dir); g_list_foreach (tries, (GFunc)g_free, NULL); g_list_free (tries); return result; }