X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fbuild-id.c;h=e8d77bb44c80305dfc682aa94eb75ea05c83f409;hb=f81e7e2db6d1aaf47561e54356aee12b585533c2;hp=57d98c96181f8ef3c6ad36fc0f4085ecce105eb9;hpb=e80aaf6183c6692ecc167bf26cbdc53f8f1a55f0;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/build-id.c b/gdb/build-id.c index 57d98c9618..e8d77bb44c 100644 --- a/gdb/build-id.c +++ b/gdb/build-id.c @@ -1,6 +1,6 @@ /* build-id-related functions. - Copyright (C) 1991-2018 Free Software Foundation, Inc. + Copyright (C) 1991-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -21,7 +21,7 @@ #include "bfd.h" #include "gdb_bfd.h" #include "build-id.h" -#include "gdb_vecs.h" +#include "gdbsupport/gdb_vecs.h" #include "symfile.h" #include "objfiles.h" #include "filenames.h" @@ -32,7 +32,8 @@ const struct bfd_build_id * build_id_bfd_get (bfd *abfd) { - if (!bfd_check_format (abfd, bfd_object)) + if (!bfd_check_format (abfd, bfd_object) + && !bfd_check_format (abfd, bfd_core)) return NULL; if (abfd->build_id != NULL) @@ -65,22 +66,66 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check) return retval; } -/* See build-id.h. */ +/* Helper for build_id_to_debug_bfd. LINK is a path to a potential + build-id-based separate debug file, potentially a symlink to the real file. + If the file exists and matches BUILD_ID, return a BFD reference to it. */ -gdb_bfd_ref_ptr -build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id) +static gdb_bfd_ref_ptr +build_id_to_debug_bfd_1 (const std::string &link, size_t build_id_len, + const bfd_byte *build_id) { - char *link, *debugdir; - int ix; - gdb_bfd_ref_ptr abfd; - int alloc_len; + if (separate_debug_file_debug) + { + printf_unfiltered (_(" Trying %s..."), link.c_str ()); + gdb_flush (gdb_stdout); + } + + /* lrealpath() is expensive even for the usually non-existent files. */ + gdb::unique_xmalloc_ptr filename; + if (access (link.c_str (), F_OK) == 0) + filename.reset (lrealpath (link.c_str ())); + + if (filename == NULL) + { + if (separate_debug_file_debug) + printf_unfiltered (_(" no, unable to compute real path\n")); + + return {}; + } + + /* We expect to be silent on the non-existing files. */ + gdb_bfd_ref_ptr debug_bfd = gdb_bfd_open (filename.get (), gnutarget, -1); - /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */ - alloc_len = (strlen (debug_file_directory) - + (sizeof "/.build-id/" - 1) + 1 - + 2 * build_id_len + (sizeof ".debug" - 1) + 1); - link = (char *) alloca (alloc_len); + if (debug_bfd == NULL) + { + if (separate_debug_file_debug) + printf_unfiltered (_(" no, unable to open.\n")); + + return {}; + } + + if (!build_id_verify (debug_bfd.get(), build_id_len, build_id)) + { + if (separate_debug_file_debug) + printf_unfiltered (_(" no, build-id does not match.\n")); + + return {}; + } + + if (separate_debug_file_debug) + printf_unfiltered (_(" yes!\n")); + + return debug_bfd; +} +/* Common code for finding BFDs of a given build-id. This function + works with both debuginfo files (SUFFIX == ".debug") and executable + files (SUFFIX == ""). */ + +static gdb_bfd_ref_ptr +build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id, + const char *suffix) +{ /* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will cause "/.build-id/..." lookups. */ @@ -89,54 +134,70 @@ build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id) for (const gdb::unique_xmalloc_ptr &debugdir : debugdir_vec) { - size_t debugdir_len = strlen (debugdir.get ()); const gdb_byte *data = build_id; size_t size = build_id_len; - char *s; - memcpy (link, debugdir.get (), debugdir_len); - s = &link[debugdir_len]; - s += sprintf (s, "/.build-id/"); + /* Compute where the file named after the build-id would be. + + If debugdir is "/usr/lib/debug" and the build-id is abcdef, this will + give "/usr/lib/debug/.build-id/ab/cdef.debug". */ + std::string link = debugdir.get (); + link += "/.build-id/"; + if (size > 0) { size--; - s += sprintf (s, "%02x", (unsigned) *data++); + string_appendf (link, "%02x/", (unsigned) *data++); } - if (size > 0) - *s++ = '/'; + while (size-- > 0) - s += sprintf (s, "%02x", (unsigned) *data++); - strcpy (s, ".debug"); + string_appendf (link, "%02x", (unsigned) *data++); - if (separate_debug_file_debug) - printf_unfiltered (_(" Trying %s\n"), link); + link += suffix; - /* lrealpath() is expensive even for the usually non-existent files. */ - gdb::unique_xmalloc_ptr filename; - if (access (link, F_OK) == 0) - filename.reset (lrealpath (link)); + gdb_bfd_ref_ptr debug_bfd + = build_id_to_debug_bfd_1 (link, build_id_len, build_id); + if (debug_bfd != NULL) + return debug_bfd; - if (filename == NULL) - continue; + /* Try to look under the sysroot as well. If the sysroot is + "/the/sysroot", it will give + "/the/sysroot/usr/lib/debug/.build-id/ab/cdef.debug". - /* We expect to be silent on the non-existing files. */ - abfd = gdb_bfd_open (filename.get (), gnutarget, -1); + Don't do it if the sysroot is the target system ("target:"). It + could work in theory, but the lrealpath in build_id_to_debug_bfd_1 + only works with local paths. */ + if (strcmp (gdb_sysroot, TARGET_SYSROOT_PREFIX) != 0) + { + link = gdb_sysroot + link; + debug_bfd = build_id_to_debug_bfd_1 (link, build_id_len, build_id); + if (debug_bfd != NULL) + return debug_bfd; + } + } - if (abfd == NULL) - continue; + return {}; +} - if (build_id_verify (abfd.get(), build_id_len, build_id)) - break; +/* See build-id.h. */ - abfd.release (); - } +gdb_bfd_ref_ptr +build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id) +{ + return build_id_to_bfd_suffix (build_id_len, build_id, ".debug"); +} - return abfd; +/* See build-id.h. */ + +gdb_bfd_ref_ptr +build_id_to_exec_bfd (size_t build_id_len, const bfd_byte *build_id) +{ + return build_id_to_bfd_suffix (build_id_len, build_id, ""); } /* See build-id.h. */ -char * +std::string find_separate_debug_file_by_buildid (struct objfile *objfile) { const struct bfd_build_id *build_id; @@ -157,7 +218,8 @@ find_separate_debug_file_by_buildid (struct objfile *objfile) warning (_("\"%s\": separate debug info file has no debug info"), bfd_get_filename (abfd.get ())); else if (abfd != NULL) - return xstrdup (bfd_get_filename (abfd.get ())); + return std::string (bfd_get_filename (abfd.get ())); } - return NULL; + + return std::string (); }