This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][libbacktrace] Handle DW_FORM_GNU_strp_alt


Hi,

The dwz tool attempts to optimize DWARF debugging information contained in ELF
shared libraries and ELF executables for size.

With the dwz -m option, it attempts to optimize by moving DWARF debugging
information entries (DIEs), strings and macro descriptions duplicated in
more than one object into a newly created ELF ET_REL object whose filename is
given as -m option argument.  The debug sections in the executables and
shared libraries specified on the command line are then modified again,
referring to the entities in the newly created object.

After a dwz invocation:
...
$ dwz -m c.debug a.out b.out
...
both a.out and b.out contain a .gnu_debugaltlink section referring to c.debug,
and use "DWZ DWARF multifile extensions" such as DW_FORM_GNU_strp_alt and
DW_FORM_GNU_ref_alt refer to the content of c.debug.

The .gnu_debugaltlink consists of a filename and the expected buildid.

This patch adds to libbacktrace:
- finding a file matching the .gnu_debugaltlink filename
- verifying the .gnu_debugaltlink buildid
- reading the dwarf of the .gnu_debugaltlink
- support for FORM_GNU_strp_alt
- a testcase btest_dwz.c, which is btest.c minimized to the point that it only
  requires FORM_GNU_strp_alt.

Bootstrapped and reg-tested on x86_64.

OK for trunk?

Thanks,
- Tom

[libbacktrace] Handle DW_FORM_GNU_strp_alt

2018-11-11  Tom de Vries  <tdevries@suse.de>

	* dwarf.c (struct dwarf_data): Add altlink field.
	(read_attribute): Add altlink parameter.  Handle DW_FORM_GNU_strp_alt
	using altlink.
	(find_address_ranges, build_address_map, build_dwarf_data): Add and
	handle altlink parameter.
	(read_referenced_name, read_function_entry): Add argument to
	read_attribute call.
	(backtrace_dwarf_add): Add and handle fileline_entry and
	fileline_altlink parameters.
	* elf.c (elf_open_debugfile_by_debugaltlink): New function.
	(elf_add): Add and handle fileline_entry, with_buildid_data and
	with_buildid_size parameters.  Handle .gnu_debugaltlink section.
	(phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
	* internal.h (backtrace_dwarf_add): Add fileline_entry and
	fileline_altlink parameters.
	* configure.ac (DWZ): Set with AC_CHECK_PROG.
	(HAVE_DWZ): Set with AM_CONDITIONAL.
	* configure: Regenerate.
	* Makefile.am (check_PROGRAMS): Add btest_dwz.
	(TESTS): Add btest_dwz_2 and btest_dwz_3.
	* Makefile.in: Regenerate.
	* btest_dwz.c: New file.

---
 libbacktrace/Makefile.am  |  22 +++++
 libbacktrace/Makefile.in  |  95 ++++++++++++++++---
 libbacktrace/btest_dwz.c  | 237 ++++++++++++++++++++++++++++++++++++++++++++++
 libbacktrace/configure    |  57 ++++++++++-
 libbacktrace/configure.ac |   3 +
 libbacktrace/dwarf.c      |  50 +++++++---
 libbacktrace/elf.c        | 120 +++++++++++++++++++++--
 libbacktrace/internal.h   |   4 +-
 8 files changed, 548 insertions(+), 40 deletions(-)

diff --git a/libbacktrace/Makefile.am b/libbacktrace/Makefile.am
index 3c1bd49dd7b..2fec9bbb4b6 100644
--- a/libbacktrace/Makefile.am
+++ b/libbacktrace/Makefile.am
@@ -96,6 +96,28 @@ btest_LDADD = libbacktrace.la
 
 check_PROGRAMS += btest
 
+if HAVE_DWZ
+
+btest_dwz_SOURCES = btest_dwz.c testlib.c
+btest_dwz_CFLAGS = $(AM_CFLAGS) -g -O0
+btest_dwz_LDADD = libbacktrace.la
+
+check_PROGRAMS += btest_dwz
+
+TESTS += btest_dwz_2 btest_dwz_3
+
+btest_dwz_2 btest_dwz_3: btest_dwz_23
+
+.PHONY: btest_dwz_23
+
+btest_dwz_23: btest_dwz
+	rm -f btest_dwz.debug
+	cp btest_dwz btest_dwz_2
+	cp btest_dwz btest_dwz_3
+	$(DWZ) -m btest_dwz.debug btest_dwz_2 btest_dwz_3
+
+endif HAVE_DWZ
+
 stest_SOURCES = stest.c
 stest_LDADD = libbacktrace.la
 
diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index 60a9d887dba..b3e9b9a4eec 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -120,12 +120,16 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
-check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
-@NATIVE_TRUE@am__append_1 = btest stest ztest edtest
-@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_2 = -lz
-@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_3 = ttest
-@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_4 = dtest
-@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_5 = ctestg ctesta
+check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
+	$(am__EXEEXT_4) $(am__EXEEXT_5)
+@NATIVE_TRUE@am__append_1 = btest
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_2 = btest_dwz
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_3 = btest_dwz_2 btest_dwz_3
+@NATIVE_TRUE@am__append_4 = stest ztest edtest
+@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_5 = -lz
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_6 = ttest
+@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_7 = dtest
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_8 = ctestg ctesta
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/cet.m4 \
@@ -158,10 +162,12 @@ AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
 am__v_lt_0 = --silent
 am__v_lt_1 = 
-@NATIVE_TRUE@am__EXEEXT_1 = btest$(EXEEXT) stest$(EXEEXT) \
-@NATIVE_TRUE@	ztest$(EXEEXT) edtest$(EXEEXT)
-@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__EXEEXT_2 = ttest$(EXEEXT)
-@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__EXEEXT_3 =  \
+@NATIVE_TRUE@am__EXEEXT_1 = btest$(EXEEXT)
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__EXEEXT_2 = btest_dwz$(EXEEXT)
+@NATIVE_TRUE@am__EXEEXT_3 = stest$(EXEEXT) ztest$(EXEEXT) \
+@NATIVE_TRUE@	edtest$(EXEEXT)
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__EXEEXT_4 = ttest$(EXEEXT)
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__EXEEXT_5 =  \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctestg$(EXEEXT) \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctesta$(EXEEXT)
 @NATIVE_TRUE@am_btest_OBJECTS = btest-btest.$(OBJEXT) \
@@ -171,6 +177,14 @@ btest_OBJECTS = $(am_btest_OBJECTS)
 btest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(btest_CFLAGS) $(CFLAGS) \
 	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am_btest_dwz_OBJECTS =  \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	btest_dwz-btest_dwz.$(OBJEXT) \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	btest_dwz-testlib.$(OBJEXT)
+btest_dwz_OBJECTS = $(am_btest_dwz_OBJECTS)
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@btest_dwz_DEPENDENCIES = libbacktrace.la
+btest_dwz_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(btest_dwz_CFLAGS) \
+	$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am_ctesta_OBJECTS = ctesta-btest.$(OBJEXT) \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctesta-testlib.$(OBJEXT)
 ctesta_OBJECTS = $(am_ctesta_OBJECTS)
@@ -244,9 +258,9 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
 SOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \
-	$(btest_SOURCES) $(ctesta_SOURCES) $(ctestg_SOURCES) \
-	$(edtest_SOURCES) $(stest_SOURCES) $(ttest_SOURCES) \
-	$(ztest_SOURCES)
+	$(btest_SOURCES) $(btest_dwz_SOURCES) $(ctesta_SOURCES) \
+	$(ctestg_SOURCES) $(edtest_SOURCES) $(stest_SOURCES) \
+	$(ttest_SOURCES) $(ztest_SOURCES)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -500,6 +514,7 @@ CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DSYMUTIL = @DSYMUTIL@
 DUMPBIN = @DUMPBIN@
+DWZ = @DWZ@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
 ECHO_T = @ECHO_T@
@@ -654,15 +669,18 @@ libbacktrace_la_LIBADD = \
 	$(ALLOC_FILE)
 
 libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
-TESTS = $(check_PROGRAMS) $(am__append_4)
+TESTS = $(check_PROGRAMS) $(am__append_3) $(am__append_7)
 @NATIVE_TRUE@btest_SOURCES = btest.c testlib.c
 @NATIVE_TRUE@btest_CFLAGS = $(AM_CFLAGS) -g -O
 @NATIVE_TRUE@btest_LDADD = libbacktrace.la
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@btest_dwz_SOURCES = btest_dwz.c testlib.c
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@btest_dwz_CFLAGS = $(AM_CFLAGS) -g -O0
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@btest_dwz_LDADD = libbacktrace.la
 @NATIVE_TRUE@stest_SOURCES = stest.c
 @NATIVE_TRUE@stest_LDADD = libbacktrace.la
 @NATIVE_TRUE@ztest_SOURCES = ztest.c testlib.c
 @NATIVE_TRUE@ztest_CFLAGS = -DSRCDIR=\"$(srcdir)\"
-@NATIVE_TRUE@ztest_LDADD = libbacktrace.la $(am__append_2) \
+@NATIVE_TRUE@ztest_LDADD = libbacktrace.la $(am__append_5) \
 @NATIVE_TRUE@	$(CLOCK_GETTIME_LINK)
 @NATIVE_TRUE@edtest_SOURCES = edtest.c edtest2_build.c testlib.c
 @NATIVE_TRUE@edtest_LDADD = libbacktrace.la
@@ -780,6 +798,10 @@ btest$(EXEEXT): $(btest_OBJECTS) $(btest_DEPENDENCIES) $(EXTRA_btest_DEPENDENCIE
 	@rm -f btest$(EXEEXT)
 	$(AM_V_CCLD)$(btest_LINK) $(btest_OBJECTS) $(btest_LDADD) $(LIBS)
 
+btest_dwz$(EXEEXT): $(btest_dwz_OBJECTS) $(btest_dwz_DEPENDENCIES) $(EXTRA_btest_dwz_DEPENDENCIES) 
+	@rm -f btest_dwz$(EXEEXT)
+	$(AM_V_CCLD)$(btest_dwz_LINK) $(btest_dwz_OBJECTS) $(btest_dwz_LDADD) $(LIBS)
+
 ctesta$(EXEEXT): $(ctesta_OBJECTS) $(ctesta_DEPENDENCIES) $(EXTRA_ctesta_DEPENDENCIES) 
 	@rm -f ctesta$(EXEEXT)
 	$(AM_V_CCLD)$(ctesta_LINK) $(ctesta_OBJECTS) $(ctesta_LDADD) $(LIBS)
@@ -831,6 +853,18 @@ btest-testlib.o: testlib.c
 btest-testlib.obj: testlib.c
 	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
 
+btest_dwz-btest_dwz.o: btest_dwz.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_dwz_CFLAGS) $(CFLAGS) -c -o btest_dwz-btest_dwz.o `test -f 'btest_dwz.c' || echo '$(srcdir)/'`btest_dwz.c
+
+btest_dwz-btest_dwz.obj: btest_dwz.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_dwz_CFLAGS) $(CFLAGS) -c -o btest_dwz-btest_dwz.obj `if test -f 'btest_dwz.c'; then $(CYGPATH_W) 'btest_dwz.c'; else $(CYGPATH_W) '$(srcdir)/btest_dwz.c'; fi`
+
+btest_dwz-testlib.o: testlib.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_dwz_CFLAGS) $(CFLAGS) -c -o btest_dwz-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c
+
+btest_dwz-testlib.obj: testlib.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_dwz_CFLAGS) $(CFLAGS) -c -o btest_dwz-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
+
 ctesta-btest.o: btest.c
 	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_CFLAGS) $(CFLAGS) -c -o ctesta-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c
 
@@ -1095,6 +1129,13 @@ btest.log: btest$(EXEEXT)
 	--log-file $$b.log --trs-file $$b.trs \
 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
+btest_dwz.log: btest_dwz$(EXEEXT)
+	@p='btest_dwz$(EXEEXT)'; \
+	b='btest_dwz'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
 stest.log: stest$(EXEEXT)
 	@p='stest$(EXEEXT)'; \
 	b='stest'; \
@@ -1137,6 +1178,20 @@ ctesta.log: ctesta$(EXEEXT)
 	--log-file $$b.log --trs-file $$b.trs \
 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
+btest_dwz_2.log: btest_dwz_2
+	@p='btest_dwz_2'; \
+	b='btest_dwz_2'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+btest_dwz_3.log: btest_dwz_3
+	@p='btest_dwz_3'; \
+	b='btest_dwz_3'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
 dtest.log: dtest
 	@p='dtest'; \
 	b='dtest'; \
@@ -1292,6 +1347,16 @@ uninstall-am:
 .PRECIOUS: Makefile
 
 
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@btest_dwz_2 btest_dwz_3: btest_dwz_23
+
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@.PHONY: btest_dwz_23
+
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@btest_dwz_23: btest_dwz
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	rm -f btest_dwz.debug
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	cp btest_dwz btest_dwz_2
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	cp btest_dwz btest_dwz_3
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	$(DWZ) -m btest_dwz.debug btest_dwz_2 btest_dwz_3
+
 @NATIVE_TRUE@edtest2_build.c: gen_edtest2_build; @true
 @NATIVE_TRUE@gen_edtest2_build: $(srcdir)/edtest2.c
 @NATIVE_TRUE@	cat $(srcdir)/edtest2.c > tmp-edtest2_build.c
