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  <tdevr...@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.  */
 

Reply via email to