[binutils/f19] Add support for the alternative debuging files generated by the DWZ program. Resolves: #965255
Nicholas Clifton
nickc at fedoraproject.org
Tue Jun 4 15:14:22 UTC 2013
commit 7c13ae2cad9300c924cd343b76c6709f8cbb0d50
Author: Nick Clifton <nickc at redhat.com>
Date: Tue Jun 4 16:12:57 2013 +0100
Add support for the alternative debuging files generated by the DWZ program.
Resolves: #965255
binutils-2.23.52.0.1-dwz-alt-debuginfo.patch | 611 ++++++++++++++++++++++++++
binutils.spec | 8 +-
2 files changed, 618 insertions(+), 1 deletions(-)
---
diff --git a/binutils-2.23.52.0.1-dwz-alt-debuginfo.patch b/binutils-2.23.52.0.1-dwz-alt-debuginfo.patch
new file mode 100644
index 0000000..5f48e7f
--- /dev/null
+++ b/binutils-2.23.52.0.1-dwz-alt-debuginfo.patch
@@ -0,0 +1,611 @@
+diff -cp ../binutils-2.23.52.0.1.orig/bfd/bfd-in2.h bfd/bfd-in2.h
+*** ../binutils-2.23.52.0.1.orig/bfd/bfd-in2.h 2013-06-04 15:26:45.127450022 +0100
+--- bfd/bfd-in2.h 2013-06-04 15:47:45.160484950 +0100
+*************** void *bfd_zalloc (bfd *abfd, bfd_size_ty
+*** 1044,1051 ****
+--- 1044,1055 ----
+ unsigned long bfd_calc_gnu_debuglink_crc32
+ (unsigned long crc, const unsigned char *buf, bfd_size_type len);
+
++ 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);
+
+diff -cp ../binutils-2.23.52.0.1.orig/bfd/dwarf2.c bfd/dwarf2.c
+*** ../binutils-2.23.52.0.1.orig/bfd/dwarf2.c 2013-06-04 15:26:44.556450006 +0100
+--- bfd/dwarf2.c 2013-06-04 15:49:24.921487716 +0100
+*************** struct dwarf2_debug
+*** 108,113 ****
+--- 108,123 ----
+ 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
+*************** const struct dwarf_debug_section dwarf_d
+*** 290,295 ****
+--- 300,306 ----
+ { ".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" },
+*************** const struct dwarf_debug_section dwarf_d
+*** 300,305 ****
+--- 311,317 ----
+ { ".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" },
+*************** const struct dwarf_debug_section dwarf_d
+*** 312,323 ****
+--- 324,338 ----
+ { 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,
+*************** enum dwarf_debug_section_enum
+*** 328,333 ****
+--- 343,349 ----
+ debug_static_func,
+ debug_static_vars,
+ debug_str,
++ debug_str_alt,
+ debug_types,
+ debug_sfnames,
+ debug_srcinfo,
+*************** read_section (bfd * abfd,
+*** 484,491 ****
+ asection *msec;
+ const char *section_name = sec->uncompressed_name;
+
+! /* read_section is a noop if the section has already been read. */
+! if (!*section_buffer)
+ {
+ msec = bfd_get_section_by_name (abfd, section_name);
+ if (! msec)
+--- 500,507 ----
+ asection *msec;
+ const char *section_name = sec->uncompressed_name;
+
+! /* The section may have already been read. */
+! if (*section_buffer == NULL)
+ {
+ msec = bfd_get_section_by_name (abfd, section_name);
+ if (! msec)
+*************** read_indirect_string (struct comp_unit *
+*** 626,631 ****
+--- 642,745 ----
+ 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)
+ {
+*************** read_attribute_value (struct attribute *
+*** 829,834 ****
+--- 943,949 ----
+ 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);
+*************** read_attribute_value (struct attribute *
+*** 878,883 ****
+--- 993,1002 ----
+ 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);
+*************** find_abstract_instance_name (struct comp
+*** 2009,2014 ****
+--- 2128,2144 ----
+
+ 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);
+*************** _bfd_dwarf2_cleanup_debug_info (bfd *abf
+*** 3692,3697 ****
+--- 3822,3833 ----
+ free (stash->dwarf_ranges_buffer);
+ if (stash->info_ptr_memory)
+ free (stash->info_ptr_memory);
++ 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);
+ if (stash->close_on_cleanup)
+ bfd_close (stash->bfd_ptr);
+ }
+diff -cp ../binutils-2.23.52.0.1.orig/bfd/opncls.c bfd/opncls.c
+*** ../binutils-2.23.52.0.1.orig/bfd/opncls.c 2013-06-04 15:26:43.723449983 +0100
+--- bfd/opncls.c 2013-06-04 15:47:45.183484951 +0100
+*************** bfd_release (bfd *abfd, void *block)
+*** 1049,1058 ****
+
+ This facilitates "optional" provision of debugging information, without
+ having to provide two complete copies of every binary object (with and
+! without debug symbols).
+! */
+
+- #define GNU_DEBUGLINK ".gnu_debuglink"
+ /*
+ FUNCTION
+ bfd_calc_gnu_debuglink_crc32
+--- 1049,1059 ----
+
+ This facilitates "optional" provision of debugging information, without
+ having to provide two complete copies of every binary object (with and
+! without debug symbols). */
+!
+! #define GNU_DEBUGLINK ".gnu_debuglink"
+! #define GNU_DEBUGALTLINK ".gnu_debugaltlink"
+
+ /*
+ FUNCTION
+ bfd_calc_gnu_debuglink_crc32
+*************** get_debug_link_info (bfd *abfd, unsigned
+*** 1188,1193 ****
+--- 1189,1242 ----
+ }
+
+ /*
++ 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
+
+*************** separate_debug_file_exists (const char *
+*** 1222,1227 ****
+--- 1271,1307 ----
+ 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
+*************** SYNOPSIS
+*** 1231,1246 ****
+ 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.
+ */
+
+ static char *
+! find_separate_debug_file (bfd *abfd, const char *debug_file_directory)
+ {
+ char *base;
+ char *dir;
+--- 1311,1334 ----
+ char *find_separate_debug_file (bfd *abfd);
+
+ DESCRIPTION
+! 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,
+! get_func_type get_func,
+! check_func_type check_func)
+ {
+ char *base;
+ char *dir;
+*************** find_separate_debug_file (bfd *abfd, con
+*** 1261,1267 ****
+ return NULL;
+ }
+
+! base = get_debug_link_info (abfd, & crc32);
+ if (base == NULL)
+ return NULL;
+
+--- 1349,1355 ----
+ return NULL;
+ }
+
+! base = get_func (abfd, & crc32);
+ if (base == NULL)
+ return NULL;
+
+*************** find_separate_debug_file (bfd *abfd, con
+*** 1300,1336 ****
+ + strlen (base)
+ + 1);
+ if (debugfile == NULL)
+! {
+! free (base);
+! free (dir);
+! free (canon_dir);
+! return 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;
+! }
+
+ /* 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;
+! }
+
+ /* Then try in the global debugfile directory. */
+ strcpy (debugfile, debug_file_directory);
+--- 1388,1409 ----
+ + strlen (base)
+ + 1);
+ if (debugfile == NULL)
+! goto found; /* Actually this returns NULL. */
+
+ /* First try in the same directory as the original file: */
+ strcpy (debugfile, dir);
+ strcat (debugfile, base);
+
+! if (check_func (debugfile, crc32))
+! goto found;
+
+ /* Then try in a subdirectory called .debug. */
+ strcpy (debugfile, dir);
+ strcat (debugfile, ".debug/");
+ strcat (debugfile, base);
+
+! if (check_func (debugfile, crc32))
+! goto found;
+
+ /* Then try in the global debugfile directory. */
+ strcpy (debugfile, debug_file_directory);
+*************** find_separate_debug_file (bfd *abfd, con
+*** 1342,1360 ****
+ strcat (debugfile, canon_dir);
+ strcat (debugfile, base);
+
+! if (separate_debug_file_exists (debugfile, crc32))
+! {
+! free (base);
+! free (dir);
+! free (canon_dir);
+! return debugfile;
+! }
+
+ free (debugfile);
+ free (base);
+ free (dir);
+ free (canon_dir);
+! return NULL;
+ }
+
+
+--- 1415,1432 ----
+ strcat (debugfile, canon_dir);
+ strcat (debugfile, base);
+
+! 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 debugfile;
+ }
+
+
+*************** RETURNS
+*** 1387,1393 ****
+ char *
+ bfd_follow_gnu_debuglink (bfd *abfd, const char *dir)
+ {
+! return find_separate_debug_file (abfd, dir);
+ }
+
+ /*
+--- 1459,1501 ----
+ char *
+ bfd_follow_gnu_debuglink (bfd *abfd, const char *dir)
+ {
+! return find_separate_debug_file (abfd, dir,
+! 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);
+ }
+
+ /*
diff --git a/binutils.spec b/binutils.spec
index 6690fd4..4571352 100644
--- a/binutils.spec
+++ b/binutils.spec
@@ -17,7 +17,7 @@
Summary: A GNU collection of binary utilities
Name: %{?cross}binutils%{?_with_debug:-debug}
Version: 2.23.52.0.1
-Release: 8%{?dist}
+Release: 9%{?dist}
License: GPLv3+
Group: Development/Tools
URL: http://sources.redhat.com/binutils
@@ -50,6 +50,8 @@ Patch13: binutils-2.23.52.0.1-revert-pr15149.patch
Patch14: binutils-2.23.52.0.1-aarch64-lib64.patch
# Check regular references without non-GOT references when building shared libraries.
Patch15: binutils-2.23.52.0.1-check-regular-ifunc-refs.patch
+# Add support to BFD library for debug information held in alternate files.
+Patch16: binutils-2.23.52.0.1-dwz-alt-debuginfo.patch
Provides: bundled(libiberty)
@@ -163,6 +165,7 @@ using libelf instead of BFD.
%patch13 -p0 -b .revert-pr15149~
%patch14 -p0 -b .aarch64-lib64~
%patch15 -p0 -b .check-ifunc~
+%patch16 -p0 -b .dwz~
# We cannot run autotools as there is an exact requirement of autoconf-2.59.
@@ -462,6 +465,9 @@ exit 0
%endif # %{isnative}
%changelog
+* Tue Jun 04 2013 Nick Clifton <nickc at redhat.com> - 2.23.52.0.1-9
+- Add support for the alternative debuging files generated by the DWZ program. (#965255)
+
* Wed Apr 17 2013 Nick Clifton <nickc at redhat.com> - 2.23.52.0.1-8
- Import patch for FSF mainline PR 15371 to fix ifunc references in shared libraries. (#927818)
More information about the scm-commits
mailing list