diff --git a/libbacktrace/btest_dwz.c b/libbacktrace/btest_dwz.c
new file mode 100644
index 00000000000..bda6c75cb98
--- /dev/null
+++ b/libbacktrace/btest_dwz.c
@@ -0,0 +1,237 @@
+/* btest.c -- Test for libbacktrace library
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+/* This program tests the externally visible interfaces of the
+   libbacktrace library.  */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "filenames.h"
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+
+#include "testlib.h"
+
+#define FILE "btest_dwz.c"
+
+/* Test the backtrace_simple function with non-inlined functions.  */
+
+static int test3 (void) __attribute__ ((noinline, unused));
+static int f22 (int) __attribute__ ((noinline));
+static int f23 (int, int) __attribute__ ((noinline));
+
+static int
+test3 (void)
+{
+  return f22 (__LINE__) + 1;
+}
+
+static int
+f22 (int f1line)
+{
+  return f23 (f1line, __LINE__) + 2;
+}
+
+static int
+f23 (int f1line, int f2line)
+{
+  uintptr_t addrs[20];
+  struct sdata data;
+  int f3line;
+  int i;
+
+  data.addrs = &addrs[0];
+  data.index = 0;
+  data.max = 20;
+  data.failed = 0;
+
+  f3line = __LINE__ + 1;
+  i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
+
+  if (i != 0)
+    {
+      fprintf (stderr, "test3: unexpected return value %d\n", i);
+      data.failed = 1;
+    }
+
+  if (!data.failed)
+    {
+      struct info all[20];
+      struct bdata bdata;
+      int j;
+
+      bdata.all = &all[0];
+      bdata.index = 0;
+      bdata.max = 20;
+      bdata.failed = 0;
+
+      for (j = 0; j < 3; ++j)
+	{
+	  i = backtrace_pcinfo (state, addrs[j], callback_one,
+				error_callback_one, &bdata);
+	  if (i != 0)
+	    {
+	      fprintf (stderr,
+		       ("test3: unexpected return value "
+			"from backtrace_pcinfo %d\n"),
+		       i);
+	      bdata.failed = 1;
+	    }
+	  if (!bdata.failed && bdata.index != (size_t) (j + 1))
+	    {
+	      fprintf (stderr,
+		       ("wrong number of calls from backtrace_pcinfo "
+			"got %u expected %d\n"),
+		       (unsigned int) bdata.index, j + 1);
+	      bdata.failed = 1;
+	    }
+	}
+
+      //check ("test3", 0, all, f3line, "f23", FILE, &bdata.failed);
+      (void)f3line;
+      //check ("test3", 1, all, f2line, "f22", FILE, &bdata.failed);
+      (void)f2line;
+      check ("test3", 2, all, f1line, "test3", FILE, &bdata.failed);
+
+      if (bdata.failed)
+	data.failed = 1;
+
+      for (j = 0; j < 3; ++j)
+	{
+	  struct symdata symdata;
+
+	  symdata.name = NULL;
+	  symdata.val = 0;
+	  symdata.size = 0;
+	  symdata.failed = 0;
+
+	  i = backtrace_syminfo (state, addrs[j], callback_three,
+				 error_callback_three, &symdata);
+	  if (i == 0)
+	    {
+	      fprintf (stderr,
+		       ("test3: [%d]: unexpected return value "
+			"from backtrace_syminfo %d\n"),
+		       j, i);
+	      symdata.failed = 1;
+	    }
+
+	  if (!symdata.failed)
+	    {
+	      const char *expected;
+
+	      switch (j)
+		{
+		case 0:
+		  expected = "f23";
+		  break;
+		case 1:
+		  expected = "f22";
+		  break;
+		case 2:
+		  expected = "test3";
+		  break;
+		default:
+		  assert (0);
+		}
+
+	      if (symdata.name == NULL)
+		{
+		  fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j);
+		  symdata.failed = 1;
+		}
+	      /* Use strncmp, not strcmp, because GCC might create a
+		 clone.  */
+	      else if (strncmp (symdata.name, expected, strlen (expected))
+		       != 0)
+		{
+		  fprintf (stderr,
+			   ("test3: [%d]: unexpected syminfo name "
+			    "got %s expected %s\n"),
+			   j, symdata.name, expected);
+		  symdata.failed = 1;
+		}
+	    }
+
+	  if (symdata.failed)
+	    data.failed = 1;
+	}
+    }
+
+  printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS");
+
+  if (data.failed)
+    ++failures;
+
+  return failures;
+}
+
+/* Check that are no files left open.  */
+
+static void
+check_open_files (void)
+{
+  int i;
+
+  for (i = 3; i < 10; i++)
+    {
+      if (close (i) == 0)
+	{
+	  fprintf (stderr,
+		   "ERROR: descriptor %d still open after tests complete\n",
+		   i);
+	  ++failures;
+	}
+    }
+}
+
+/* Run all the tests.  */
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv)
+{
+  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
+				  error_callback_create, NULL);
+
+#if BACKTRACE_SUPPORTED
+  test3 ();
+#endif
+
+  check_open_files ();
+
+  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/libbacktrace/configure b/libbacktrace/configure
index c316dde1ad2..2ea112bde68 100755
--- a/libbacktrace/configure
+++ b/libbacktrace/configure
@@ -672,6 +672,9 @@ LD
 FGREP
 SED
 LIBTOOL
