* dwarf2.c (struct dwarf2_debug): Add fields for handling
alternate debug info source. (dwarf_debug_sections): Add entries for alternate .debug_str and .debug_info sections. (dwarf_debug_section_enum): Likewise. (read_alt_indirect_string): New function. Handles a DW_FORM_GNU_strp_alt attribute. (read_alt_indirect_ref): New function. Handles a DW_FORM_GNU_ref_alt attribute. (read_attribute_value): Process DW_FORM_GNU_ref_alt and DW_FORM_GNU_strp_alt. (find_abstract_instance_name): Handle DW_FORM_GNU_ref_alt attributes. (_bfd_dwarf2_cleanup_debug_info): Free alternate debug info sources. * opncls.c (GNU_DEBUGALTLINK): Define. (bfd_get_alt_debug_link_info): New function. (separate_alt_debug_file_exists): New function. (find_separate_debug_file): Add parameters for fetch and check functions. (bfd_follow_gnu_debugaltlink): New function. * bfd-in2.h: Regenerate.
This commit is contained in:
parent
28439a30ac
commit
95e34fb4f4
4 changed files with 320 additions and 46 deletions
|
@ -1,3 +1,28 @@
|
|||
2013-05-29 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* dwarf2.c (struct dwarf2_debug): Add fields for handling
|
||||
alternate debug info source.
|
||||
(dwarf_debug_sections): Add entries for alternate .debug_str and
|
||||
.debug_info sections.
|
||||
(dwarf_debug_section_enum): Likewise.
|
||||
(read_alt_indirect_string): New function. Handles a
|
||||
DW_FORM_GNU_strp_alt attribute.
|
||||
(read_alt_indirect_ref): New function. Handles a
|
||||
DW_FORM_GNU_ref_alt attribute.
|
||||
(read_attribute_value): Process DW_FORM_GNU_ref_alt and
|
||||
DW_FORM_GNU_strp_alt.
|
||||
(find_abstract_instance_name): Handle DW_FORM_GNU_ref_alt
|
||||
attributes.
|
||||
(_bfd_dwarf2_cleanup_debug_info): Free alternate debug info
|
||||
sources.
|
||||
* opncls.c (GNU_DEBUGALTLINK): Define.
|
||||
(bfd_get_alt_debug_link_info): New function.
|
||||
(separate_alt_debug_file_exists): New function.
|
||||
(find_separate_debug_file): Add parameters for fetch and check
|
||||
functions.
|
||||
(bfd_follow_gnu_debugaltlink): New function.
|
||||
* bfd-in2.h: Regenerate.
|
||||
|
||||
2013-05-28 Yufeng Zhang <yufeng.zhang@arm.com>
|
||||
|
||||
* reloc.c (BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE): Rename to ...
|
||||
|
|
|
@ -1051,8 +1051,12 @@ unsigned long bfd_calc_gnu_debuglink_crc32
|
|||
|
||||
char *bfd_get_debug_link_info (bfd *abfd, unsigned long *crc32_out);
|
||||
|
||||
char *bfd_get_alt_debug_link_info (bfd *abfd, unsigned long *crc32_out);
|
||||
|
||||
char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir);
|
||||
|
||||
char *bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir);
|
||||
|
||||
struct bfd_section *bfd_create_gnu_debuglink_section
|
||||
(bfd *abfd, const char *filename);
|
||||
|
||||
|
|
148
bfd/dwarf2.c
148
bfd/dwarf2.c
|
@ -1,6 +1,5 @@
|
|||
/* DWARF 2 support.
|
||||
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
|
||||
2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
Copyright 1994-2013 Free Software Foundation, Inc.
|
||||
|
||||
Adapted from gdb/dwarf2read.c by Gavin Koch of Cygnus Solutions
|
||||
(gavin@cygnus.com).
|
||||
|
@ -108,6 +107,16 @@ struct dwarf2_debug
|
|||
asection *sec;
|
||||
bfd_byte *sec_info_ptr;
|
||||
|
||||
/* Support for alternate debug info sections created by the DWZ utility:
|
||||
This includes a pointer to an alternate bfd which contains *extra*,
|
||||
possibly duplicate debug sections, and pointers to the loaded
|
||||
.debug_str and .debug_info sections from this bfd. */
|
||||
bfd * alt_bfd_ptr;
|
||||
bfd_byte * alt_dwarf_str_buffer;
|
||||
bfd_size_type alt_dwarf_str_size;
|
||||
bfd_byte * alt_dwarf_info_buffer;
|
||||
bfd_size_type alt_dwarf_info_size;
|
||||
|
||||
/* A pointer to the memory block allocated for info_ptr. Neither
|
||||
info_ptr nor sec_info_ptr are guaranteed to stay pointing to the
|
||||
beginning of the malloc block. This is used only to free the
|
||||
|
@ -290,6 +299,7 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
|
|||
{ ".debug_aranges", ".zdebug_aranges" },
|
||||
{ ".debug_frame", ".zdebug_frame" },
|
||||
{ ".debug_info", ".zdebug_info" },
|
||||
{ ".debug_info", ".zdebug_info" },
|
||||
{ ".debug_line", ".zdebug_line" },
|
||||
{ ".debug_loc", ".zdebug_loc" },
|
||||
{ ".debug_macinfo", ".zdebug_macinfo" },
|
||||
|
@ -300,6 +310,7 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
|
|||
{ ".debug_static_func", ".zdebug_static_func" },
|
||||
{ ".debug_static_vars", ".zdebug_static_vars" },
|
||||
{ ".debug_str", ".zdebug_str", },
|
||||
{ ".debug_str", ".zdebug_str", },
|
||||
{ ".debug_types", ".zdebug_types" },
|
||||
/* GNU DWARF 1 extensions */
|
||||
{ ".debug_sfnames", ".zdebug_sfnames" },
|
||||
|
@ -312,12 +323,15 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
|
|||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
/* NB/ Numbers in this enum must match up with indicies
|
||||
into the dwarf_debug_sections[] array above. */
|
||||
enum dwarf_debug_section_enum
|
||||
{
|
||||
debug_abbrev = 0,
|
||||
debug_aranges,
|
||||
debug_frame,
|
||||
debug_info,
|
||||
debug_info_alt,
|
||||
debug_line,
|
||||
debug_loc,
|
||||
debug_macinfo,
|
||||
|
@ -328,6 +342,7 @@ enum dwarf_debug_section_enum
|
|||
debug_static_func,
|
||||
debug_static_vars,
|
||||
debug_str,
|
||||
debug_str_alt,
|
||||
debug_types,
|
||||
debug_sfnames,
|
||||
debug_srcinfo,
|
||||
|
@ -484,8 +499,8 @@ read_section (bfd * abfd,
|
|||
asection *msec;
|
||||
const char *section_name = sec->uncompressed_name;
|
||||
|
||||
/* read_section is a noop if the section has already been read. */
|
||||
if (!*section_buffer)
|
||||
/* The section may have already been read. */
|
||||
if (*section_buffer == NULL)
|
||||
{
|
||||
msec = bfd_get_section_by_name (abfd, section_name);
|
||||
if (! msec)
|
||||
|
@ -626,6 +641,104 @@ read_indirect_string (struct comp_unit * unit,
|
|||
return str;
|
||||
}
|
||||
|
||||
/* Like read_indirect_string but uses a .debug_str located in
|
||||
an alternate filepointed to by the .gnu_debuglink section.
|
||||
Used to impement DW_FORM_GNU_strp_alt. */
|
||||
|
||||
static char *
|
||||
read_alt_indirect_string (struct comp_unit * unit,
|
||||
bfd_byte * buf,
|
||||
unsigned int * bytes_read_ptr)
|
||||
{
|
||||
bfd_uint64_t offset;
|
||||
struct dwarf2_debug *stash = unit->stash;
|
||||
char *str;
|
||||
|
||||
if (unit->offset_size == 4)
|
||||
offset = read_4_bytes (unit->abfd, buf);
|
||||
else
|
||||
offset = read_8_bytes (unit->abfd, buf);
|
||||
|
||||
*bytes_read_ptr = unit->offset_size;
|
||||
|
||||
if (stash->alt_bfd_ptr == NULL)
|
||||
{
|
||||
bfd * debug_bfd;
|
||||
char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR);
|
||||
|
||||
if (debug_filename == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
|
||||
|| ! bfd_check_format (debug_bfd, bfd_object))
|
||||
{
|
||||
if (debug_bfd)
|
||||
bfd_close (debug_bfd);
|
||||
|
||||
/* FIXME: Should we report our failure to follow the debuglink ? */
|
||||
free (debug_filename);
|
||||
return NULL;
|
||||
}
|
||||
stash->alt_bfd_ptr = debug_bfd;
|
||||
}
|
||||
|
||||
if (! read_section (unit->stash->alt_bfd_ptr,
|
||||
stash->debug_sections + debug_str_alt,
|
||||
NULL, /* FIXME: Do we need to load alternate symbols ? */
|
||||
offset,
|
||||
&stash->alt_dwarf_str_buffer,
|
||||
&stash->alt_dwarf_str_size))
|
||||
return NULL;
|
||||
|
||||
str = (char *) stash->alt_dwarf_str_buffer + offset;
|
||||
if (*str == '\0')
|
||||
return NULL;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/* Resolve an alternate reference from UNIT at OFFSET.
|
||||
Returns a pointer into the loaded alternate CU upon success
|
||||
or NULL upon failure. */
|
||||
|
||||
static bfd_byte *
|
||||
read_alt_indirect_ref (struct comp_unit * unit,
|
||||
bfd_uint64_t offset)
|
||||
{
|
||||
struct dwarf2_debug *stash = unit->stash;
|
||||
|
||||
if (stash->alt_bfd_ptr == NULL)
|
||||
{
|
||||
bfd * debug_bfd;
|
||||
char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR);
|
||||
|
||||
if (debug_filename == NULL)
|
||||
return FALSE;
|
||||
|
||||
if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
|
||||
|| ! bfd_check_format (debug_bfd, bfd_object))
|
||||
{
|
||||
if (debug_bfd)
|
||||
bfd_close (debug_bfd);
|
||||
|
||||
/* FIXME: Should we report our failure to follow the debuglink ? */
|
||||
free (debug_filename);
|
||||
return NULL;
|
||||
}
|
||||
stash->alt_bfd_ptr = debug_bfd;
|
||||
}
|
||||
|
||||
if (! read_section (unit->stash->alt_bfd_ptr,
|
||||
stash->debug_sections + debug_info_alt,
|
||||
NULL, /* FIXME: Do we need to load alternate symbols ? */
|
||||
offset,
|
||||
&stash->alt_dwarf_info_buffer,
|
||||
&stash->alt_dwarf_info_size))
|
||||
return NULL;
|
||||
|
||||
return stash->alt_dwarf_info_buffer + offset;
|
||||
}
|
||||
|
||||
static bfd_uint64_t
|
||||
read_address (struct comp_unit *unit, bfd_byte *buf)
|
||||
{
|
||||
|
@ -829,6 +942,7 @@ read_attribute_value (struct attribute *attr,
|
|||
attr->u.val = read_address (unit, info_ptr);
|
||||
info_ptr += unit->addr_size;
|
||||
break;
|
||||
case DW_FORM_GNU_ref_alt:
|
||||
case DW_FORM_sec_offset:
|
||||
if (unit->offset_size == 4)
|
||||
attr->u.val = read_4_bytes (unit->abfd, info_ptr);
|
||||
|
@ -878,6 +992,10 @@ read_attribute_value (struct attribute *attr,
|
|||
attr->u.str = read_indirect_string (unit, info_ptr, &bytes_read);
|
||||
info_ptr += bytes_read;
|
||||
break;
|
||||
case DW_FORM_GNU_strp_alt:
|
||||
attr->u.str = read_alt_indirect_string (unit, info_ptr, &bytes_read);
|
||||
info_ptr += bytes_read;
|
||||
break;
|
||||
case DW_FORM_exprloc:
|
||||
case DW_FORM_block:
|
||||
amt = sizeof (struct dwarf_block);
|
||||
|
@ -950,7 +1068,7 @@ read_attribute_value (struct attribute *attr,
|
|||
info_ptr = read_attribute_value (attr, form, unit, info_ptr);
|
||||
break;
|
||||
default:
|
||||
(*_bfd_error_handler) (_("Dwarf Error: Invalid or unhandled FORM value: %u."),
|
||||
(*_bfd_error_handler) (_("Dwarf Error: Invalid or unhandled FORM value: %#x."),
|
||||
form);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return NULL;
|
||||
|
@ -1996,7 +2114,7 @@ find_abstract_instance_name (struct comp_unit *unit,
|
|||
struct abbrev_info *abbrev;
|
||||
bfd_uint64_t die_ref = attr_ptr->u.val;
|
||||
struct attribute attr;
|
||||
char *name = 0;
|
||||
char *name = NULL;
|
||||
|
||||
/* DW_FORM_ref_addr can reference an entry in a different CU. It
|
||||
is an offset from the .debug_info section, not the current CU. */
|
||||
|
@ -2009,8 +2127,20 @@ find_abstract_instance_name (struct comp_unit *unit,
|
|||
|
||||
info_ptr = unit->sec_info_ptr + die_ref;
|
||||
}
|
||||
else if (attr_ptr->form == DW_FORM_GNU_ref_alt)
|
||||
{
|
||||
info_ptr = read_alt_indirect_ref (unit, die_ref);
|
||||
if (info_ptr == NULL)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("Dwarf Error: Unable to read alt ref %u."), die_ref);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
else
|
||||
info_ptr = unit->info_ptr_unit + die_ref;
|
||||
|
||||
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
||||
info_ptr += bytes_read;
|
||||
|
||||
|
@ -3694,4 +3824,10 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd, void **pinfo)
|
|||
free (stash->info_ptr_memory);
|
||||
if (stash->close_on_cleanup)
|
||||
bfd_close (stash->bfd_ptr);
|
||||
if (stash->alt_dwarf_str_buffer)
|
||||
free (stash->alt_dwarf_str_buffer);
|
||||
if (stash->alt_dwarf_info_buffer)
|
||||
free (stash->alt_dwarf_info_buffer);
|
||||
if (stash->alt_bfd_ptr)
|
||||
bfd_close (stash->alt_bfd_ptr);
|
||||
}
|
||||
|
|
189
bfd/opncls.c
189
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
|
||||
<<NULL>> 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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue