X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Fopncls.c;h=cd9c826dd4bcf9989dc040d143d5c2feed8a7b76;hb=95e34fb4f43f5cc57c48d4799c5c59d7dcf6c2a2;hp=3879a65338ce9f784fa59862f15c7789b304593f;hpb=a253d456e1c74d11503d31fe813da7eeeceed338;p=binutils-gdb.git diff --git a/bfd/opncls.c b/bfd/opncls.c index 3879a65338c..cd9c826dd4b 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -1048,10 +1048,11 @@ bfd_release (bfd *abfd, void *block) This facilitates "optional" provision of debugging information, without having to provide two complete copies of every binary object (with and - without debug symbols). -*/ + without debug symbols). */ + +#define GNU_DEBUGLINK ".gnu_debuglink" +#define GNU_DEBUGALTLINK ".gnu_debugaltlink" -#define GNU_DEBUGLINK ".gnu_debuglink" /* FUNCTION bfd_calc_gnu_debuglink_crc32 @@ -1188,6 +1189,54 @@ bfd_get_debug_link_info (bfd *abfd, unsigned long *crc32_out) return name; } +/* +FUNCTION + bfd_get_alt_debug_link_info + +SYNOPSIS + char *bfd_get_alt_debug_link_info (bfd *abfd, unsigned long *crc32_out); + +DESCRIPTION + Fetch the filename and BuildID value for any alternate debuginfo + associated with @var{abfd}. Return NULL if no such info found, + otherwise return filename and update @var{buildid_out}. The + returned filename is allocated with @code{malloc}; freeing it + is the responsibility of the caller. +*/ + +char * +bfd_get_alt_debug_link_info (bfd * abfd, unsigned long * buildid_out) +{ + asection *sect; + bfd_byte *contents; + int buildid_offset; + char *name; + + BFD_ASSERT (abfd); + BFD_ASSERT (buildid_out); + + sect = bfd_get_section_by_name (abfd, GNU_DEBUGALTLINK); + + if (sect == NULL) + return NULL; + + if (!bfd_malloc_and_get_section (abfd, sect, & contents)) + { + if (contents != NULL) + free (contents); + return NULL; + } + + /* BuildID value is stored after the filename, aligned up to 4 bytes. */ + name = (char *) contents; + buildid_offset = strlen (name) + 1; + buildid_offset = (buildid_offset + 3) & ~3; + + * buildid_out = bfd_get_32 (abfd, contents + buildid_offset); + + return name; +} + /* INTERNAL_FUNCTION separate_debug_file_exists @@ -1223,6 +1272,37 @@ separate_debug_file_exists (const char *name, const unsigned long crc) return crc == file_crc; } +/* +INTERNAL_FUNCTION + separate_alt_debug_file_exists + +SYNOPSIS + bfd_boolean separate_alt_debug_file_exists + (char *name, unsigned long crc32); + +DESCRIPTION + Checks to see if @var{name} is a file and if its BuildID + matches @var{buildid}. +*/ + +static bfd_boolean +separate_alt_debug_file_exists (const char *name, + const unsigned long buildid ATTRIBUTE_UNUSED) +{ + FILE *f; + + BFD_ASSERT (name); + + f = real_fopen (name, FOPEN_RB); + if (f == NULL) + return FALSE; + + /* FIXME: Add code to check buildid. */ + + fclose (f); + + return TRUE; +} /* INTERNAL_FUNCTION @@ -1232,16 +1312,24 @@ SYNOPSIS char *find_separate_debug_file (bfd *abfd); DESCRIPTION - Searches @var{abfd} for a reference to separate debugging - information, scans various locations in the filesystem, including - the file tree rooted at @var{debug_file_directory}, and returns a - filename of such debugging information if the file is found and has - matching CRC32. Returns NULL if no reference to debugging file - exists, or file cannot be found. + Searches @var{abfd} for a section called @var{section_name} which + is expected to contain a reference to a file containing separate + debugging information. The function scans various locations in + the filesystem, including the file tree rooted at + @var{debug_file_directory}, and returns the first matching + filename that it finds. If @var{check_crc} is TRUE then the + contents of the file must also match the CRC value contained in + @var{section_name}. Returns NULL if no valid file could be found. */ +typedef char * (* get_func_type) (bfd *, unsigned long *); +typedef bfd_boolean (* check_func_type) (const char *, const unsigned long); + static char * -find_separate_debug_file (bfd *abfd, const char *debug_file_directory) +find_separate_debug_file (bfd * abfd, + const char * debug_file_directory, + get_func_type get_func, + check_func_type check_func) { char *base; char *dir; @@ -1262,7 +1350,8 @@ find_separate_debug_file (bfd *abfd, const char *debug_file_directory) return NULL; } - base = bfd_get_debug_link_info (abfd, & crc32); + base = get_func (abfd, & crc32); + if (base == NULL) return NULL; @@ -1301,37 +1390,22 @@ find_separate_debug_file (bfd *abfd, const char *debug_file_directory) + strlen (base) + 1); if (debugfile == NULL) - { - free (base); - free (dir); - free (canon_dir); - return NULL; - } + goto found; /* Actually this returns NULL. */ /* First try in the same directory as the original file: */ strcpy (debugfile, dir); strcat (debugfile, base); - if (separate_debug_file_exists (debugfile, crc32)) - { - free (base); - free (dir); - free (canon_dir); - return debugfile; - } + if (check_func (debugfile, crc32)) + goto found; /* Then try in a subdirectory called .debug. */ strcpy (debugfile, dir); strcat (debugfile, ".debug/"); strcat (debugfile, base); - if (separate_debug_file_exists (debugfile, crc32)) - { - free (base); - free (dir); - free (canon_dir); - return debugfile; - } + if (check_func (debugfile, crc32)) + goto found; /* Then try in the global debugfile directory. */ strcpy (debugfile, debug_file_directory); @@ -1343,19 +1417,18 @@ find_separate_debug_file (bfd *abfd, const char *debug_file_directory) strcat (debugfile, canon_dir); strcat (debugfile, base); - if (separate_debug_file_exists (debugfile, crc32)) - { - free (base); - free (dir); - free (canon_dir); - return debugfile; - } + if (check_func (debugfile, crc32)) + goto found; + /* Failed to find the file. */ free (debugfile); + debugfile = NULL; + + found: free (base); free (dir); free (canon_dir); - return NULL; + return debugfile; } @@ -1388,7 +1461,43 @@ RETURNS char * bfd_follow_gnu_debuglink (bfd *abfd, const char *dir) { - return find_separate_debug_file (abfd, dir); + return find_separate_debug_file (abfd, dir, + bfd_get_debug_link_info, + separate_debug_file_exists); +} + +/* +FUNCTION + bfd_follow_gnu_debugaltlink + +SYNOPSIS + char *bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir); + +DESCRIPTION + + Takes a BFD and searches it for a .gnu_debugaltlink section. If this + section is found, it examines the section for the name of a file + containing auxiliary debugging information. It then searches the + filesystem for this file in a set of standard locations, including + the directory tree rooted at @var{dir}, and if found returns the + full filename. + + If @var{dir} is NULL, it will search a default path configured into + libbfd at build time. [FIXME: This feature is not currently + implemented]. + +RETURNS + <> on any errors or failure to locate the debug file, + otherwise a pointer to a heap-allocated string containing the + filename. The caller is responsible for freeing this string. +*/ + +char * +bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir) +{ + return find_separate_debug_file (abfd, dir, + bfd_get_alt_debug_link_info, + separate_alt_debug_file_exists); } /*