+HAVE_DWZ_FALSE
+HAVE_DWZ_TRUE
+DWZ
 RANLIB
 MAINT
 MAINTAINER_MODE_FALSE
@@ -5366,6 +5369,52 @@ case "$AWK" in
 "") as_fn_error $? "can't build without awk" "$LINENO" 5 ;;
 esac
 
+# Extract the first word of "dwz", so it can be a program name with args.
+set dummy dwz; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DWZ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DWZ"; then
+  ac_cv_prog_DWZ="$DWZ" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DWZ="dwz"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DWZ=$ac_cv_prog_DWZ
+if test -n "$DWZ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DWZ" >&5
+$as_echo "$DWZ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "$DWZ" != ""; then
+  HAVE_DWZ_TRUE=
+  HAVE_DWZ_FALSE='#'
+else
+  HAVE_DWZ_TRUE='#'
+  HAVE_DWZ_FALSE=
+fi
+
+
 case `pwd` in
   *\ * | *\	*)
     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
@@ -11440,7 +11489,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11443 "configure"
+#line 11492 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11546,7 +11595,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11549 "configure"
+#line 11598 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13558,6 +13607,10 @@ if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
   as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${HAVE_DWZ_TRUE}" && test -z "${HAVE_DWZ_FALSE}"; then
+  as_fn_error $? "conditional \"HAVE_DWZ\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${HAVE_PTHREAD_TRUE}" && test -z "${HAVE_PTHREAD_FALSE}"; then
   as_fn_error $? "conditional \"HAVE_PTHREAD\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac
index c75fc9d7ebc..9f0fac80719 100644
--- a/libbacktrace/configure.ac
+++ b/libbacktrace/configure.ac
@@ -78,6 +78,9 @@ case "$AWK" in
 "") AC_MSG_ERROR([can't build without awk]) ;;
 esac
 
+AC_CHECK_PROG(DWZ, dwz, dwz)
+AM_CONDITIONAL(HAVE_DWZ, test "$DWZ" != "")
+
 LT_INIT
 AM_PROG_LIBTOOL
 
diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 4566d37cf2f..c14b571bcb9 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -343,6 +343,8 @@ struct dwarf_data
 {
   /* The data for the next file we know about.  */
   struct dwarf_data *next;
+  /* The data for .gnu_debugaltlink.  */
+  struct dwarf_data *altlink;
   /* The base address for this file.  */
   uintptr_t base_address;
   /* A sorted list of address ranges.  */
@@ -660,7 +662,7 @@ static int
 read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
 		int is_dwarf64, int version, int addrsize,
 		const unsigned char *dwarf_str, size_t dwarf_str_size,
-		struct attr_val *val)
+		struct attr_val *val, struct dwarf_data *altlink)
 {
   /* Avoid warnings about val.u.FIELD may be used uninitialized if
      this function is inlined.  The warnings aren't valid but can
@@ -766,7 +768,7 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
 	form = read_uleb128 (buf);
 	return read_attribute ((enum dwarf_form) form, buf, is_dwarf64,
 			       version, addrsize, dwarf_str, dwarf_str_size,
-			       val);
+			       val, altlink);
       }
     case DW_FORM_sec_offset:
       val->encoding = ATTR_VAL_REF_SECTION;
@@ -796,8 +798,18 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
       val->u.uint = read_offset (buf, is_dwarf64);
       return 1;
     case DW_FORM_GNU_strp_alt:
-      val->encoding = ATTR_VAL_REF_SECTION;
-      val->u.uint = read_offset (buf, is_dwarf64);
+      {
+	uint64_t offset;
+
+	offset = read_offset (buf, is_dwarf64);
+	if (offset >= altlink->dwarf_str_size)
+	  {
+	    dwarf_buf_error (buf, "DW_FORM_GNU_strp_alt out of range");
+	    return 0;
+	  }
+	val->encoding = ATTR_VAL_STRING;
+	val->u.string = (const char *) altlink->dwarf_str + offset;
+      }
       return 1;
     default:
       dwarf_buf_error (buf, "unrecognized DWARF form");
@@ -1252,7 +1264,8 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 		     size_t dwarf_ranges_size,
 		     int is_bigendian, backtrace_error_callback error_callback,
 		     void *data, struct unit *u,
-		     struct unit_addrs_vector *addrs)
+		     struct unit_addrs_vector *addrs,
+		     struct dwarf_data *altlink)
 {
   while (unit_buf->left > 0)
     {
@@ -1288,7 +1301,7 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 
 	  if (!read_attribute (abbrev->attrs[i].form, unit_buf,
 			       u->is_dwarf64, u->version, u->addrsize,
-			       dwarf_str, dwarf_str_size, &val))
+			       dwarf_str, dwarf_str_size, &val, altlink))
 	    return 0;
 
 	  switch (abbrev->attrs[i].name)
@@ -1387,7 +1400,7 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 				    dwarf_str, dwarf_str_size,
 				    dwarf_ranges, dwarf_ranges_size,
 				    is_bigendian, error_callback, data,
-				    u, addrs))
+				    u, addrs, altlink))
 	    return 0;
 	}
     }
@@ -1406,7 +1419,8 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
 		   const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
 		   const unsigned char *dwarf_str, size_t dwarf_str_size,
 		   int is_bigendian, backtrace_error_callback error_callback,
-		   void *data, struct unit_addrs_vector *addrs)
+		   void *data, struct unit_addrs_vector *addrs,
+		   struct dwarf_data *altlink)
 {
   struct dwarf_buf info;
   struct abbrevs abbrevs;
@@ -1499,7 +1513,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
 				dwarf_str, dwarf_str_size,
 				dwarf_ranges, dwarf_ranges_size,
 				is_bigendian, error_callback, data,
-				u, addrs))
+				u, addrs, altlink))
 	{
 	  free_abbrevs (state, &u->abbrevs, error_callback, data);
 	  backtrace_free (state, u, sizeof *u, error_callback, data);
@@ -2101,7 +2115,7 @@ read_referenced_name (struct dwarf_data *ddata, struct unit *u,
       if (!read_attribute (abbrev->attrs[i].form, &unit_buf,
 			   u->is_dwarf64, u->version, u->addrsize,
 			   ddata->dwarf_str, ddata->dwarf_str_size,
-			   &val))
+			   &val, ddata->altlink))
 	return NULL;
 
       switch (abbrev->attrs[i].name)
@@ -2314,7 +2328,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
 	  if (!read_attribute (abbrev->attrs[i].form, unit_buf,
 			       u->is_dwarf64, u->version, u->addrsize,
 			       ddata->dwarf_str, ddata->dwarf_str_size,
-			       &val))
+			       &val, ddata->altlink))
 	    return 0;
 
 	  /* The compile unit sets the base address for any address
@@ -2925,7 +2939,7 @@ build_dwarf_data (struct backtrace_state *state,
 		  size_t dwarf_str_size,
 		  int is_bigendian,
 		  backtrace_error_callback error_callback,
-		  void *data)
+		  void *data, struct dwarf_data *altlink)
 {
   struct unit_addrs_vector addrs_vec;
   struct unit_addrs *addrs;
@@ -2935,7 +2949,8 @@ build_dwarf_data (struct backtrace_state *state,
   if (!build_address_map (state, base_address, dwarf_info, dwarf_info_size,
 			  dwarf_abbrev, dwarf_abbrev_size, dwarf_ranges,
 			  dwarf_ranges_size, dwarf_str, dwarf_str_size,
-			  is_bigendian, error_callback, data, &addrs_vec))
+			  is_bigendian, error_callback, data, &addrs_vec,
+			  altlink))
     return NULL;
 
   if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))
@@ -2952,6 +2967,7 @@ build_dwarf_data (struct backtrace_state *state,
     return NULL;
 
   fdata->next = NULL;
+  fdata->altlink = altlink;
   fdata->base_address = base_address;
   fdata->addrs = addrs;
   fdata->addrs_count = addrs_count;
@@ -2988,7 +3004,8 @@ backtrace_dwarf_add (struct backtrace_state *state,
 		     size_t dwarf_str_size,
 		     int is_bigendian,
 		     backtrace_error_callback error_callback,
-		     void *data, fileline *fileline_fn)
+		     void *data, fileline *fileline_fn, void **fileline_entry,
+		     void *fileline_altlink)
 {
   struct dwarf_data *fdata;
 
@@ -2996,10 +3013,13 @@ backtrace_dwarf_add (struct backtrace_state *state,
 			    dwarf_line, dwarf_line_size, dwarf_abbrev,
 			    dwarf_abbrev_size, dwarf_ranges, dwarf_ranges_size,
 			    dwarf_str, dwarf_str_size, is_bigendian,
-			    error_callback, data);
+			    error_callback, data, fileline_altlink);
   if (fdata == NULL)
     return 0;
 
+  if (fileline_entry != NULL)
+    *fileline_entry = fdata;
+
   if (!state->threaded)
     {
       struct dwarf_data **pp;
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index f4863f0bea5..f63f9c8bcec 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -1051,6 +1051,27 @@ elf_open_debugfile_by_debuglink (struct backtrace_state *state,
   return ddescriptor;
 }
 
+/* Open a separate debug info file, using the debugaltlink section data
+   to find it.  Returns an open file descriptor, or -1.  */
+
+static int
+elf_open_debugfile_by_debugaltlink (struct backtrace_state *state,
+				    const char *filename,
+				    const char *debugaltlink_name,
+				    backtrace_error_callback error_callback,
+				    void *data)
+{
+  int ddescriptor;
+
+  ddescriptor = elf_find_debugfile_by_debuglink (state, filename,
+						 debugaltlink_name,
+						 error_callback, data);
+  if (ddescriptor < 0)
+    return -1;
+
+  return ddescriptor;
+}
+
 /* A function useful for setting a breakpoint for an inflation failure
    when this code is compiled with -g.  */
 
@@ -2638,7 +2659,8 @@ static int
 elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	 uintptr_t base_address, backtrace_error_callback error_callback,
 	 void *data, fileline *fileline_fn, int *found_sym, int *found_dwarf,
-	 int exe, int debuginfo)
+	 void **fileline_entry, int exe, int debuginfo,
+	 const char *with_buildid_data, uint32_t with_buildid_size)
 {
   struct backtrace_view ehdr_view;
   b_elf_ehdr ehdr;
@@ -2670,6 +2692,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
   int debuglink_view_valid;
   const char *debuglink_name;
   uint32_t debuglink_crc;
+  struct backtrace_view debugaltlink_view;
+  int debugaltlink_view_valid;
+  const char *debugaltlink_name;
+  const char *debugaltlink_buildid_data;
+  uint32_t debugaltlink_buildid_size;
   off_t min_offset;
   off_t max_offset;
   struct backtrace_view debug_view;
@@ -2694,6 +2721,10 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
   debuglink_view_valid = 0;
   debuglink_name = NULL;
   debuglink_crc = 0;
+  debugaltlink_view_valid = 0;
+  debugaltlink_name = NULL;
+  debugaltlink_buildid_data = NULL;
+  debugaltlink_buildid_size = 0;
   debug_view_valid = 0;
   opd = NULL;
 
@@ -2873,6 +2904,15 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	      buildid_data = &note->name[0] + ((note->namesz + 3) & ~ 3);
 	      buildid_size = note->descsz;
 	    }
+
+	  if (with_buildid_size != 0)
+	    {
+	      if (buildid_size != with_buildid_size)
+		goto fail;
+
+	      if (memcmp (buildid_data, with_buildid_data, buildid_size) != 0)
+		goto fail;
+	    }
 	}
 
       /* Read the debuglink file if present.  */
@@ -2899,6 +2939,27 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	    }
 	}
 
+      if (!debugaltlink_view_valid
+	  && strcmp (name, ".gnu_debugaltlink") == 0)
+	{
+	  const char *debugaltlink_data;
+	  size_t debugaltlink_name_len;
+
+	  if (!backtrace_get_view (state, descriptor, shdr->sh_offset,
+				   shdr->sh_size, error_callback, data,
+				   &debugaltlink_view))
+	    goto fail;
+
+	  debugaltlink_view_valid = 1;
+	  debugaltlink_data = (const char *) debugaltlink_view.data;
+	  debugaltlink_name = debugaltlink_data;
+	  debugaltlink_name_len = strnlen (debugaltlink_data, shdr->sh_size);
+	  debugaltlink_buildid_data = (debugaltlink_data
+				       + debugaltlink_name_len
+				       + 1);
+	  debugaltlink_buildid_size = shdr->sh_size - debugaltlink_name_len - 1;
+	}
+
       /* Read the .opd section on PowerPC64 ELFv1.  */
       if (ehdr.e_machine == EM_PPC64
 	  && (ehdr.e_flags & EF_PPC64_ABI) < 2
@@ -2993,8 +3054,12 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	  if (debuglink_view_valid)
 	    backtrace_release_view (state, &debuglink_view, error_callback,
 				    data);
+	  if (debugaltlink_view_valid)
+	    backtrace_release_view (state, &debugaltlink_view, error_callback,
+				    data);
 	  ret = elf_add (state, NULL, d, base_address, error_callback, data,
-			 fileline_fn, found_sym, found_dwarf, 0, 1);
+			 fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL,
+			 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3028,8 +3093,12 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 
 	  backtrace_release_view (state, &debuglink_view, error_callback,
 				  data);
-	  ret = elf_add (state, NULL, d, base_address, error_callback, data,
-			 fileline_fn, found_sym, found_dwarf, 0, 1);
+	  if (debugaltlink_view_valid)
+	    backtrace_release_view (state, &debugaltlink_view, error_callback,
+				    data);
+	  ret = elf_add (state, filename, d, base_address, error_callback, data,
+			 fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL,
+			 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3044,6 +3113,39 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
       debuglink_view_valid = 0;
     }
 
+  void *fileline_altlink = NULL;
+  if (debugaltlink_name != NULL)
+    {
+      int d;
+
+      d = elf_open_debugfile_by_debugaltlink (state, filename,
+					      debugaltlink_name,
+					      error_callback, data);
+      if (d >= 0)
+	{
+	  int ret;
+
+	  ret = elf_add (state, filename, d, base_address, error_callback, data,
+			 fileline_fn, found_sym, found_dwarf, &fileline_altlink,
+			 0, 1, debugaltlink_buildid_data,
+			 debugaltlink_buildid_size);
+	  backtrace_release_view (state, &debugaltlink_view, error_callback,
+				  data);
+	  debugaltlink_view_valid = 0;
+	  if (ret < 0)
+	    {
+	      backtrace_close (d, error_callback, data);
+	      return ret;
+	    }
+	}
+    }
+
+  if (debugaltlink_view_valid)
+    {
+      backtrace_release_view (state, &debugaltlink_view, error_callback, data);
+      debugaltlink_view_valid = 0;
+    }
+
   /* Read all the debug sections in a single view, since they are
      probably adjacent in the file.  We never release this view.  */
 
@@ -3181,7 +3283,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 			    sections[DEBUG_STR].data,
 			    sections[DEBUG_STR].size,
 			    ehdr.e_ident[EI_DATA] == ELFDATA2MSB,
-			    error_callback, data, fileline_fn))
+			    error_callback, data, fileline_fn, fileline_entry,
+			    fileline_altlink))
     goto fail;
 
   *found_dwarf = 1;
@@ -3199,6 +3302,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
     backtrace_release_view (state, &strtab_view, error_callback, data);
   if (debuglink_view_valid)
     backtrace_release_view (state, &debuglink_view, error_callback, data);
+  if (debugaltlink_view_valid)
+    backtrace_release_view (state, &debugaltlink_view, error_callback, data);
   if (buildid_view_valid)
     backtrace_release_view (state, &buildid_view, error_callback, data);
   if (debug_view_valid)
@@ -3269,7 +3374,7 @@ phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
 
   if (elf_add (pd->state, filename, descriptor, info->dlpi_addr,
 	       pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym,
-	       &found_dwarf, 0, 0))
+	       &found_dwarf, NULL, 0, 0, NULL, 0))
     {
       if (found_dwarf)
 	{
@@ -3297,7 +3402,8 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
   struct phdr_data pd;
 
   ret = elf_add (state, filename, descriptor, 0, error_callback, data,
-		 &elf_fileline_fn, &found_sym, &found_dwarf, 1, 0);
+		 &elf_fileline_fn, &found_sym, &found_dwarf, NULL, 1, 0, NULL,
+		 0);
   if (!ret)
     return 0;
 
diff --git a/libbacktrace/internal.h b/libbacktrace/internal.h
index bff8ed470e4..9c91f673d49 100644
--- a/libbacktrace/internal.h
+++ b/libbacktrace/internal.h
@@ -290,7 +290,9 @@ extern int backtrace_dwarf_add (struct backtrace_state *state,
 				size_t dwarf_str_size,
 				int is_bigendian,
 				backtrace_error_callback error_callback,
-				void *data, fileline *fileline_fn);
+				void *data, fileline *fileline_fn,
+				void **fileline_entry,
+				void *fileline_altlink);
 
 /* A test-only hook for elf_uncompress_zdebug.  */
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]