public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 6/9] [libbacktrace] Factor out read_referenced_name_1
  2018-12-11 10:14 [PATCH 0/9] [libbacktrace] Handle .gnu_debugaltlink Tom de Vries
                   ` (2 preceding siblings ...)
  2018-12-11 10:14 ` [PATCH 4/9] [libbacktrace] Handle DW_FORM_GNU_strp_alt Tom de Vries
@ 2018-12-11 10:14 ` Tom de Vries
  2019-01-16  1:15   ` Ian Lance Taylor via gcc-patches
  2018-12-11 10:14 ` [PATCH 3/9] [libbacktrace] Handle alt FORMS without .gnu_debugaltlink Tom de Vries
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2018-12-11 10:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ian Lance Taylor

Factor out the common handling of DW_AT_abstract_origin and
DW_AT_specification from read_function_entry and read_referenced_name.

2018-12-10  Tom de Vries  <tdevries@suse.de>

	* dwarf.c (read_referenced_name_1): New function.  Factor out of ...
 	(read_referenced_name): ... here, and ...
	(read_function_entry): ... here.
---
 libbacktrace/dwarf.c | 83 +++++++++++++++++++++++++++++++---------------------
 1 file changed, 50 insertions(+), 33 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 2483295beb4..99e5f4c3f51 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -2111,6 +2111,42 @@ read_line_info (struct backtrace_state *state, struct dwarf_data *ddata,
   return 0;
 }
 
+static const char *read_referenced_name (struct dwarf_data *, struct unit *,
+					 uint64_t, backtrace_error_callback,
+					 void *);
+
+/* Read the name of a function from a DIE referenced by ATTR with VAL.  */
+
+static const char *
+read_referenced_name_1 (struct dwarf_data *ddata, struct unit *u,
+			struct attr *attr, struct attr_val *val,
+			backtrace_error_callback error_callback, void *data)
+{
+  switch (attr->name)
+    {
+    case DW_AT_abstract_origin:
+    case DW_AT_specification:
+      break;
+    default:
+      return NULL;
+    }
+
+  if (attr->form == DW_FORM_ref_addr
+      || attr->form == DW_FORM_ref_sig8)
+    {
+      /* This refers to an abstract origin defined in
+	 some other compilation unit.  We can handle
+	 this case if we must, but it's harder.  */
+      return NULL;
+    }
+
+  if (val->encoding == ATTR_VAL_UINT
+      || val->encoding == ATTR_VAL_REF_UNIT)
+    return read_referenced_name (ddata, u, val->u.uint, error_callback, data);
+
+  return NULL;
+}
+
 /* Read the name of a function from a DIE referenced by a
    DW_AT_abstract_origin or DW_AT_specification tag.  OFFSET is within
    the same compilation unit.  */
@@ -2194,24 +2230,14 @@ read_referenced_name (struct dwarf_data *ddata, struct unit *u,
 	case DW_AT_specification:
 	  /* Second name preference: override DW_AT_name, don't override
 	     DW_AT_linkage_name.  */
-	  if (abbrev->attrs[i].form == DW_FORM_ref_addr
-	      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
-	    {
-	      /* This refers to a specification defined in some other
-		 compilation unit.  We can handle this case if we
-		 must, but it's harder.  */
-	      break;
-	    }
-	  if (val.encoding == ATTR_VAL_UINT
-	      || val.encoding == ATTR_VAL_REF_UNIT)
-	    {
-	      const char *name;
+	  {
+	    const char *name;
 
-	      name = read_referenced_name (ddata, u, val.u.uint,
+	    name = read_referenced_name_1 (ddata, u, &abbrev->attrs[i], &val,
 					   error_callback, data);
-	      if (name != NULL)
-		ret = name;
-	    }
+	    if (name != NULL)
+	      ret = name;
+	  }
 	  break;
 
 	default:
@@ -2436,24 +2462,15 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
 		     DW_AT_linkage_name.  */
 		  if (have_linkage_name)
 		    break;
-		  if (abbrev->attrs[i].form == DW_FORM_ref_addr
-		      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
-		    {
-		      /* This refers to an abstract origin defined in
-			 some other compilation unit.  We can handle
-			 this case if we must, but it's harder.  */
-		      break;
-		    }
-		  if (val.encoding == ATTR_VAL_UINT
-		      || val.encoding == ATTR_VAL_REF_UNIT)
-		    {
-		      const char *name;
+		  {
+		    const char *name;
 
-		      name = read_referenced_name (ddata, u, val.u.uint,
-						   error_callback, data);
-		      if (name != NULL)
-			function->name = name;
-		    }
+		    name
+		      = read_referenced_name_1 (ddata, u, &abbrev->attrs[i],
+						&val, error_callback, data);
+		    if (name != NULL)
+		      function->name = name;
+		  }
 		  break;
 
 		case DW_AT_name:
-- 
2.16.4

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data
  2018-12-11 10:14 [PATCH 0/9] [libbacktrace] Handle .gnu_debugaltlink Tom de Vries
@ 2018-12-11 10:14 ` Tom de Vries
  2019-01-16  1:02   ` Ian Lance Taylor
  2018-12-11 10:14 ` [PATCH 9/9] [libbacktrace] Add printdwarftest_dwz_cmp.sh test-case Tom de Vries
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2018-12-11 10:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ian Lance Taylor

Add an altlink field to struct dwarf_data, and initialize it with the pointer
to the struct dwarf_data for the .gnu_debugaltlink.

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

	* dwarf.c (struct dwarf_data): Add altlink field.
	(backtrace_dwarf_add): Add and handle fileline_entry and
	fileline_altlink parameters.
	* elf.c	(elf_add): Add and handle fileline_entry parameter.  Add args to
	backtrace_dwarf_add call.
	(phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
	* internal.h (backtrace_dwarf_add): Add fileline_entry and
	fileline_altlink parameters.
	* pecoff.c (coff_add): Add args to backtrace_dwarf_add call.
	* xcoff.c (xcoff_add): Same.
---
 libbacktrace/dwarf.c    | 13 ++++++++++---
 libbacktrace/elf.c      | 24 +++++++++++++++---------
 libbacktrace/internal.h |  4 +++-
 libbacktrace/pecoff.c   |  3 ++-
 libbacktrace/xcoff.c    |  3 ++-
 5 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 0f8f70881f8..b571c9fbb06 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.  */
@@ -2968,7 +2970,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;
@@ -2995,6 +2997,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;
@@ -3031,7 +3034,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;
 
@@ -3039,10 +3043,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 f3bc2119c07..aeb248ec5e3 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -2638,8 +2638,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, const char *with_buildid_data,
-	 uint32_t with_buildid_size)
+	 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;
@@ -3037,7 +3037,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	    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, NULL, 0);
+			 fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL,
+			 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3075,7 +3076,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	    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, NULL, 0);
+			 fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL,
+			 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3090,6 +3092,7 @@ 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;
@@ -3101,8 +3104,9 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	  int ret;
 
 	  ret = elf_add (state, filename, d, base_address, error_callback, data,
-			 fileline_fn, found_sym, found_dwarf, 0, 1,
-			 debugaltlink_buildid_data, debugaltlink_buildid_size);
+			 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;
@@ -3264,7 +3268,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;
@@ -3354,7 +3359,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, NULL, 0))
+	       &found_dwarf, NULL, 0, 0, NULL, 0))
     {
       if (found_dwarf)
 	{
@@ -3382,7 +3387,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, NULL, 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 548f9d70905..bcf5a31da68 100644
--- a/libbacktrace/internal.h
+++ b/libbacktrace/internal.h
@@ -302,7 +302,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.  */
 
diff --git a/libbacktrace/pecoff.c b/libbacktrace/pecoff.c
index 85737d61d49..fbe481cbbb6 100644
--- a/libbacktrace/pecoff.c
+++ b/libbacktrace/pecoff.c
@@ -867,7 +867,8 @@ coff_add (struct backtrace_state *state, int descriptor,
 			    sections[DEBUG_STR].data,
 			    sections[DEBUG_STR].size,
 			    0, /* FIXME */
-			    error_callback, data, fileline_fn))
+			    error_callback, data, fileline_fn,
+			    NULL, NULL))
     goto fail;
 
   *found_dwarf = 1;
diff --git a/libbacktrace/xcoff.c b/libbacktrace/xcoff.c
index 84d0340d744..dc8265c59a8 100644
--- a/libbacktrace/xcoff.c
+++ b/libbacktrace/xcoff.c
@@ -1315,7 +1315,8 @@ xcoff_add (struct backtrace_state *state, int descriptor, off_t offset,
 				dwsect[DWSECT_STR].data,
 				dwsect[DWSECT_STR].size,
 				1, /* big endian */
-				error_callback, data, fileline_fn))
+				error_callback, data, fileline_fn,
+				NULL, NULL))
 	goto fail;
     }
 
-- 
2.16.4

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH 4/9] [libbacktrace] Handle DW_FORM_GNU_strp_alt
  2018-12-11 10:14 [PATCH 0/9] [libbacktrace] Handle .gnu_debugaltlink Tom de Vries
  2018-12-11 10:14 ` [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data Tom de Vries
  2018-12-11 10:14 ` [PATCH 9/9] [libbacktrace] Add printdwarftest_dwz_cmp.sh test-case Tom de Vries
@ 2018-12-11 10:14 ` Tom de Vries
  2019-01-16  1:07   ` Ian Lance Taylor via gcc-patches
  2018-12-11 10:14 ` [PATCH 6/9] [libbacktrace] Factor out read_referenced_name_1 Tom de Vries
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2018-12-11 10:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ian Lance Taylor

Handle DW_FORM_GNU_strp_alt which references the .debug_str section in the
.gnu_debugaltlink file.

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

	* dwarf.c (read_attribute): Handle DW_FORM_GNU_strp_alt
	using altlink.
---
 libbacktrace/dwarf.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 8b802a085ca..341b84605c0 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -843,14 +843,23 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
       val->encoding = ATTR_VAL_REF_SECTION;
       return 1;
     case DW_FORM_GNU_strp_alt:
-      val->u.uint = read_offset (buf, is_dwarf64);
-      if (altlink == NULL)
-	{
-	  val->encoding = ATTR_VAL_NONE;
-	  return 1;
-	}
-      val->encoding = ATTR_VAL_REF_SECTION;
-      return 1;
+      {
+	uint64_t offset;
+	offset = read_offset (buf, is_dwarf64);
+	if (altlink == NULL)
+	  {
+	    val->encoding = ATTR_VAL_NONE;
+	    return 1;
+	  }
+	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");
       return 0;
-- 
2.16.4

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH 0/9] [libbacktrace] Handle .gnu_debugaltlink
@ 2018-12-11 10:14 Tom de Vries
  2018-12-11 10:14 ` [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data Tom de Vries
                   ` (8 more replies)
  0 siblings, 9 replies; 47+ messages in thread
From: Tom de Vries @ 2018-12-11 10:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ian Lance Taylor

[ Part of this patch series was earlier posted as "[libbacktrace] Handle
DW_FORM_GNU_strp_alt" here (
https://gcc.gnu.org/ml/gcc-patches/2018-11/msg01091.html ).

This patch series is based on the patch series submitted here (
https://gcc.gnu.org/ml/gcc-patches/2018-11/msg01091.html).  It needs the part
that adds keeping track of units.  ]

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 to refer to the content of c.debug.

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

This patch series adds to libbacktrace:
- reading the dwarf of the .gnu_debugaltlink
- support for FORM_GNU_strp_alt and FORM_GNU_ref_alt
- a test-case btest_dwz
- a test-case printdwarftest_dwz_cmp.sh

Bootstrapped and reg-tested on x86_64.

OK for trunk?

Thanks,
- Tom

Tom de Vries (9):
  [libbacktrace] Read .gnu_debugaltlink
  [libbacktrace] Add altlink field to struct dwarf_data
  [libbacktrace] Handle alt FORMS without .gnu_debugaltlink
  [libbacktrace] Handle DW_FORM_GNU_strp_alt
  [libbacktrace] Unify function name preference handling
  [libbacktrace] Factor out read_referenced_name_1
  [libbacktrace] Handle DW_FORM_GNU_ref_alt
  [libbacktrace] Add btest_dwz test-case
  [libbacktrace] Add printdwarftest_dwz_cmp.sh test-case

 libbacktrace/Makefile.am               |  23 +++
 libbacktrace/Makefile.in               |  88 ++++++++---
 libbacktrace/configure                 |  57 ++++++-
 libbacktrace/configure.ac              |   3 +
 libbacktrace/dwarf.c                   | 274 +++++++++++++++++++++++++--------
 libbacktrace/elf.c                     | 103 ++++++++++++-
 libbacktrace/internal.h                |   4 +-
 libbacktrace/pecoff.c                  |   3 +-
 libbacktrace/printdwarftest.c          | 241 +++++++++++++++++++++++++++++
 libbacktrace/printdwarftest_dwz_cmp.sh |   8 +
 libbacktrace/xcoff.c                   |   3 +-
 11 files changed, 711 insertions(+), 96 deletions(-)
 create mode 100644 libbacktrace/printdwarftest.c
 create mode 100755 libbacktrace/printdwarftest_dwz_cmp.sh

-- 
2.16.4

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH 3/9] [libbacktrace] Handle alt FORMS without .gnu_debugaltlink
  2018-12-11 10:14 [PATCH 0/9] [libbacktrace] Handle .gnu_debugaltlink Tom de Vries
                   ` (3 preceding siblings ...)
  2018-12-11 10:14 ` [PATCH 6/9] [libbacktrace] Factor out read_referenced_name_1 Tom de Vries
@ 2018-12-11 10:14 ` Tom de Vries
  2019-01-16  1:06   ` Ian Lance Taylor
  2018-12-11 10:14 ` [PATCH 1/9] [libbacktrace] Read .gnu_debugaltlink Tom de Vries
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2018-12-11 10:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ian Lance Taylor

Handle DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt references robustly in
presence of missing .gnu_debugaltlink file.

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

	* dwarf.c (enum attr_val_encoding): Add ATTR_VAL_NONE.
	(read_attribute): Add altlink parameter.  Handle missing altlink for
	DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt.
	(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.
---
 libbacktrace/dwarf.c | 39 +++++++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 12 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index b571c9fbb06..8b802a085ca 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -129,6 +129,8 @@ struct abbrevs
 
 enum attr_val_encoding
 {
+  /* No attribute value.  */
+  ATTR_VAL_NONE,
   /* An address.  */
   ATTR_VAL_ADDRESS,
   /* A unsigned integer.  */
@@ -700,7 +702,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
@@ -806,7 +808,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;
@@ -832,12 +834,22 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
       val->u.uint = read_uleb128 (buf);
       return 1;
     case DW_FORM_GNU_ref_alt:
-      val->encoding = ATTR_VAL_REF_SECTION;
       val->u.uint = read_offset (buf, is_dwarf64);
+      if (altlink == NULL)
+	{
+	  val->encoding = ATTR_VAL_NONE;
+	  return 1;
+	}
+      val->encoding = ATTR_VAL_REF_SECTION;
       return 1;
     case DW_FORM_GNU_strp_alt:
-      val->encoding = ATTR_VAL_REF_SECTION;
       val->u.uint = read_offset (buf, is_dwarf64);
+      if (altlink == NULL)
+	{
+	  val->encoding = ATTR_VAL_NONE;
+	  return 1;
+	}
+      val->encoding = ATTR_VAL_REF_SECTION;
       return 1;
     default:
       dwarf_buf_error (buf, "unrecognized DWARF form");
@@ -1277,7 +1289,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)
     {
@@ -1313,7 +1326,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)
@@ -1412,7 +1425,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;
 	}
     }
@@ -1431,7 +1444,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 backtrace_vector units;
@@ -1533,7 +1547,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))
 	goto fail;
 
       if (unit_buf.reported_underflow)
@@ -2146,7 +2160,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)
@@ -2359,7 +2373,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
@@ -2980,7 +2994,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))
-- 
2.16.4

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH 5/9] [libbacktrace] Unify function name preference handling
  2018-12-11 10:14 [PATCH 0/9] [libbacktrace] Handle .gnu_debugaltlink Tom de Vries
                   ` (5 preceding siblings ...)
  2018-12-11 10:14 ` [PATCH 1/9] [libbacktrace] Read .gnu_debugaltlink Tom de Vries
@ 2018-12-11 10:14 ` Tom de Vries
  2019-01-16  1:10   ` Ian Lance Taylor via gcc-patches
  2018-12-11 10:14 ` [PATCH 8/9] [libbacktrace] Add btest_dwz test-case Tom de Vries
  2018-12-11 10:14 ` [PATCH 7/9] [libbacktrace] Handle DW_FORM_GNU_ref_alt Tom de Vries
  8 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2018-12-11 10:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ian Lance Taylor

Both read_function_entry and read_referenced_name implement a priority scheme
for names.  The priorities are:
- 1st: DW_AT_linkage_name
- 2nd: Name from DW_AT_abstract_origin or DW_AT_specification
- 3rd: DW_AT_name.

Ensure both functions fully adhere to it.

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

	* dwarf.c (read_referenced_name): Don't allow DW_AT_name to override any
	name.
	(read_function_entry): Same.  Don't allow name found via
	DW_AT_abstract_origin or case DW_AT_specification to override linkage
	name.
---
 libbacktrace/dwarf.c | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 341b84605c0..2483295beb4 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -2175,18 +2175,25 @@ read_referenced_name (struct dwarf_data *ddata, struct unit *u,
       switch (abbrev->attrs[i].name)
 	{
 	case DW_AT_name:
-	  /* We prefer the linkage name if get one.  */
+	  /* Third name preference: don't override.  A name we found in some
+	     other way, will normally be more useful -- e.g., this name is
+	     normally not mangled.  */
+	  if (ret != NULL)
+	    break;
 	  if (val.encoding == ATTR_VAL_STRING)
 	    ret = val.u.string;
 	  break;
 
 	case DW_AT_linkage_name:
 	case DW_AT_MIPS_linkage_name:
+	  /* First name preference: override all.  */
 	  if (val.encoding == ATTR_VAL_STRING)
 	    return val.u.string;
 	  break;
 
 	case DW_AT_specification:
+	  /* Second name preference: override DW_AT_name, don't override
+	     DW_AT_linkage_name.  */
 	  if (abbrev->attrs[i].form == DW_FORM_ref_addr
 	      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
 	    {
@@ -2339,6 +2346,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
       int highpc_is_relative;
       uint64_t ranges;
       int have_ranges;
+      int have_linkage_name;
 
       code = read_uleb128 (unit_buf);
       if (code == 0)
@@ -2375,6 +2383,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
       highpc_is_relative = 0;
       ranges = 0;
       have_ranges = 0;
+      have_linkage_name = 0;
       for (i = 0; i < abbrev->num_attrs; ++i)
 	{
 	  struct attr_val val;
@@ -2423,6 +2432,10 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
 
 		case DW_AT_abstract_origin:
 		case DW_AT_specification:
+		  /* Second name preference: override DW_AT_name, don't override
+		     DW_AT_linkage_name.  */
+		  if (have_linkage_name)
+		    break;
 		  if (abbrev->attrs[i].form == DW_FORM_ref_addr
 		      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
 		    {
@@ -2444,21 +2457,21 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
 		  break;
 
 		case DW_AT_name:
+		  /* Third name preference: don't override.  */
+		  if (function->name != NULL)
+		    break;
 		  if (val.encoding == ATTR_VAL_STRING)
-		    {
-		      /* Don't override a name we found in some other
-			 way, as it will normally be more
-			 useful--e.g., this name is normally not
-			 mangled.  */
-		      if (function->name == NULL)
-			function->name = val.u.string;
-		    }
+		    function->name = val.u.string;
 		  break;
 
 		case DW_AT_linkage_name:
 		case DW_AT_MIPS_linkage_name:
+		  /* First name preference: override all.  */
 		  if (val.encoding == ATTR_VAL_STRING)
-		    function->name = val.u.string;
+		    {
+		      function->name = val.u.string;
+		      have_linkage_name = 1;
+		    }
 		  break;
 
 		case DW_AT_low_pc:
-- 
2.16.4

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH 8/9] [libbacktrace] Add btest_dwz test-case
  2018-12-11 10:14 [PATCH 0/9] [libbacktrace] Handle .gnu_debugaltlink Tom de Vries
                   ` (6 preceding siblings ...)
  2018-12-11 10:14 ` [PATCH 5/9] [libbacktrace] Unify function name preference handling Tom de Vries
@ 2018-12-11 10:14 ` Tom de Vries
  2019-01-16  1:19   ` Ian Lance Taylor
  2018-12-11 10:14 ` [PATCH 7/9] [libbacktrace] Handle DW_FORM_GNU_ref_alt Tom de Vries
  8 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2018-12-11 10:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ian Lance Taylor

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

	* configure.ac (DWZ): Set with AC_CHECK_PROG.
	(HAVE_DWZ): Set with AM_CONDITIONAL.
	* configure: Regenerate.
	* Makefile.am (TESTS): Add btest_dwz.
	* Makefile.in: Regenerate.
---
 libbacktrace/Makefile.am  | 12 ++++++++++
 libbacktrace/Makefile.in  | 29 ++++++++++++++++++------
 libbacktrace/configure    | 57 +++++++++++++++++++++++++++++++++++++++++++++--
 libbacktrace/configure.ac |  3 +++
 4 files changed, 92 insertions(+), 9 deletions(-)

diff --git a/libbacktrace/Makefile.am b/libbacktrace/Makefile.am
index 1a3680bc98c..497cc2f5c97 100644
--- a/libbacktrace/Makefile.am
+++ b/libbacktrace/Makefile.am
@@ -157,6 +157,18 @@ btest_alloc_LDADD = libbacktrace_alloc.la
 
 check_PROGRAMS += btest_alloc
 
+if HAVE_DWZ
+
+%_dwz: %
+	rm -f $@_common.debug
+	cp $< $@
+	cp $< $@_2
+	$(DWZ) -m $@_common.debug $@ $@_2
+
+TESTS += btest_dwz
+
+endif HAVE_DWZ
+
 stest_SOURCES = stest.c
 stest_LDADD = libbacktrace.la
 
diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index 6eaa1e28c01..0abfcb42460 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -125,11 +125,12 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
 @NATIVE_TRUE@	test_pecoff test_unknown unittest unittest_alloc \
 @NATIVE_TRUE@	btest btest_alloc stest stest_alloc ztest \
 @NATIVE_TRUE@	ztest_alloc edtest edtest_alloc
-@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_2 = -lz
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_2 = btest_dwz
 @HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_3 = -lz
-@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_4 = ttest ttest_alloc
-@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_5 = dtest
-@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_6 = ctestg ctesta \
+@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_4 = -lz
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_5 = ttest ttest_alloc
+@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_6 = dtest
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_7 = ctestg ctesta \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctestg_alloc \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctesta_alloc
 subdir = .
@@ -620,6 +621,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@
@@ -774,7 +776,7 @@ libbacktrace_la_LIBADD = \
 	$(ALLOC_FILE)
 
 libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
-TESTS = $(check_PROGRAMS) $(am__append_5)
+TESTS = $(check_PROGRAMS) $(am__append_2) $(am__append_6)
 @NATIVE_TRUE@check_LTLIBRARIES = libbacktrace_alloc.la \
 @NATIVE_TRUE@	libbacktrace_noformat.la
 @NATIVE_TRUE@libbacktrace_alloc_la_SOURCES = $(libbacktrace_la_SOURCES)
@@ -809,9 +811,9 @@ TESTS = $(check_PROGRAMS) $(am__append_5)
 @NATIVE_TRUE@stest_alloc_LDADD = libbacktrace_alloc.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_3) \
 @NATIVE_TRUE@	$(CLOCK_GETTIME_LINK)
-@NATIVE_TRUE@ztest_alloc_LDADD = libbacktrace_alloc.la $(am__append_3) \
+@NATIVE_TRUE@ztest_alloc_LDADD = libbacktrace_alloc.la $(am__append_4) \
 @NATIVE_TRUE@	$(CLOCK_GETTIME_LINK)
 @NATIVE_TRUE@ztest_alloc_SOURCES = $(ztest_SOURCES)
 @NATIVE_TRUE@ztest_alloc_CFLAGS = $(ztest_CFLAGS)
@@ -1532,6 +1534,13 @@ ctesta_alloc.log: ctesta_alloc$(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
+	@p='btest_dwz'; \
+	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)
 dtest.log: dtest
 	@p='dtest'; \
 	b='dtest'; \
@@ -1695,6 +1704,12 @@ uninstall-am:
 @NATIVE_TRUE@		$(srcdir)/xcoff.c \
 @NATIVE_TRUE@		> $@
 
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@%_dwz: %
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	rm -f $@_common.debug
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	cp $< $@
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	cp $< $@_2
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	$(DWZ) -m $@_common.debug $@ $@_2
+
 @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/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
 
-- 
2.16.4

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH 9/9] [libbacktrace] Add printdwarftest_dwz_cmp.sh test-case
  2018-12-11 10:14 [PATCH 0/9] [libbacktrace] Handle .gnu_debugaltlink Tom de Vries
  2018-12-11 10:14 ` [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data Tom de Vries
@ 2018-12-11 10:14 ` Tom de Vries
  2019-01-17 13:58   ` Tom de Vries
  2018-12-11 10:14 ` [PATCH 4/9] [libbacktrace] Handle DW_FORM_GNU_strp_alt Tom de Vries
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2018-12-11 10:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ian Lance Taylor

2018-12-10  Tom de Vries  <tdevries@suse.de>

	* Makefile.am (TESTS): Add printdwarftest_dwz_cmp.sh.
	* Makefile.in: Regenerate.
	* printdwarftest.c: New file.
	* printdwarftest_dwz_cmp.sh: New file.
---
 libbacktrace/Makefile.am               |  11 ++
 libbacktrace/Makefile.in               |  75 +++++++---
 libbacktrace/printdwarftest.c          | 241 +++++++++++++++++++++++++++++++++
 libbacktrace/printdwarftest_dwz_cmp.sh |   8 ++
 4 files changed, 315 insertions(+), 20 deletions(-)
 create mode 100644 libbacktrace/printdwarftest.c
 create mode 100755 libbacktrace/printdwarftest_dwz_cmp.sh

diff --git a/libbacktrace/Makefile.am b/libbacktrace/Makefile.am
index 497cc2f5c97..f270cf16833 100644
--- a/libbacktrace/Makefile.am
+++ b/libbacktrace/Makefile.am
@@ -167,6 +167,17 @@ if HAVE_DWZ
 
 TESTS += btest_dwz
 
+printdwarftest.lo: dwarf.c
+
+printdwarftest_SOURCES = printdwarftest.c testlib.c
+printdwarftest_LDADD = libbacktrace.la
+
+check_PROGRAMS += printdwarftest
+
+printdwarftest_dwz_cmp.sh: printdwarftest_dwz
+
+TESTS += printdwarftest_dwz_cmp.sh
+
 endif HAVE_DWZ
 
 stest_SOURCES = stest.c
diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index 0abfcb42460..d5cc8e958c4 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -120,17 +120,21 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
-check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
+check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
+	$(am__EXEEXT_4) $(am__EXEEXT_5)
 @NATIVE_TRUE@am__append_1 = test_elf test_xcoff_32 test_xcoff_64 \
 @NATIVE_TRUE@	test_pecoff test_unknown unittest unittest_alloc \
-@NATIVE_TRUE@	btest btest_alloc stest stest_alloc ztest \
-@NATIVE_TRUE@	ztest_alloc edtest edtest_alloc
-@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_2 = btest_dwz
-@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_3 = -lz
-@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_4 = -lz
-@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_5 = ttest ttest_alloc
-@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_6 = dtest
-@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_7 = ctestg ctesta \
+@NATIVE_TRUE@	btest btest_alloc
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_2 = btest_dwz \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	printdwarftest_dwz_cmp.sh
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_3 = printdwarftest
+@NATIVE_TRUE@am__append_4 = stest stest_alloc ztest ztest_alloc edtest \
+@NATIVE_TRUE@	edtest_alloc
+@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_5 = -lz
+@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_6 = -lz
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_7 = ttest ttest_alloc
+@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_8 = dtest
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_9 = ctestg ctesta \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctestg_alloc \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctesta_alloc
 subdir = .
@@ -178,13 +182,14 @@ libbacktrace_noformat_la_OBJECTS =  \
 @NATIVE_TRUE@	test_xcoff_64$(EXEEXT) test_pecoff$(EXEEXT) \
 @NATIVE_TRUE@	test_unknown$(EXEEXT) unittest$(EXEEXT) \
 @NATIVE_TRUE@	unittest_alloc$(EXEEXT) btest$(EXEEXT) \
-@NATIVE_TRUE@	btest_alloc$(EXEEXT) stest$(EXEEXT) \
-@NATIVE_TRUE@	stest_alloc$(EXEEXT) ztest$(EXEEXT) \
-@NATIVE_TRUE@	ztest_alloc$(EXEEXT) edtest$(EXEEXT) \
-@NATIVE_TRUE@	edtest_alloc$(EXEEXT)
-@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__EXEEXT_2 = ttest$(EXEEXT) \
+@NATIVE_TRUE@	btest_alloc$(EXEEXT)
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__EXEEXT_2 = printdwarftest$(EXEEXT)
+@NATIVE_TRUE@am__EXEEXT_3 = stest$(EXEEXT) stest_alloc$(EXEEXT) \
+@NATIVE_TRUE@	ztest$(EXEEXT) ztest_alloc$(EXEEXT) \
+@NATIVE_TRUE@	edtest$(EXEEXT) edtest_alloc$(EXEEXT)
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__EXEEXT_4 = ttest$(EXEEXT) \
 @HAVE_PTHREAD_TRUE@@NATIVE_TRUE@	ttest_alloc$(EXEEXT)
-@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__EXEEXT_3 =  \
+@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) \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctestg_alloc$(EXEEXT) \
@@ -247,6 +252,12 @@ edtest_OBJECTS = $(am_edtest_OBJECTS)
 @NATIVE_TRUE@am_edtest_alloc_OBJECTS = $(am__objects_5)
 edtest_alloc_OBJECTS = $(am_edtest_alloc_OBJECTS)
 @NATIVE_TRUE@edtest_alloc_DEPENDENCIES = libbacktrace_alloc.la
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am_printdwarftest_OBJECTS =  \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	printdwarftest.$(OBJEXT) \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	testlib.$(OBJEXT)
+printdwarftest_OBJECTS = $(am_printdwarftest_OBJECTS)
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest_DEPENDENCIES =  \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	libbacktrace.la
 @NATIVE_TRUE@am_stest_OBJECTS = stest.$(OBJEXT)
 stest_OBJECTS = $(am_stest_OBJECTS)
 @NATIVE_TRUE@stest_DEPENDENCIES = libbacktrace.la
@@ -361,8 +372,8 @@ SOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \
 	$(btest_alloc_SOURCES) $(ctesta_SOURCES) \
 	$(ctesta_alloc_SOURCES) $(ctestg_SOURCES) \
 	$(ctestg_alloc_SOURCES) $(edtest_SOURCES) \
-	$(edtest_alloc_SOURCES) $(stest_SOURCES) \
-	$(stest_alloc_SOURCES) $(test_elf_SOURCES) \
+	$(edtest_alloc_SOURCES) $(printdwarftest_SOURCES) \
+	$(stest_SOURCES) $(stest_alloc_SOURCES) $(test_elf_SOURCES) \
 	$(test_pecoff_SOURCES) $(test_unknown_SOURCES) \
 	$(test_xcoff_32_SOURCES) $(test_xcoff_64_SOURCES) \
 	$(ttest_SOURCES) $(ttest_alloc_SOURCES) $(unittest_SOURCES) \
@@ -776,7 +787,7 @@ libbacktrace_la_LIBADD = \
 	$(ALLOC_FILE)
 
 libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
-TESTS = $(check_PROGRAMS) $(am__append_2) $(am__append_6)
+TESTS = $(check_PROGRAMS) $(am__append_2) $(am__append_8)
 @NATIVE_TRUE@check_LTLIBRARIES = libbacktrace_alloc.la \
 @NATIVE_TRUE@	libbacktrace_noformat.la
 @NATIVE_TRUE@libbacktrace_alloc_la_SOURCES = $(libbacktrace_la_SOURCES)
@@ -805,15 +816,17 @@ TESTS = $(check_PROGRAMS) $(am__append_2) $(am__append_6)
 @NATIVE_TRUE@btest_alloc_SOURCES = $(btest_SOURCES)
 @NATIVE_TRUE@btest_alloc_CFLAGS = $(btest_CFLAGS)
 @NATIVE_TRUE@btest_alloc_LDADD = libbacktrace_alloc.la
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest_SOURCES = printdwarftest.c testlib.c
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest_LDADD = libbacktrace.la
 @NATIVE_TRUE@stest_SOURCES = stest.c
 @NATIVE_TRUE@stest_LDADD = libbacktrace.la
 @NATIVE_TRUE@stest_alloc_SOURCES = $(stest_SOURCES)
 @NATIVE_TRUE@stest_alloc_LDADD = libbacktrace_alloc.la
 @NATIVE_TRUE@ztest_SOURCES = ztest.c testlib.c
 @NATIVE_TRUE@ztest_CFLAGS = -DSRCDIR=\"$(srcdir)\"
-@NATIVE_TRUE@ztest_LDADD = libbacktrace.la $(am__append_3) \
+@NATIVE_TRUE@ztest_LDADD = libbacktrace.la $(am__append_5) \
 @NATIVE_TRUE@	$(CLOCK_GETTIME_LINK)
-@NATIVE_TRUE@ztest_alloc_LDADD = libbacktrace_alloc.la $(am__append_4) \
+@NATIVE_TRUE@ztest_alloc_LDADD = libbacktrace_alloc.la $(am__append_6) \
 @NATIVE_TRUE@	$(CLOCK_GETTIME_LINK)
 @NATIVE_TRUE@ztest_alloc_SOURCES = $(ztest_SOURCES)
 @NATIVE_TRUE@ztest_alloc_CFLAGS = $(ztest_CFLAGS)
@@ -991,6 +1004,10 @@ edtest_alloc$(EXEEXT): $(edtest_alloc_OBJECTS) $(edtest_alloc_DEPENDENCIES) $(EX
 	@rm -f edtest_alloc$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(edtest_alloc_OBJECTS) $(edtest_alloc_LDADD) $(LIBS)
 
+printdwarftest$(EXEEXT): $(printdwarftest_OBJECTS) $(printdwarftest_DEPENDENCIES) $(EXTRA_printdwarftest_DEPENDENCIES) 
+	@rm -f printdwarftest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(printdwarftest_OBJECTS) $(printdwarftest_LDADD) $(LIBS)
+
 stest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) $(EXTRA_stest_DEPENDENCIES) 
 	@rm -f stest$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(stest_OBJECTS) $(stest_LDADD) $(LIBS)
@@ -1450,6 +1467,13 @@ btest_alloc.log: btest_alloc$(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)
+printdwarftest.log: printdwarftest$(EXEEXT)
+	@p='printdwarftest$(EXEEXT)'; \
+	b='printdwarftest'; \
+	$(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'; \
@@ -1541,6 +1565,13 @@ btest_dwz.log: btest_dwz
 	--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)
+printdwarftest_dwz_cmp.sh.log: printdwarftest_dwz_cmp.sh
+	@p='printdwarftest_dwz_cmp.sh'; \
+	b='printdwarftest_dwz_cmp.sh'; \
+	$(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'; \
@@ -1710,6 +1741,10 @@ uninstall-am:
 @HAVE_DWZ_TRUE@@NATIVE_TRUE@	cp $< $@_2
 @HAVE_DWZ_TRUE@@NATIVE_TRUE@	$(DWZ) -m $@_common.debug $@ $@_2
 
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest.lo: dwarf.c
+
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest_dwz_cmp.sh: printdwarftest_dwz
+
 @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/printdwarftest.c b/libbacktrace/printdwarftest.c
new file mode 100644
index 00000000000..f4fea4c09d6
--- /dev/null
+++ b/libbacktrace/printdwarftest.c
@@ -0,0 +1,241 @@
+/* printdwarftest.c -- Print dwarf info cached by libbacktrace.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+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.  */
+
+/* Add all dwarf.c includes here, to make sure once-included headers are
+   included here (before defining backtrace_dwarf_add) rather than at the
+   #include "dwarf.c" below.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "dwarf2.h"
+#include "filenames.h"
+
+#include "backtrace.h"
+#include "internal.h"
+
+#include "testlib.h"
+#include "backtrace-supported.h"
+
+/* Include dwarf.c, using dwarf.c as header file defining struct dwarf_data.
+   Rename the only external function to prevent conflict with dwarf.o.  */
+
+extern int dummy_backtrace_dwarf_add (struct backtrace_state *state,
+				      uintptr_t base_address,
+				      const unsigned char* dwarf_info,
+				      size_t dwarf_info_size,
+				      const unsigned char *dwarf_line,
+				      size_t dwarf_line_size,
+				      const unsigned char *dwarf_abbrev,
+				      size_t dwarf_abbrev_size,
+				      const unsigned char *dwarf_ranges,
+				      size_t dwarf_range_size,
+				      const unsigned char *dwarf_str,
+				      size_t dwarf_str_size,
+				      int is_bigendian,
+				      backtrace_error_callback error_callback,
+				      void *data, fileline *fileline_fn,
+				      void **fileline_entry,
+				      void *fileline_altlink);
+
+#define backtrace_dwarf_add dummy_backtrace_dwarf_add
+#include "dwarf.c"
+
+static void
+error_callback (void *vdata ATTRIBUTE_UNUSED, const char *msg ATTRIBUTE_UNUSED,
+		int errnum ATTRIBUTE_UNUSED)
+{
+}
+
+static int
+dummmy_callback (void *data ATTRIBUTE_UNUSED, uintptr_t pc ATTRIBUTE_UNUSED,
+		 const char *filename ATTRIBUTE_UNUSED,
+		 int lineno ATTRIBUTE_UNUSED,
+		 const char *function ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+struct print_callback_data
+{
+  uintptr_t base_address;
+  uintptr_t pc;
+  const char *filename;
+  int lineno;
+  const char *function;
+  uintptr_t d1_pc;
+  const char *d1_filename;
+  int d1_lineno;
+  const char *d1_function;
+  int depth;
+  int stack_printed;
+  int skip;
+};
+
+static int
+print_callback (void *data, uintptr_t pc ATTRIBUTE_UNUSED,
+		const char *filename ATTRIBUTE_UNUSED,
+		int lineno ATTRIBUTE_UNUSED,
+		const char *function ATTRIBUTE_UNUSED)
+{
+  struct print_callback_data *prev = (struct print_callback_data *)data;
+
+  prev->depth++;
+  if (prev->depth == 1)
+    {
+      if (prev->stack_printed)
+	prev->skip = 1;
+    }
+  else
+    {
+      if (prev->skip)
+	return 0;
+
+      fprintf (stderr, " %s@%d", function, prev->depth);
+      fprintf (stderr, " %d", lineno);
+      prev->stack_printed = 1;
+
+      return 0;
+    }
+
+  if (function == NULL)
+    return 0;
+
+  if (prev->pc == 0)
+    {
+      fprintf (stderr, "%p", (void *)(pc - prev->base_address));
+      fprintf (stderr, " %s@%d", function, prev->depth);
+      fprintf (stderr, " %s", filename);
+      fprintf (stderr, "\n  %d", lineno);
+      fprintf (stderr, "@%p", (void *)(pc - prev->base_address));
+      goto update;
+    }
+
+  if (function != prev->function)
+    {
+      if (pc != prev->pc)
+	{
+	  fprintf (stderr, "\n");
+	  fprintf (stderr, "%p", (void *)(pc - prev->base_address));
+	  fprintf (stderr, " %s@%d", function, prev->depth);
+	}
+      else
+	fprintf (stderr, " %s@%d", function, prev->depth);
+    }
+
+  if (filename != prev->filename)
+    fprintf (stderr, " %s", filename);
+
+  if (lineno != prev->lineno)
+    {
+      prev->stack_printed = 0;
+      prev->skip = 0;
+      fprintf (stderr, "\n  %d", lineno);
+      fprintf (stderr, "@%p", (void *)(pc - prev->base_address));
+    }
+
+ update:
+  prev->pc = pc;
+  prev->filename = filename;
+  prev->lineno = lineno;
+  prev->function = function;
+  if (prev->depth == 1)
+    {
+      prev->d1_pc = pc;
+      prev->d1_filename = filename;
+      prev->d1_lineno = lineno;
+      prev->d1_function = function;
+    }
+  return 0;
+}
+
+static void
+print_dwarf_data (struct backtrace_state *state, void *data)
+{
+  struct dwarf_data *fdata;
+  unsigned int i;
+
+  fdata = (struct dwarf_data *)data;
+
+  for (i = 0; i < fdata->addrs_count; ++i)
+    {
+      struct unit_addrs *addr = &fdata->addrs[i];
+      uintptr_t pc;
+
+      struct print_callback_data tdata;
+      tdata.base_address = fdata->base_address;
+      tdata.pc = 0;
+      tdata.stack_printed = 0;
+      tdata.skip = 0;
+      for (pc = addr->low; pc < addr->high; ++pc)
+	{
+	  int found;
+	  tdata.depth = 0;
+	  dwarf_lookup_pc (state, fdata, pc, print_callback, error_callback,
+			   &tdata, &found);
+	  if (!found)
+	    fprintf (stderr, "not found: %p\n", (void *)pc);
+	}
+      if (tdata.pc != 0)
+	fprintf (stderr, "\n");
+    }
+}
+
+static void
+print_dwarf_cache (struct backtrace_state *state)
+{
+  struct dwarf_data **pp;
+
+  if (state->fileline_data == NULL)
+    backtrace_pcinfo (state, (uintptr_t)print_callback, dummmy_callback,
+		      NULL, NULL);
+
+  for (pp = (struct dwarf_data **) (void *) &state->fileline_data;
+       *pp != NULL;
+       pp = &(*pp)->next)
+    print_dwarf_data (state, *pp);
+}
+
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv)
+{
+  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
+				  error_callback_create, NULL);
+
+  print_dwarf_cache ((struct backtrace_state *)state);
+
+  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/libbacktrace/printdwarftest_dwz_cmp.sh b/libbacktrace/printdwarftest_dwz_cmp.sh
new file mode 100755
index 00000000000..617de00ece8
--- /dev/null
+++ b/libbacktrace/printdwarftest_dwz_cmp.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+log1=printdwarftest_dwz.1.log
+log2=printdwarftest_dwz.2.log
+
+./printdwarftest 2> $log1
+./printdwarftest_dwz 2> $log2
+cmp $log1 $log2
-- 
2.16.4

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH 1/9] [libbacktrace] Read .gnu_debugaltlink
  2018-12-11 10:14 [PATCH 0/9] [libbacktrace] Handle .gnu_debugaltlink Tom de Vries
                   ` (4 preceding siblings ...)
  2018-12-11 10:14 ` [PATCH 3/9] [libbacktrace] Handle alt FORMS without .gnu_debugaltlink Tom de Vries
@ 2018-12-11 10:14 ` Tom de Vries
  2019-01-16  0:56   ` Ian Lance Taylor via gcc-patches
  2018-12-11 10:14 ` [PATCH 5/9] [libbacktrace] Unify function name preference handling Tom de Vries
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2018-12-11 10:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ian Lance Taylor

Read the elf file pointed at by the .gnu_debugaltlink section, and verify that
the build id matches.

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

	* elf.c (elf_add): Add and handle with_buildid_data and
	with_buildid_size parameters.  Handle .gnu_debugaltlink section.
	(phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
---
 libbacktrace/elf.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 90 insertions(+), 5 deletions(-)

diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index f4863f0bea5..f3bc2119c07 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -2638,7 +2638,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)
+	 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 +2671,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 +2700,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 +2883,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 +2918,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 +3033,11 @@ 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, 0, 1, NULL, 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3028,8 +3071,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 
 	  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, 0, 1, NULL, 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3044,6 +3090,43 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
       debuglink_view_valid = 0;
     }
 
+  if (debugaltlink_name != NULL)
+    {
+      int d;
+
+      d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name,
+					   0, 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, 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;
+	    }
+	}
+      else
+	{
+	  error_callback (data,
+			  "Could not open .gnu_debugaltlink", 0);
+	  /* Don't goto fail, but try continue without the info in the
+	     .gnu_debugaltlink.  */
+	}
+    }
+
+  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.  */
 
@@ -3199,6 +3282,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 +3354,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, 0, 0, NULL, 0))
     {
       if (found_dwarf)
 	{
@@ -3297,7 +3382,7 @@ 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, 1, 0, NULL, 0);
   if (!ret)
     return 0;
 
-- 
2.16.4

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH 7/9] [libbacktrace] Handle DW_FORM_GNU_ref_alt
  2018-12-11 10:14 [PATCH 0/9] [libbacktrace] Handle .gnu_debugaltlink Tom de Vries
                   ` (7 preceding siblings ...)
  2018-12-11 10:14 ` [PATCH 8/9] [libbacktrace] Add btest_dwz test-case Tom de Vries
@ 2018-12-11 10:14 ` Tom de Vries
  2019-01-17  0:17   ` Tom de Vries
  8 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2018-12-11 10:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ian Lance Taylor

2018-12-10  Tom de Vries  <tdevries@suse.de>

	* dwarf.c (enum attr_val_encoding): Add ATTR_VAL_REF_ALT_INFO.
	(struct unit): Add low and high fields.
	(struct unit_vector): New type.
	(struct dwarf_data): Add units and units_counts fields.
	(read_attribute): Handle DW_FORM_GNU_ref_alt using
	ATTR_VAL_REF_ALT_INFO.
	(find_unit): New function.
	(find_address_ranges): Add and handle unit_tag parameter.
	(build_address_map): Add and handle units_vec parameter.
	(read_referenced_name_1): Handle DW_FORM_GNU_ref_alt.
	(build_dwarf_data): Pass units_vec to build_address_map.  Store resulting
	units vector.
---
 libbacktrace/dwarf.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 91 insertions(+), 10 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 99e5f4c3f51..9a0b93120c8 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -143,6 +143,8 @@ enum attr_val_encoding
   ATTR_VAL_REF_UNIT,
   /* An offset to other data within the .dwarf_info section.  */
   ATTR_VAL_REF_INFO,
+  /* An offset to other data within the alt .dwarf_info section.  */
+  ATTR_VAL_REF_ALT_INFO,
   /* An offset to data in some other section.  */
   ATTR_VAL_REF_SECTION,
   /* A type signature.  */
@@ -281,6 +283,10 @@ struct unit
   /* The offset of UNIT_DATA from the start of the information for
      this compilation unit.  */
   size_t unit_data_offset;
+  /* Start of the compilation unit.  */
+  size_t low;
+  /* End of the compilation unit.  */
+  size_t high;
   /* DWARF version.  */
   int version;
   /* Whether unit is DWARF64.  */
@@ -339,6 +345,14 @@ struct unit_addrs_vector
   size_t count;
 };
 
+/* A growable vector of compilation unit pointer.  */
+
+struct unit_vector
+{
+  struct backtrace_vector vec;
+  size_t count;
+};
+
 /* The information we need to map a PC to a file and line.  */
 
 struct dwarf_data
@@ -353,6 +367,10 @@ struct dwarf_data
   struct unit_addrs *addrs;
   /* Number of address ranges in list.  */
   size_t addrs_count;
+  /* A sorted list of units.  */
+  struct unit **units;
+  /* Number of units in the list.  */
+  size_t units_count;
   /* The unparsed .debug_info section.  */
   const unsigned char *dwarf_info;
   size_t dwarf_info_size;
@@ -840,7 +858,7 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
 	  val->encoding = ATTR_VAL_NONE;
 	  return 1;
 	}
-      val->encoding = ATTR_VAL_REF_SECTION;
+      val->encoding = ATTR_VAL_REF_ALT_INFO;
       return 1;
     case DW_FORM_GNU_strp_alt:
       {
@@ -866,6 +884,34 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
     }
 }
 
+/* Compare a unit offset against a unit for bsearch.  */
+
+static int
+units_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct unit *entry = *((const struct unit *const *) ventry);
+  uintptr_t offset;
+
+  offset = *key;
+  if (offset < entry->low)
+    return -1;
+  else if (offset >= entry->high)
+    return 1;
+  else
+    return 0;
+}
+
+/* Find a unit in PU containing OFFSET.  */
+
+static struct unit *
+find_unit (struct unit **pu, size_t units_count, size_t offset)
+{
+  struct unit **u;
+  u = bsearch (&offset, pu, units_count, sizeof (struct unit *), units_search);
+  return u == NULL ? NULL : *u;
+}
+
 /* Compare function_addrs for qsort.  When ranges are nested, make the
    smallest one sort last.  */
 
@@ -1299,7 +1345,7 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 		     int is_bigendian, backtrace_error_callback error_callback,
 		     void *data, struct unit *u,
 		     struct unit_addrs_vector *addrs,
-		     struct dwarf_data *altlink)
+		     struct dwarf_data *altlink, enum dwarf_tag *unit_tag)
 {
   while (unit_buf->left > 0)
     {
@@ -1322,6 +1368,9 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
       if (abbrev == NULL)
 	return 0;
 
+      if (unit_tag != NULL)
+	*unit_tag = abbrev->tag;
+
       lowpc = 0;
       have_lowpc = 0;
       highpc = 0;
@@ -1434,7 +1483,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, altlink))
+				    u, addrs, altlink, NULL))
 	    return 0;
 	}
     }
@@ -1454,6 +1503,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
 		   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,
+		   struct unit_vector *unit_vec,
 		   struct dwarf_data *altlink)
 {
   struct dwarf_buf info;
@@ -1462,9 +1512,12 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
   size_t i;
   struct unit **pu;
   size_t prev_addrs_count;
+  size_t unit_offset = 0;
 
   memset (&addrs->vec, 0, sizeof addrs->vec);
+  memset (&unit_vec->vec, 0, sizeof unit_vec->vec);
   addrs->count = 0;
+  unit_vec->count = 0;
   prev_addrs_count = 0;
 
   /* Read through the .debug_info section.  FIXME: Should we use the
@@ -1493,6 +1546,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
       uint64_t abbrev_offset;
       int addrsize;
       struct unit *u;
+      enum dwarf_tag unit_tag;
 
       if (info.reported_underflow)
 	goto fail;
@@ -1535,6 +1589,9 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
 
       addrsize = read_byte (&unit_buf);
 
+      u->low = unit_offset;
+      unit_offset += len + (is_dwarf64 ? 12 : 4);
+      u->high = unit_offset;
       u->unit_data = unit_buf.buf;
       u->unit_data_len = unit_buf.left;
       u->unit_data_offset = unit_buf.buf - unit_data_start;
@@ -1556,13 +1613,13 @@ 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, altlink))
+				u, addrs, altlink, &unit_tag))
 	goto fail;
 
       if (unit_buf.reported_underflow)
 	goto fail;
 
-      if (addrs->count == prev_addrs_count)
+      if (unit_tag != DW_TAG_partial_unit && addrs->count == prev_addrs_count)
 	{
 	  --units_count;
 	  units.size -= sizeof (u);
@@ -1576,11 +1633,8 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
   if (info.reported_underflow)
     goto fail;
 
-  // We only kept the list of units to free them on failure.  On
-  // success the units are retained, pointed to by the entries in
-  // addrs.
-  backtrace_vector_free (state, &units, error_callback, data);
-
+  unit_vec->vec = units;
+  unit_vec->count = units_count;
   return 1;
 
  fail:
@@ -2144,6 +2198,22 @@ read_referenced_name_1 (struct dwarf_data *ddata, struct unit *u,
       || val->encoding == ATTR_VAL_REF_UNIT)
     return read_referenced_name (ddata, u, val->u.uint, error_callback, data);
 
+  if (val->encoding == ATTR_VAL_REF_ALT_INFO)
+    {
+      struct unit *alt_unit
+	= find_unit (ddata->altlink->units, ddata->altlink->units_count,
+		     val->u.uint);
+      if (alt_unit == NULL)
+	{
+	  error_callback (data,
+			  "Could not find unit for DW_FORM_GNU_ref_alt", 0);
+	  return NULL;
+	}
+      uint64_t unit_offset = val->u.uint - alt_unit->low;
+      return read_referenced_name (ddata->altlink, alt_unit, unit_offset,
+				   error_callback, data);
+    }
+
   return NULL;
 }
 
@@ -3028,21 +3098,30 @@ build_dwarf_data (struct backtrace_state *state,
   struct unit_addrs_vector addrs_vec;
   struct unit_addrs *addrs;
   size_t addrs_count;
+  struct unit_vector units_vec;
+  struct unit **units;
+  size_t units_count;
   struct dwarf_data *fdata;
 
   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,
+			  &units_vec,
 			  altlink))
     return NULL;
 
   if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))
     return NULL;
+  if (!backtrace_vector_release (state, &units_vec.vec, error_callback, data))
+    return NULL;
   addrs = (struct unit_addrs *) addrs_vec.vec.base;
+  units = (struct unit **) units_vec.vec.base;
   addrs_count = addrs_vec.count;
+  units_count = units_vec.count;
   backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs),
 		   unit_addrs_compare);
+  /* No qsort for units required, already sorted.  */
 
   fdata = ((struct dwarf_data *)
 	   backtrace_alloc (state, sizeof (struct dwarf_data),
@@ -3055,6 +3134,8 @@ build_dwarf_data (struct backtrace_state *state,
   fdata->base_address = base_address;
   fdata->addrs = addrs;
   fdata->addrs_count = addrs_count;
+  fdata->units = units;
+  fdata->units_count = units_count;
   fdata->dwarf_info = dwarf_info;
   fdata->dwarf_info_size = dwarf_info_size;
   fdata->dwarf_line = dwarf_line;
-- 
2.16.4

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 1/9] [libbacktrace] Read .gnu_debugaltlink
  2018-12-11 10:14 ` [PATCH 1/9] [libbacktrace] Read .gnu_debugaltlink Tom de Vries
@ 2019-01-16  0:56   ` Ian Lance Taylor via gcc-patches
  2019-01-16 16:26     ` Tom de Vries
  0 siblings, 1 reply; 47+ messages in thread
From: Ian Lance Taylor via gcc-patches @ 2019-01-16  0:56 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
>
> Read the elf file pointed at by the .gnu_debugaltlink section, and verify that
> the build id matches.
>
> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>
>         * elf.c (elf_add): Add and handle with_buildid_data and
>         with_buildid_size parameters.  Handle .gnu_debugaltlink section.
>         (phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
> ---



@@ -2899,6 +2918,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;
> +       }
> +

This doesn't look quite right.  debugaltlink_buildid_size is unsigned.
If there is some misunderstanding of the format it's possible for
strnlen to return shdr->sh_size.  If it does,
debugaltlink_buildid_size will be set to a very large value.


> +  if (debugaltlink_name != NULL)
> +    {
> +      int d;
> +
> +      d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name,
> +                                          0, 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, 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;
> +           }
> +       }
> +      else
> +       {
> +         error_callback (data,
> +                         "Could not open .gnu_debugaltlink", 0);
> +         /* Don't goto fail, but try continue without the info in the
> +            .gnu_debugaltlink.  */
> +       }
> +    }

The strings passed to error_callback always start with a lowercase
letter (unless they start with something like ELF) because the
callback will most likely print them with some prefix.

More seriously, we don't call error_callback in any cases that
correspond to this.  We just carry on.  Is there any reason to call
error_callback here?

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data
  2018-12-11 10:14 ` [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data Tom de Vries
@ 2019-01-16  1:02   ` Ian Lance Taylor
  2019-01-16 16:33     ` Tom de Vries
  0 siblings, 1 reply; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-16  1:02 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
>
> Add an altlink field to struct dwarf_data, and initialize it with the pointer
> to the struct dwarf_data for the .gnu_debugaltlink.
>
> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>
>         * dwarf.c (struct dwarf_data): Add altlink field.
>         (backtrace_dwarf_add): Add and handle fileline_entry and
>         fileline_altlink parameters.
>         * elf.c (elf_add): Add and handle fileline_entry parameter.  Add args to
>         backtrace_dwarf_add call.
>         (phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
>         * internal.h (backtrace_dwarf_add): Add fileline_entry and
>         fileline_altlink parameters.
>         * pecoff.c (coff_add): Add args to backtrace_dwarf_add call.
>         * xcoff.c (xcoff_add): Same.


> @@ -2968,7 +2970,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)
>  {

error_callback and data should remain the last two parameters, as they
are for many of the functions in this file.


>   @@ -3031,7 +3034,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)

The new fileline_altlink parameter should come before error_callback,
as it is not error_callback/data and is not a result parameter.

What is fileline_entry for?  Why is it void**?

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 3/9] [libbacktrace] Handle alt FORMS without .gnu_debugaltlink
  2018-12-11 10:14 ` [PATCH 3/9] [libbacktrace] Handle alt FORMS without .gnu_debugaltlink Tom de Vries
@ 2019-01-16  1:06   ` Ian Lance Taylor
  2019-01-16 16:34     ` Tom de Vries
  0 siblings, 1 reply; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-16  1:06 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
>
> Handle DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt references robustly in
> presence of missing .gnu_debugaltlink file.
>
> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>
>         * dwarf.c (enum attr_val_encoding): Add ATTR_VAL_NONE.
>         (read_attribute): Add altlink parameter.  Handle missing altlink for
>         DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt.
>         (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.



>  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)
>  {

altlink is not a result parameter, so it should be before val.


> @@ -1277,7 +1289,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)

Same.  altlink should be before the error_callback parameter.


> @@ -1431,7 +1444,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)

Same.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 4/9] [libbacktrace] Handle DW_FORM_GNU_strp_alt
  2018-12-11 10:14 ` [PATCH 4/9] [libbacktrace] Handle DW_FORM_GNU_strp_alt Tom de Vries
@ 2019-01-16  1:07   ` Ian Lance Taylor via gcc-patches
  0 siblings, 0 replies; 47+ messages in thread
From: Ian Lance Taylor via gcc-patches @ 2019-01-16  1:07 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches, Ian Lance Taylor

On Tue, Dec 11, 2018 at 2:15 AM Tom de Vries <tdevries@suse.de> wrote:
>
> Handle DW_FORM_GNU_strp_alt which references the .debug_str section in the
> .gnu_debugaltlink file.
>
> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>
>         * dwarf.c (read_attribute): Handle DW_FORM_GNU_strp_alt
>         using altlink.

This is OK.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 5/9] [libbacktrace] Unify function name preference handling
  2018-12-11 10:14 ` [PATCH 5/9] [libbacktrace] Unify function name preference handling Tom de Vries
@ 2019-01-16  1:10   ` Ian Lance Taylor via gcc-patches
  0 siblings, 0 replies; 47+ messages in thread
From: Ian Lance Taylor via gcc-patches @ 2019-01-16  1:10 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches, Ian Lance Taylor

On Tue, Dec 11, 2018 at 2:15 AM Tom de Vries <tdevries@suse.de> wrote:
>
> Both read_function_entry and read_referenced_name implement a priority scheme
> for names.  The priorities are:
> - 1st: DW_AT_linkage_name
> - 2nd: Name from DW_AT_abstract_origin or DW_AT_specification
> - 3rd: DW_AT_name.
>
> Ensure both functions fully adhere to it.
>
> 2018-11-21  Tom de Vries  <tdevries@suse.de>
>
>         * dwarf.c (read_referenced_name): Don't allow DW_AT_name to override any
>         name.
>         (read_function_entry): Same.  Don't allow name found via
>         DW_AT_abstract_origin or case DW_AT_specification to override linkage
>         name.

This is OK.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 6/9] [libbacktrace] Factor out read_referenced_name_1
  2018-12-11 10:14 ` [PATCH 6/9] [libbacktrace] Factor out read_referenced_name_1 Tom de Vries
@ 2019-01-16  1:15   ` Ian Lance Taylor via gcc-patches
  2019-01-16 16:37     ` Tom de Vries
  0 siblings, 1 reply; 47+ messages in thread
From: Ian Lance Taylor via gcc-patches @ 2019-01-16  1:15 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches, Ian Lance Taylor

On Tue, Dec 11, 2018 at 2:15 AM Tom de Vries <tdevries@suse.de> wrote:
>
> Factor out the common handling of DW_AT_abstract_origin and
> DW_AT_specification from read_function_entry and read_referenced_name.
>
> 2018-12-10  Tom de Vries  <tdevries@suse.de>
>
>         * dwarf.c (read_referenced_name_1): New function.  Factor out of ...
>         (read_referenced_name): ... here, and ...
>         (read_function_entry): ... here.

> +static const char *read_referenced_name (struct dwarf_data *, struct unit *,
> +                                        uint64_t, backtrace_error_callback,
> +                                        void *);
> +

We don't need this declaration.  Only add a static declaration if
there is a forward reference.


> +/* Read the name of a function from a DIE referenced by ATTR with VAL.  */
> +
> +static const char *
> +read_referenced_name_1 (struct dwarf_data *ddata, struct unit *u,
> +                       struct attr *attr, struct attr_val *val,
> +                       backtrace_error_callback error_callback, void *data)
> +{

Let's not use a name ending in "_1".  That is a cop-out.  Pick a
meaningful name.  Perhaps read_referenced_name_from_attr.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 8/9] [libbacktrace] Add btest_dwz test-case
  2018-12-11 10:14 ` [PATCH 8/9] [libbacktrace] Add btest_dwz test-case Tom de Vries
@ 2019-01-16  1:19   ` Ian Lance Taylor
  2019-01-16 16:39     ` Tom de Vries
  0 siblings, 1 reply; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-16  1:19 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Tue, Dec 11, 2018 at 2:16 AM Tom de Vries <tdevries@suse.de> wrote:
>
> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>
>         * configure.ac (DWZ): Set with AC_CHECK_PROG.
>         (HAVE_DWZ): Set with AM_CONDITIONAL.
>         * configure: Regenerate.
>         * Makefile.am (TESTS): Add btest_dwz.
>         * Makefile.in: Regenerate.

> diff --git a/libbacktrace/Makefile.am b/libbacktrace/Makefile.am
> index 1a3680bc98c..497cc2f5c97 100644
> --- a/libbacktrace/Makefile.am
> +++ b/libbacktrace/Makefile.am
> @@ -157,6 +157,18 @@ btest_alloc_LDADD = libbacktrace_alloc.la
>
>  check_PROGRAMS += btest_alloc
>
> +if HAVE_DWZ
> +
> +%_dwz: %
> +       rm -f $@_common.debug
> +       cp $< $@
> +       cp $< $@_2
> +       $(DWZ) -m $@_common.debug $@ $@_2

This doesn't look right.  A Makefile recipe must always create the
target as the very last command.  Otherwise, if the recipe is
interrupted for any reason, such as, in this case, a failure to run
dwz, then when you run make again it will think that the recipe has
already been run.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 1/9] [libbacktrace] Read .gnu_debugaltlink
  2019-01-16  0:56   ` Ian Lance Taylor via gcc-patches
@ 2019-01-16 16:26     ` Tom de Vries
  2019-01-16 17:15       ` Ian Lance Taylor via gcc-patches
  0 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-16 16:26 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 5083 bytes --]

On 16-01-19 01:56, Ian Lance Taylor wrote:
> On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
>>
>> Read the elf file pointed at by the .gnu_debugaltlink section, and verify that
>> the build id matches.
>>
>> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>>
>>         * elf.c (elf_add): Add and handle with_buildid_data and
>>         with_buildid_size parameters.  Handle .gnu_debugaltlink section.
>>         (phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
>> ---
> 
> 
> 
> @@ -2899,6 +2918,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;
>> +       }
>> +
> 
> This doesn't look quite right.  debugaltlink_buildid_size is unsigned.
> If there is some misunderstanding of the format it's possible for
> strnlen to return shdr->sh_size.  If it does,
> debugaltlink_buildid_size will be set to a very large value.
> 

I see, thanks for finding that.

Fixed like this:
...
    debugaltlink_name_len = strnlen (debugaltlink_data, shdr->sh_size);
    if (debugaltlink_name_len < shdr->sh_size)
      {
        /* Include terminating zero.  */
        debugaltlink_name_len =+ 1;

        debugaltlink_buildid_data
          = debugaltlink_data + debugaltlink_name_len;
        debugaltlink_buildid_size
          = shdr->sh_size - debugaltlink_name_len;
      }
...

>> +  if (debugaltlink_name != NULL)
>> +    {
>> +      int d;
>> +
>> +      d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name,
>> +                                          0, 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, 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;
>> +           }
>> +       }
>> +      else
>> +       {
>> +         error_callback (data,
>> +                         "Could not open .gnu_debugaltlink", 0);
>> +         /* Don't goto fail, but try continue without the info in the
>> +            .gnu_debugaltlink.  */
>> +       }
>> +    }
> 
> The strings passed to error_callback always start with a lowercase
> letter (unless they start with something like ELF) because the
> callback will most likely print them with some prefix.
> 

Fixed.

> More seriously, we don't call error_callback in any cases that
> correspond to this.  We just carry on.

Indeed, I noticed that, and filed PR88244 - "[libbacktrace] Failure to
open .gnu_debuglink is silent".

[ The scenario there is: an executable has a .gnu_debuglink, but the
file the .gnu_debuglink is pointing to is absent, because f.i. it has
been removed, or moved to a different location. If a user runs this
executable and a backtrace is triggered, the information relating to the
functions in the executable will be missing in the backtrace, but
there's no error explaining to the user why that information is missing.
 Note: there is a default error "no debug info in ELF executable" in
elf_nodebug, but AFAIU this is not triggered if debug info for one of
the shared libraries is present. ]

BTW, though in the code above an error_callback is called, we don't
error out, but do carry on afterwards (as the comment explicitly states).

> Is there any reason to call
> error_callback here?

A similar scenario: an executable has a .gnu_altdebuglink, but the file
the .gnu_debugaltlink is pointing to is absent, because f.i. it has been
removed, or moved to a different location. If a user runs this
executable and a backtrace is triggered, the information stored in the
.gnu_debugaltlink file will be missing in the backtrace, but there's no
error explaining to the user why that information is missing.

Thanks,
- Tom

[-- Attachment #2: 0001-libbacktrace-Read-.gnu_debugaltlink.patch --]
[-- Type: text/x-patch, Size: 7060 bytes --]

[libbacktrace] Read .gnu_debugaltlink

Read the elf file pointed at by the .gnu_debugaltlink section, and verify that
the build id matches.

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

	* elf.c (elf_add): Add and handle with_buildid_data and
	with_buildid_size parameters.  Handle .gnu_debugaltlink section.
	(phdr_callback, backtrace_initialize): Add arguments to elf_add calls.

---
 libbacktrace/elf.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 95 insertions(+), 5 deletions(-)

diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index 85a323c5876..e363e470525 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -2638,7 +2638,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)
+	 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 +2671,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 +2700,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 +2883,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 +2918,32 @@ 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);
+	  if (debugaltlink_name_len < shdr->sh_size)
+	    {
+	      /* Include terminating zero.  */
+	      debugaltlink_name_len =+ 1;
+
+	      debugaltlink_buildid_data
+		= debugaltlink_data + debugaltlink_name_len;
+	      debugaltlink_buildid_size = shdr->sh_size - debugaltlink_name_len;
+	    }
+	}
+
       /* Read the .opd section on PowerPC64 ELFv1.  */
       if (ehdr.e_machine == EM_PPC64
 	  && (ehdr.e_flags & EF_PPC64_ABI) < 2
@@ -2993,8 +3038,11 @@ 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, 0, 1, NULL, 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3028,8 +3076,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 
 	  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, 0, 1, NULL, 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3044,6 +3095,43 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
       debuglink_view_valid = 0;
     }
 
+  if (debugaltlink_name != NULL)
+    {
+      int d;
+
+      d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name,
+					   0, 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, 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;
+	    }
+	}
+      else
+	{
+	  error_callback (data,
+			  "could not open .gnu_debugaltlink", 0);
+	  /* Don't goto fail, but try continue without the info in the
+	     .gnu_debugaltlink.  */
+	}
+    }
+
+  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.  */
 
@@ -3199,6 +3287,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 +3359,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, 0, 0, NULL, 0))
     {
       if (found_dwarf)
 	{
@@ -3297,7 +3387,7 @@ 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, 1, 0, NULL, 0);
   if (!ret)
     return 0;
 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data
  2019-01-16  1:02   ` Ian Lance Taylor
@ 2019-01-16 16:33     ` Tom de Vries
  2019-01-16 16:34       ` Tom de Vries
  2019-01-16 17:17       ` Ian Lance Taylor
  0 siblings, 2 replies; 47+ messages in thread
From: Tom de Vries @ 2019-01-16 16:33 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2573 bytes --]

On 16-01-19 02:02, Ian Lance Taylor wrote:
> On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
>>
>> Add an altlink field to struct dwarf_data, and initialize it with the pointer
>> to the struct dwarf_data for the .gnu_debugaltlink.
>>
>> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>>
>>         * dwarf.c (struct dwarf_data): Add altlink field.
>>         (backtrace_dwarf_add): Add and handle fileline_entry and
>>         fileline_altlink parameters.
>>         * elf.c (elf_add): Add and handle fileline_entry parameter.  Add args to
>>         backtrace_dwarf_add call.
>>         (phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
>>         * internal.h (backtrace_dwarf_add): Add fileline_entry and
>>         fileline_altlink parameters.
>>         * pecoff.c (coff_add): Add args to backtrace_dwarf_add call.
>>         * xcoff.c (xcoff_add): Same.
> 
> 
>> @@ -2968,7 +2970,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)
>>  {
> 
> error_callback and data should remain the last two parameters, as they
> are for many of the functions in this file.
> 
> 

Done.

>>   @@ -3031,7 +3034,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)
> 
> The new fileline_altlink parameter should come before error_callback,
> as it is not error_callback/data and is not a result parameter.
> 

Done.

> What is fileline_entry for? 

There are two bits to this patch:
- add fileline_entry parameter to elf_add.  This allows the callers of
  elf_add access to the struct dwarf_data pointer corresponding to the
  added elf.
- add an altlink field to struct dwarf_data, and initialize it with the
  pointer to the struct dwarf_data for the .gnu_debugaltlink.

I've split the patch up this way now, hoping it will make things clearer
and/or easier to review.

> Why is it void**?

It's really struct dwarf_data *, but struct dwarf_data is a type
declared in dwarf.c, so it's not known in other files.

Thanks,
- Tom

Here's the first part.

[-- Attachment #2: 0002-libbacktrace-Return-struct-dwarf_data-pointer-from-elf_add.patch --]
[-- Type: text/x-patch, Size: 6198 bytes --]

[libbacktrace] Return struct dwarf_data pointer from elf_add

Allow the caller of elf_add access to the struct dwarf_data pointer
corresponding to the added elf.

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

	* internal.h (backtrace_dwarf_add): Add fileline_entry parameter.
	* dwarf.c (backtrace_dwarf_add): Add and handle fileline_entry parameter.
	* elf.c	(elf_add): Add and handle fileline_entry parameter.  Add
	argument to backtrace_dwarf_add call.
	(phdr_callback, backtrace_initialize): Add argument to elf_add calls.
	* pecoff.c (coff_add): Add argument to backtrace_dwarf_add call.
	* xcoff.c (xcoff_add): Same.

---
 libbacktrace/dwarf.c    |  6 +++++-
 libbacktrace/elf.c      | 23 ++++++++++++++---------
 libbacktrace/internal.h |  3 ++-
 libbacktrace/pecoff.c   |  3 ++-
 libbacktrace/xcoff.c    |  3 ++-
 5 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index af864d68b00..c7913f43617 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -3045,7 +3045,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)
 {
   struct dwarf_data *fdata;
 
@@ -3057,6 +3058,9 @@ backtrace_dwarf_add (struct backtrace_state *state,
   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 e363e470525..6f99461db84 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -2638,8 +2638,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, const char *with_buildid_data,
-	 uint32_t with_buildid_size)
+	 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;
@@ -3042,7 +3042,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	    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, NULL, 0);
+			 fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL,
+			 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3080,7 +3081,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	    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, NULL, 0);
+			 fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL,
+			 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3106,8 +3108,9 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	  int ret;
 
 	  ret = elf_add (state, filename, d, base_address, error_callback, data,
-			 fileline_fn, found_sym, found_dwarf, 0, 1,
-			 debugaltlink_buildid_data, debugaltlink_buildid_size);
+			 fileline_fn, found_sym, found_dwarf, NULL,
+			 0, 1, debugaltlink_buildid_data,
+			 debugaltlink_buildid_size);
 	  backtrace_release_view (state, &debugaltlink_view, error_callback,
 				  data);
 	  debugaltlink_view_valid = 0;
@@ -3269,7 +3272,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))
     goto fail;
 
   *found_dwarf = 1;
@@ -3359,7 +3363,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, NULL, 0))
+	       &found_dwarf, NULL, 0, 0, NULL, 0))
     {
       if (found_dwarf)
 	{
@@ -3387,7 +3391,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, NULL, 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 bf3e7d1989f..0664b2e10c3 100644
--- a/libbacktrace/internal.h
+++ b/libbacktrace/internal.h
@@ -302,7 +302,8 @@ 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);
 
 /* A test-only hook for elf_uncompress_zdebug.  */
 
diff --git a/libbacktrace/pecoff.c b/libbacktrace/pecoff.c
index f51fc0f13c5..cd20cbe17a7 100644
--- a/libbacktrace/pecoff.c
+++ b/libbacktrace/pecoff.c
@@ -867,7 +867,8 @@ coff_add (struct backtrace_state *state, int descriptor,
 			    sections[DEBUG_STR].data,
 			    sections[DEBUG_STR].size,
 			    0, /* FIXME */
-			    error_callback, data, fileline_fn))
+			    error_callback, data, fileline_fn,
+			    NULL))
     goto fail;
 
   *found_dwarf = 1;
diff --git a/libbacktrace/xcoff.c b/libbacktrace/xcoff.c
index 111134d4d21..095800b4f71 100644
--- a/libbacktrace/xcoff.c
+++ b/libbacktrace/xcoff.c
@@ -1315,7 +1315,8 @@ xcoff_add (struct backtrace_state *state, int descriptor, off_t offset,
 				dwsect[DWSECT_STR].data,
 				dwsect[DWSECT_STR].size,
 				1, /* big endian */
-				error_callback, data, fileline_fn))
+				error_callback, data, fileline_fn,
+				NULL))
 	goto fail;
     }
 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 3/9] [libbacktrace] Handle alt FORMS without .gnu_debugaltlink
  2019-01-16  1:06   ` Ian Lance Taylor
@ 2019-01-16 16:34     ` Tom de Vries
  2019-01-16 18:24       ` Ian Lance Taylor
  0 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-16 16:34 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2222 bytes --]

On 16-01-19 02:06, Ian Lance Taylor wrote:
> On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
>>
>> Handle DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt references robustly in
>> presence of missing .gnu_debugaltlink file.
>>
>> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>>
>>         * dwarf.c (enum attr_val_encoding): Add ATTR_VAL_NONE.
>>         (read_attribute): Add altlink parameter.  Handle missing altlink for
>>         DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt.
>>         (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.
> 
> 
> 
>>  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)
>>  {
> 
> altlink is not a result parameter, so it should be before val.
> 
> 

Done.

>> @@ -1277,7 +1289,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)
> 
> Same.  altlink should be before the error_callback parameter.
> 
> 

Done.

>> @@ -1431,7 +1444,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)
> 
> Same.
> 

Done.

Thanks,
- Tom

[-- Attachment #2: 0004-libbacktrace-Handle-alt-FORMS-without-.gnu_debugaltlink.patch --]
[-- Type: text/x-patch, Size: 6094 bytes --]

[libbacktrace] Handle alt FORMS without .gnu_debugaltlink

Handle DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt references robustly in
presence of missing .gnu_debugaltlink file.

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

	* dwarf.c (enum attr_val_encoding): Add ATTR_VAL_NONE.
	(read_attribute): Add altlink parameter.  Handle missing altlink for
	DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt.
	(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.

---
 libbacktrace/dwarf.c | 44 +++++++++++++++++++++++++++++---------------
 1 file changed, 29 insertions(+), 15 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 5469f968468..0e2d57122a2 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -129,6 +129,8 @@ struct abbrevs
 
 enum attr_val_encoding
 {
+  /* No attribute value.  */
+  ATTR_VAL_NONE,
   /* An address.  */
   ATTR_VAL_ADDRESS,
   /* A unsigned integer.  */
@@ -700,7 +702,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 dwarf_data *altlink, struct attr_val *val)
 {
   /* Avoid warnings about val.u.FIELD may be used uninitialized if
      this function is inlined.  The warnings aren't valid but can
@@ -806,7 +808,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);
+			       altlink, val);
       }
     case DW_FORM_sec_offset:
       val->encoding = ATTR_VAL_REF_SECTION;
@@ -832,12 +834,22 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
       val->u.uint = read_uleb128 (buf);
       return 1;
     case DW_FORM_GNU_ref_alt:
-      val->encoding = ATTR_VAL_REF_SECTION;
       val->u.uint = read_offset (buf, is_dwarf64);
+      if (altlink == NULL)
+	{
+	  val->encoding = ATTR_VAL_NONE;
+	  return 1;
+	}
+      val->encoding = ATTR_VAL_REF_SECTION;
       return 1;
     case DW_FORM_GNU_strp_alt:
-      val->encoding = ATTR_VAL_REF_SECTION;
       val->u.uint = read_offset (buf, is_dwarf64);
+      if (altlink == NULL)
+	{
+	  val->encoding = ATTR_VAL_NONE;
+	  return 1;
+	}
+      val->encoding = ATTR_VAL_REF_SECTION;
       return 1;
     default:
       dwarf_buf_error (buf, "unrecognized DWARF form");
@@ -1275,9 +1287,9 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 		     const unsigned char *dwarf_str, size_t dwarf_str_size,
 		     const unsigned char *dwarf_ranges,
 		     size_t dwarf_ranges_size,
-		     int is_bigendian, backtrace_error_callback error_callback,
-		     void *data, struct unit *u,
-		     struct unit_addrs_vector *addrs)
+		     int is_bigendian, struct dwarf_data *altlink,
+		     backtrace_error_callback error_callback, void *data,
+		     struct unit *u, struct unit_addrs_vector *addrs)
 {
   while (unit_buf->left > 0)
     {
@@ -1313,7 +1325,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, altlink, &val))
 	    return 0;
 
 	  switch (abbrev->attrs[i].name)
@@ -1411,7 +1423,7 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 	  if (!find_address_ranges (state, base_address, unit_buf,
 				    dwarf_str, dwarf_str_size,
 				    dwarf_ranges, dwarf_ranges_size,
-				    is_bigendian, error_callback, data,
+				    is_bigendian, altlink, error_callback, data,
 				    u, addrs))
 	    return 0;
 	}
@@ -1430,8 +1442,9 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
 		   const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
 		   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)
+		   int is_bigendian, struct dwarf_data *altlink,
+		   backtrace_error_callback error_callback, void *data,
+		   struct unit_addrs_vector *addrs)
 {
   struct dwarf_buf info;
   struct backtrace_vector units;
@@ -1532,7 +1545,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
       if (!find_address_ranges (state, base_address, &unit_buf,
 				dwarf_str, dwarf_str_size,
 				dwarf_ranges, dwarf_ranges_size,
-				is_bigendian, error_callback, data,
+				is_bigendian, altlink, error_callback, data,
 				u, addrs))
 	goto fail;
 
@@ -2147,7 +2160,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))
+			   ddata->altlink, &val))
 	return NULL;
 
       switch (abbrev->attrs[i].name)
@@ -2369,7 +2382,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))
+			       ddata->altlink, &val))
 	    return 0;
 
 	  /* The compile unit sets the base address for any address
@@ -2995,7 +3008,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, altlink, error_callback, data,
+			  &addrs_vec))
     return NULL;
 
   if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data
  2019-01-16 16:33     ` Tom de Vries
@ 2019-01-16 16:34       ` Tom de Vries
  2019-01-16 22:20         ` Tom de Vries
  2019-01-16 17:17       ` Ian Lance Taylor
  1 sibling, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-16 16:34 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2734 bytes --]

On 16-01-19 17:33, Tom de Vries wrote:
> On 16-01-19 02:02, Ian Lance Taylor wrote:
>> On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
>>>
>>> Add an altlink field to struct dwarf_data, and initialize it with the pointer
>>> to the struct dwarf_data for the .gnu_debugaltlink.
>>>
>>> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>>>
>>>         * dwarf.c (struct dwarf_data): Add altlink field.
>>>         (backtrace_dwarf_add): Add and handle fileline_entry and
>>>         fileline_altlink parameters.
>>>         * elf.c (elf_add): Add and handle fileline_entry parameter.  Add args to
>>>         backtrace_dwarf_add call.
>>>         (phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
>>>         * internal.h (backtrace_dwarf_add): Add fileline_entry and
>>>         fileline_altlink parameters.
>>>         * pecoff.c (coff_add): Add args to backtrace_dwarf_add call.
>>>         * xcoff.c (xcoff_add): Same.
>>
>>
>>> @@ -2968,7 +2970,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)
>>>  {
>>
>> error_callback and data should remain the last two parameters, as they
>> are for many of the functions in this file.
>>
>>
> 
> Done.
> 
>>>   @@ -3031,7 +3034,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)
>>
>> The new fileline_altlink parameter should come before error_callback,
>> as it is not error_callback/data and is not a result parameter.
>>
> 
> Done.
> 
>> What is fileline_entry for? 
> 
> There are two bits to this patch:
> - add fileline_entry parameter to elf_add.  This allows the callers of
>   elf_add access to the struct dwarf_data pointer corresponding to the
>   added elf.
> - add an altlink field to struct dwarf_data, and initialize it with the
>   pointer to the struct dwarf_data for the .gnu_debugaltlink.
> 
> I've split the patch up this way now, hoping it will make things clearer
> and/or easier to review.
> 
>> Why is it void**?
> 
> It's really struct dwarf_data *, but struct dwarf_data is a type
> declared in dwarf.c, so it's not known in other files.
> 
> Thanks,
> - Tom
> 
> Here's the first part.
> 

And here's the second part.


[-- Attachment #2: 0003-libbacktrace-Add-altlink-field-to-struct-dwarf_data.patch --]
[-- Type: text/x-patch, Size: 4931 bytes --]

[libbacktrace] Add altlink field to struct dwarf_data

Add an altlink field to struct dwarf_data, and initialize it with the pointer
to the struct dwarf_data for the .gnu_debugaltlink.

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

	* dwarf.c (struct dwarf_data): Add altlink field.
	(backtrace_dwarf_add): Add and handle fileline_altlink parameter.
	* elf.c	(elf_add): Add argument to backtrace_dwarf_add call.
	(phdr_callback, backtrace_initialize): Add argument to elf_add calls.
	* internal.h (backtrace_dwarf_add): Add fileline_altlink parameter.
	* pecoff.c (coff_add): Add argument to backtrace_dwarf_add call.
	* xcoff.c (xcoff_add): Same.

---
 libbacktrace/dwarf.c    | 7 ++++++-
 libbacktrace/elf.c      | 4 +++-
 libbacktrace/internal.h | 1 +
 libbacktrace/pecoff.c   | 1 +
 libbacktrace/xcoff.c    | 1 +
 5 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index c7913f43617..5469f968468 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.  */
@@ -2981,6 +2983,7 @@ build_dwarf_data (struct backtrace_state *state,
 		  const unsigned char *dwarf_str,
 		  size_t dwarf_str_size,
 		  int is_bigendian,
+		  struct dwarf_data *altlink,
 		  backtrace_error_callback error_callback,
 		  void *data)
 {
@@ -3009,6 +3012,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;
@@ -3044,6 +3048,7 @@ backtrace_dwarf_add (struct backtrace_state *state,
 		     const unsigned char *dwarf_str,
 		     size_t dwarf_str_size,
 		     int is_bigendian,
+		     void *fileline_altlink,
 		     backtrace_error_callback error_callback,
 		     void *data, fileline *fileline_fn,
 		     void **fileline_entry)
@@ -3054,7 +3059,7 @@ 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);
+			    fileline_altlink, error_callback, data);
   if (fdata == NULL)
     return 0;
 
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index 6f99461db84..88987edb6f4 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -3097,6 +3097,7 @@ 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;
@@ -3108,7 +3109,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	  int ret;
 
 	  ret = elf_add (state, filename, d, base_address, error_callback, data,
-			 fileline_fn, found_sym, found_dwarf, NULL,
+			 fileline_fn, found_sym, found_dwarf, &fileline_altlink,
 			 0, 1, debugaltlink_buildid_data,
 			 debugaltlink_buildid_size);
 	  backtrace_release_view (state, &debugaltlink_view, error_callback,
@@ -3272,6 +3273,7 @@ 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,
+			    fileline_altlink,
 			    error_callback, data, fileline_fn,
 			    fileline_entry))
     goto fail;
diff --git a/libbacktrace/internal.h b/libbacktrace/internal.h
index 0664b2e10c3..febdaeebc21 100644
--- a/libbacktrace/internal.h
+++ b/libbacktrace/internal.h
@@ -301,6 +301,7 @@ extern int backtrace_dwarf_add (struct backtrace_state *state,
 				const unsigned char *dwarf_str,
 				size_t dwarf_str_size,
 				int is_bigendian,
+				void *fileline_altlink,
 				backtrace_error_callback error_callback,
 				void *data, fileline *fileline_fn,
 				void **fileline_entry);
diff --git a/libbacktrace/pecoff.c b/libbacktrace/pecoff.c
index cd20cbe17a7..da1982fd3ca 100644
--- a/libbacktrace/pecoff.c
+++ b/libbacktrace/pecoff.c
@@ -867,6 +867,7 @@ coff_add (struct backtrace_state *state, int descriptor,
 			    sections[DEBUG_STR].data,
 			    sections[DEBUG_STR].size,
 			    0, /* FIXME */
+			    NULL,
 			    error_callback, data, fileline_fn,
 			    NULL))
     goto fail;
diff --git a/libbacktrace/xcoff.c b/libbacktrace/xcoff.c
index 095800b4f71..d50b5bc517e 100644
--- a/libbacktrace/xcoff.c
+++ b/libbacktrace/xcoff.c
@@ -1315,6 +1315,7 @@ xcoff_add (struct backtrace_state *state, int descriptor, off_t offset,
 				dwsect[DWSECT_STR].data,
 				dwsect[DWSECT_STR].size,
 				1, /* big endian */
+				NULL,
 				error_callback, data, fileline_fn,
 				NULL))
 	goto fail;

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 6/9] [libbacktrace] Factor out read_referenced_name_1
  2019-01-16  1:15   ` Ian Lance Taylor via gcc-patches
@ 2019-01-16 16:37     ` Tom de Vries
  2019-01-16 18:26       ` Ian Lance Taylor
  0 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-16 16:37 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches, Ian Lance Taylor

[-- Attachment #1: Type: text/plain, Size: 1454 bytes --]

On 16-01-19 02:15, Ian Lance Taylor wrote:
> On Tue, Dec 11, 2018 at 2:15 AM Tom de Vries <tdevries@suse.de> wrote:
>>
>> Factor out the common handling of DW_AT_abstract_origin and
>> DW_AT_specification from read_function_entry and read_referenced_name.
>>
>> 2018-12-10  Tom de Vries  <tdevries@suse.de>
>>
>>         * dwarf.c (read_referenced_name_1): New function.  Factor out of ...
>>         (read_referenced_name): ... here, and ...
>>         (read_function_entry): ... here.
> 
>> +static const char *read_referenced_name (struct dwarf_data *, struct unit *,
>> +                                        uint64_t, backtrace_error_callback,
>> +                                        void *);
>> +
> 
> We don't need this declaration.  Only add a static declaration if
> there is a forward reference.
> 
> 

We need this static declaration because there's a forward reference to
read_referenced_name in read_referenced_name_1.

>> +/* Read the name of a function from a DIE referenced by ATTR with VAL.  */
>> +
>> +static const char *
>> +read_referenced_name_1 (struct dwarf_data *ddata, struct unit *u,
>> +                       struct attr *attr, struct attr_val *val,
>> +                       backtrace_error_callback error_callback, void *data)
>> +{
> 
> Let's not use a name ending in "_1".  That is a cop-out.  Pick a
> meaningful name.  Perhaps read_referenced_name_from_attr.

Used read_referenced_name_from_attr.

Thanks,
- Tom

[-- Attachment #2: 0006-libbacktrace-Factor-out-read_referenced_name_from_attr.patch --]
[-- Type: text/x-patch, Size: 3971 bytes --]

[libbacktrace] Factor out read_referenced_name_from_attr

Factor out the common handling of DW_AT_abstract_origin and
DW_AT_specification from read_function_entry and read_referenced_name.

2018-12-10  Tom de Vries  <tdevries@suse.de>

	* dwarf.c (read_referenced_name_from_attr): New function.  Factor out
	of ...
 	(read_referenced_name): ... here, and ...
	(read_function_entry): ... here.

---
 libbacktrace/dwarf.c | 89 +++++++++++++++++++++++++++++++---------------------
 1 file changed, 54 insertions(+), 35 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 03365e05778..2a58d938de6 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -2111,6 +2111,43 @@ read_line_info (struct backtrace_state *state, struct dwarf_data *ddata,
   return 0;
 }
 
+static const char *read_referenced_name (struct dwarf_data *, struct unit *,
+					 uint64_t, backtrace_error_callback,
+					 void *);
+
+/* Read the name of a function from a DIE referenced by ATTR with VAL.  */
+
+static const char *
+read_referenced_name_from_attr (struct dwarf_data *ddata, struct unit *u,
+				struct attr *attr, struct attr_val *val,
+				backtrace_error_callback error_callback,
+				void *data)
+{
+  switch (attr->name)
+    {
+    case DW_AT_abstract_origin:
+    case DW_AT_specification:
+      break;
+    default:
+      return NULL;
+    }
+
+  if (attr->form == DW_FORM_ref_addr
+      || attr->form == DW_FORM_ref_sig8)
+    {
+      /* This refers to an abstract origin defined in
+	 some other compilation unit.  We can handle
+	 this case if we must, but it's harder.  */
+      return NULL;
+    }
+
+  if (val->encoding == ATTR_VAL_UINT
+      || val->encoding == ATTR_VAL_REF_UNIT)
+    return read_referenced_name (ddata, u, val->u.uint, error_callback, data);
+
+  return NULL;
+}
+
 /* Read the name of a function from a DIE referenced by a
    DW_AT_abstract_origin or DW_AT_specification tag.  OFFSET is within
    the same compilation unit.  */
@@ -2194,24 +2231,14 @@ read_referenced_name (struct dwarf_data *ddata, struct unit *u,
 	case DW_AT_specification:
 	  /* Second name preference: override DW_AT_name, don't override
 	     DW_AT_linkage_name.  */
-	  if (abbrev->attrs[i].form == DW_FORM_ref_addr
-	      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
-	    {
-	      /* This refers to a specification defined in some other
-		 compilation unit.  We can handle this case if we
-		 must, but it's harder.  */
-	      break;
-	    }
-	  if (val.encoding == ATTR_VAL_UINT
-	      || val.encoding == ATTR_VAL_REF_UNIT)
-	    {
-	      const char *name;
+	  {
+	    const char *name;
 
-	      name = read_referenced_name (ddata, u, val.u.uint,
-					   error_callback, data);
-	      if (name != NULL)
-		ret = name;
-	    }
+	    name = read_referenced_name_from_attr (ddata, u, &abbrev->attrs[i],
+						   &val, error_callback, data);
+	    if (name != NULL)
+	      ret = name;
+	  }
 	  break;
 
 	default:
@@ -2436,24 +2463,16 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
 		     DW_AT_linkage_name.  */
 		  if (have_linkage_name)
 		    break;
-		  if (abbrev->attrs[i].form == DW_FORM_ref_addr
-		      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
-		    {
-		      /* This refers to an abstract origin defined in
-			 some other compilation unit.  We can handle
-			 this case if we must, but it's harder.  */
-		      break;
-		    }
-		  if (val.encoding == ATTR_VAL_UINT
-		      || val.encoding == ATTR_VAL_REF_UNIT)
-		    {
-		      const char *name;
-
-		      name = read_referenced_name (ddata, u, val.u.uint,
-						   error_callback, data);
-		      if (name != NULL)
-			function->name = name;
-		    }
+		  {
+		    const char *name;
+
+		    name
+		      = read_referenced_name_from_attr (ddata, u,
+							&abbrev->attrs[i], &val,
+							error_callback, data);
+		    if (name != NULL)
+		      function->name = name;
+		  }
 		  break;
 
 		case DW_AT_name:

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 8/9] [libbacktrace] Add btest_dwz test-case
  2019-01-16  1:19   ` Ian Lance Taylor
@ 2019-01-16 16:39     ` Tom de Vries
  2019-01-16 18:30       ` Ian Lance Taylor
  0 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-16 16:39 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1159 bytes --]

On 16-01-19 02:19, Ian Lance Taylor wrote:
> On Tue, Dec 11, 2018 at 2:16 AM Tom de Vries <tdevries@suse.de> wrote:
>>
>> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>>
>>         * configure.ac (DWZ): Set with AC_CHECK_PROG.
>>         (HAVE_DWZ): Set with AM_CONDITIONAL.
>>         * configure: Regenerate.
>>         * Makefile.am (TESTS): Add btest_dwz.
>>         * Makefile.in: Regenerate.
> 
>> diff --git a/libbacktrace/Makefile.am b/libbacktrace/Makefile.am
>> index 1a3680bc98c..497cc2f5c97 100644
>> --- a/libbacktrace/Makefile.am
>> +++ b/libbacktrace/Makefile.am
>> @@ -157,6 +157,18 @@ btest_alloc_LDADD = libbacktrace_alloc.la
>>
>>  check_PROGRAMS += btest_alloc
>>
>> +if HAVE_DWZ
>> +
>> +%_dwz: %
>> +       rm -f $@_common.debug
>> +       cp $< $@
>> +       cp $< $@_2
>> +       $(DWZ) -m $@_common.debug $@ $@_2
> 
> This doesn't look right.  A Makefile recipe must always create the
> target as the very last command.  Otherwise, if the recipe is
> interrupted for any reason, such as, in this case, a failure to run
> dwz, then when you run make again it will think that the recipe has
> already been run.

Fixed.

Thanks,
- Tom



[-- Attachment #2: 0008-libbacktrace-Add-btest_dwz-test-case.patch --]
[-- Type: text/x-patch, Size: 8151 bytes --]

[libbacktrace] Add btest_dwz test-case

Add test-case to verify that libbacktrace can read debug info that was
compressed with dwz.

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

	* configure.ac (DWZ): Set with AC_CHECK_PROG.
	(HAVE_DWZ): Set with AM_CONDITIONAL.
	* configure: Regenerate.
	* Makefile.am (TESTS): Add btest_dwz.
	* Makefile.in: Regenerate.

---
 libbacktrace/Makefile.am  | 13 +++++++++++
 libbacktrace/Makefile.in  | 33 ++++++++++++++++++++-------
 libbacktrace/configure    | 57 +++++++++++++++++++++++++++++++++++++++++++++--
 libbacktrace/configure.ac |  3 +++
 4 files changed, 96 insertions(+), 10 deletions(-)

diff --git a/libbacktrace/Makefile.am b/libbacktrace/Makefile.am
index 527353aa3f0..0331e9272e8 100644
--- a/libbacktrace/Makefile.am
+++ b/libbacktrace/Makefile.am
@@ -178,6 +178,19 @@ btest_alloc_LDADD = libbacktrace_alloc.la
 
 check_PROGRAMS += btest_alloc
 
+if HAVE_DWZ
+
+%_dwz: %
+	rm -f $@_common.debug
+	cp $< $@_1
+	cp $< $@_2
+	$(DWZ) -m $@_common.debug $@_1 $@_2
+	cp $@_1 $@
+
+TESTS += btest_dwz
+
+endif HAVE_DWZ
+
 stest_SOURCES = stest.c
 stest_LDADD = libbacktrace.la
 
diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index c595a8b4a3e..a7fa47fdb52 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -15,7 +15,7 @@
 @SET_MAKE@
 
 # Makefile.am -- Backtrace Makefile.
-# Copyright (C) 2012-2018 Free Software Foundation, Inc.
+# Copyright (C) 2012-2019 Free Software Foundation, Inc.
 
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
@@ -126,11 +126,12 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
 @NATIVE_TRUE@	allocfail btest btest_alloc stest stest_alloc \
 @NATIVE_TRUE@	ztest ztest_alloc edtest edtest_alloc
 @NATIVE_TRUE@am__append_2 = allocfail.sh
-@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_3 = -lz
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_3 = btest_dwz
 @HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_4 = -lz
-@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_5 = ttest ttest_alloc
-@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_6 = dtest
-@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_7 = ctestg ctesta \
+@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_5 = -lz
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_6 = ttest ttest_alloc
+@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_7 = dtest
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_8 = ctestg ctesta \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctestg_alloc \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctesta_alloc
 subdir = .
@@ -632,6 +633,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@
@@ -786,7 +788,8 @@ libbacktrace_la_LIBADD = \
 	$(ALLOC_FILE)
 
 libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
-TESTS = $(check_PROGRAMS) $(am__append_2) $(am__append_6)
+TESTS = $(check_PROGRAMS) $(am__append_2) $(am__append_3) \
+	$(am__append_7)
 @NATIVE_TRUE@check_LTLIBRARIES = libbacktrace_alloc.la \
 @NATIVE_TRUE@	libbacktrace_noformat.la \
 @NATIVE_TRUE@	libbacktrace_instrumented_alloc.la
@@ -831,9 +834,9 @@ TESTS = $(check_PROGRAMS) $(am__append_2) $(am__append_6)
 @NATIVE_TRUE@stest_alloc_LDADD = libbacktrace_alloc.la
 @NATIVE_TRUE@ztest_SOURCES = ztest.c testlib.c
 @NATIVE_TRUE@ztest_CFLAGS = -DSRCDIR=\"$(srcdir)\"
-@NATIVE_TRUE@ztest_LDADD = libbacktrace.la $(am__append_3) \
+@NATIVE_TRUE@ztest_LDADD = libbacktrace.la $(am__append_4) \
 @NATIVE_TRUE@	$(CLOCK_GETTIME_LINK)
-@NATIVE_TRUE@ztest_alloc_LDADD = libbacktrace_alloc.la $(am__append_4) \
+@NATIVE_TRUE@ztest_alloc_LDADD = libbacktrace_alloc.la $(am__append_5) \
 @NATIVE_TRUE@	$(CLOCK_GETTIME_LINK)
 @NATIVE_TRUE@ztest_alloc_SOURCES = $(ztest_SOURCES)
 @NATIVE_TRUE@ztest_alloc_CFLAGS = $(ztest_CFLAGS)
@@ -1575,6 +1578,13 @@ allocfail.sh.log: allocfail.sh
 	--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
+	@p='btest_dwz'; \
+	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)
 dtest.log: dtest
 	@p='dtest'; \
 	b='dtest'; \
@@ -1743,6 +1753,13 @@ uninstall-am:
 
 @NATIVE_TRUE@allocfail.sh: allocfail
 
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@%_dwz: %
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	rm -f $@_common.debug
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	cp $< $@_1
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	cp $< $@_2
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	$(DWZ) -m $@_common.debug $@_1 $@_2
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	cp $@_1 $@
+
 @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/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 c992675c621..c64bf3473bb 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
 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 1/9] [libbacktrace] Read .gnu_debugaltlink
  2019-01-16 16:26     ` Tom de Vries
@ 2019-01-16 17:15       ` Ian Lance Taylor via gcc-patches
  2019-01-16 22:48         ` Tom de Vries
  0 siblings, 1 reply; 47+ messages in thread
From: Ian Lance Taylor via gcc-patches @ 2019-01-16 17:15 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Wed, Jan 16, 2019 at 8:26 AM Tom de Vries <tdevries@suse.de> wrote:
>
> On 16-01-19 01:56, Ian Lance Taylor wrote:
> > On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
> >>
> >> Read the elf file pointed at by the .gnu_debugaltlink section, and verify that
> >> the build id matches.
> >>
> >> 2018-11-11  Tom de Vries  <tdevries@suse.de>
> >>
> >>         * elf.c (elf_add): Add and handle with_buildid_data and
> >>         with_buildid_size parameters.  Handle .gnu_debugaltlink section.
> >>         (phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
> >> ---
> >
> >
> >
> > @@ -2899,6 +2918,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;
> >> +       }
> >> +
> >
> > This doesn't look quite right.  debugaltlink_buildid_size is unsigned.
> > If there is some misunderstanding of the format it's possible for
> > strnlen to return shdr->sh_size.  If it does,
> > debugaltlink_buildid_size will be set to a very large value.
> >
>
> I see, thanks for finding that.
>
> Fixed like this:
> ...
>     debugaltlink_name_len = strnlen (debugaltlink_data, shdr->sh_size);
>     if (debugaltlink_name_len < shdr->sh_size)
>       {
>         /* Include terminating zero.  */
>         debugaltlink_name_len =+ 1;
>
>         debugaltlink_buildid_data
>           = debugaltlink_data + debugaltlink_name_len;
>         debugaltlink_buildid_size
>           = shdr->sh_size - debugaltlink_name_len;
>       }
> ...
>
> >> +  if (debugaltlink_name != NULL)
> >> +    {
> >> +      int d;
> >> +
> >> +      d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name,
> >> +                                          0, 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, 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;
> >> +           }
> >> +       }
> >> +      else
> >> +       {
> >> +         error_callback (data,
> >> +                         "Could not open .gnu_debugaltlink", 0);
> >> +         /* Don't goto fail, but try continue without the info in the
> >> +            .gnu_debugaltlink.  */
> >> +       }
> >> +    }
> >
> > The strings passed to error_callback always start with a lowercase
> > letter (unless they start with something like ELF) because the
> > callback will most likely print them with some prefix.
> >
>
> Fixed.
>
> > More seriously, we don't call error_callback in any cases that
> > correspond to this.  We just carry on.
>
> Indeed, I noticed that, and filed PR88244 - "[libbacktrace] Failure to
> open .gnu_debuglink is silent".
>
> [ The scenario there is: an executable has a .gnu_debuglink, but the
> file the .gnu_debuglink is pointing to is absent, because f.i. it has
> been removed, or moved to a different location. If a user runs this
> executable and a backtrace is triggered, the information relating to the
> functions in the executable will be missing in the backtrace, but
> there's no error explaining to the user why that information is missing.
>  Note: there is a default error "no debug info in ELF executable" in
> elf_nodebug, but AFAIU this is not triggered if debug info for one of
> the shared libraries is present. ]
>
> BTW, though in the code above an error_callback is called, we don't
> error out, but do carry on afterwards (as the comment explicitly states).
>
> > Is there any reason to call
> > error_callback here?
>
> A similar scenario: an executable has a .gnu_altdebuglink, but the file
> the .gnu_debugaltlink is pointing to is absent, because f.i. it has been
> removed, or moved to a different location. If a user runs this
> executable and a backtrace is triggered, the information stored in the
> .gnu_debugaltlink file will be missing in the backtrace, but there's no
> error explaining to the user why that information is missing.

The problem is that libbacktrace is often run in cases where it needs
to present best effort information.  But the error_callback is
currently only called for cases where it can't present any information
at all.  You are suggesting that we call it and then carry on.  But
currently we don't do that (as far as I know); we call it and then
fail.  For example, in libgo, if the error_callback function is
called, the program will print the error and then crash.  So while I
understand your desire to present a warning message to the user about
a missing file, I don't think we should use the existing
error_callback mechanism to do so.  I think we'll need to introduce
some way to let error_callback know that this is a warning rather than
an error.  Unfortunately changing the actual API at this point would
be somewhat painful.  Still, we should either do that, or introduce
some convention like "if MSG starts with a '-' then this is just a
warning."  Any thoughts?

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data
  2019-01-16 16:33     ` Tom de Vries
  2019-01-16 16:34       ` Tom de Vries
@ 2019-01-16 17:17       ` Ian Lance Taylor
  2019-01-16 22:18         ` Tom de Vries
  1 sibling, 1 reply; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-16 17:17 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Wed, Jan 16, 2019 at 8:33 AM Tom de Vries <tdevries@suse.de> wrote:
>
> > Why is it void**?
>
> It's really struct dwarf_data *, but struct dwarf_data is a type
> declared in dwarf.c, so it's not known in other files.

It woud be OK to add "struct dwarf_data;" to internal.h and refer to
the struct, without dereferencing it, in elf.c.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 3/9] [libbacktrace] Handle alt FORMS without .gnu_debugaltlink
  2019-01-16 16:34     ` Tom de Vries
@ 2019-01-16 18:24       ` Ian Lance Taylor
  0 siblings, 0 replies; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-16 18:24 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Wed, Jan 16, 2019 at 8:35 AM Tom de Vries <tdevries@suse.de> wrote:
>
> On 16-01-19 02:06, Ian Lance Taylor wrote:
> > On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
> >>
> >> Handle DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt references robustly in
> >> presence of missing .gnu_debugaltlink file.
> >>
> >> 2018-11-11  Tom de Vries  <tdevries@suse.de>
> >>
> >>         * dwarf.c (enum attr_val_encoding): Add ATTR_VAL_NONE.
> >>         (read_attribute): Add altlink parameter.  Handle missing altlink for
> >>         DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt.
> >>         (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.
> >
> >
> >
> >>  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)
> >>  {
> >
> > altlink is not a result parameter, so it should be before val.
> >
> >
>
> Done.
>
> >> @@ -1277,7 +1289,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)
> >
> > Same.  altlink should be before the error_callback parameter.
> >
> >
>
> Done.
>
> >> @@ -1431,7 +1444,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)
> >
> > Same.
> >
>
> Done.

This patch is OK.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 6/9] [libbacktrace] Factor out read_referenced_name_1
  2019-01-16 16:37     ` Tom de Vries
@ 2019-01-16 18:26       ` Ian Lance Taylor
  0 siblings, 0 replies; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-16 18:26 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Wed, Jan 16, 2019 at 8:37 AM Tom de Vries <tdevries@suse.de> wrote:
>
> On 16-01-19 02:15, Ian Lance Taylor wrote:
> > On Tue, Dec 11, 2018 at 2:15 AM Tom de Vries <tdevries@suse.de> wrote:
> >>
> >> Factor out the common handling of DW_AT_abstract_origin and
> >> DW_AT_specification from read_function_entry and read_referenced_name.
> >>
> >> 2018-12-10  Tom de Vries  <tdevries@suse.de>
> >>
> >>         * dwarf.c (read_referenced_name_1): New function.  Factor out of ...
> >>         (read_referenced_name): ... here, and ...
> >>         (read_function_entry): ... here.
> >
> >> +static const char *read_referenced_name (struct dwarf_data *, struct unit *,
> >> +                                        uint64_t, backtrace_error_callback,
> >> +                                        void *);
> >> +
> >
> > We don't need this declaration.  Only add a static declaration if
> > there is a forward reference.
> >
> >
>
> We need this static declaration because there's a forward reference to
> read_referenced_name in read_referenced_name_1.

Whoops, sorry.

This patch is OK.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 8/9] [libbacktrace] Add btest_dwz test-case
  2019-01-16 16:39     ` Tom de Vries
@ 2019-01-16 18:30       ` Ian Lance Taylor
  0 siblings, 0 replies; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-16 18:30 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Wed, Jan 16, 2019 at 8:39 AM Tom de Vries <tdevries@suse.de> wrote:
>
> On 16-01-19 02:19, Ian Lance Taylor wrote:
> > On Tue, Dec 11, 2018 at 2:16 AM Tom de Vries <tdevries@suse.de> wrote:
> >>
> >> 2018-11-11  Tom de Vries  <tdevries@suse.de>
> >>
> >>         * configure.ac (DWZ): Set with AC_CHECK_PROG.
> >>         (HAVE_DWZ): Set with AM_CONDITIONAL.
> >>         * configure: Regenerate.
> >>         * Makefile.am (TESTS): Add btest_dwz.
> >>         * Makefile.in: Regenerate.
> >
> >> diff --git a/libbacktrace/Makefile.am b/libbacktrace/Makefile.am
> >> index 1a3680bc98c..497cc2f5c97 100644
> >> --- a/libbacktrace/Makefile.am
> >> +++ b/libbacktrace/Makefile.am
> >> @@ -157,6 +157,18 @@ btest_alloc_LDADD = libbacktrace_alloc.la
> >>
> >>  check_PROGRAMS += btest_alloc
> >>
> >> +if HAVE_DWZ
> >> +
> >> +%_dwz: %
> >> +       rm -f $@_common.debug
> >> +       cp $< $@
> >> +       cp $< $@_2
> >> +       $(DWZ) -m $@_common.debug $@ $@_2
> >
> > This doesn't look right.  A Makefile recipe must always create the
> > target as the very last command.  Otherwise, if the recipe is
> > interrupted for any reason, such as, in this case, a failure to run
> > dwz, then when you run make again it will think that the recipe has
> > already been run.
>
> Fixed.

> +%_dwz: %
> +         rm -f $@_common.debug

Add $@ to the initial rm -f, so that you remove the target.

> +         cp $@_1 $@

Make this a mv.  You don't need $@_1 after this.  Also, rm $@_2 here
or in mostlyclean or something.

This is OK with those changes.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data
  2019-01-16 17:17       ` Ian Lance Taylor
@ 2019-01-16 22:18         ` Tom de Vries
  2019-01-16 22:40           ` Ian Lance Taylor
  0 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-16 22:18 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 431 bytes --]

On 16-01-19 18:17, Ian Lance Taylor wrote:
> On Wed, Jan 16, 2019 at 8:33 AM Tom de Vries <tdevries@suse.de> wrote:
>>
>>> Why is it void**?
>>
>> It's really struct dwarf_data *, but struct dwarf_data is a type
>> declared in dwarf.c, so it's not known in other files.
> 
> It woud be OK to add "struct dwarf_data;" to internal.h and refer to
> the struct, without dereferencing it, in elf.c.

Updated accordingly.

Thanks,
- Tom

[-- Attachment #2: 0003-libbacktrace-Return-struct-dwarf_data-pointer-from-elf_add.patch --]
[-- Type: text/x-patch, Size: 6515 bytes --]

[libbacktrace] Return struct dwarf_data pointer from elf_add

Allow the caller of elf_add access to the struct dwarf_data pointer
corresponding to the added elf.

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

	* internal.h (backtrace_dwarf_add): Add fileline_entry parameter.
	* dwarf.c (backtrace_dwarf_add): Add and handle fileline_entry parameter.
	* elf.c	(elf_add): Add and handle fileline_entry parameter.  Add
	argument to backtrace_dwarf_add call.
	(phdr_callback, backtrace_initialize): Add argument to elf_add calls.
	* pecoff.c (coff_add): Add argument to backtrace_dwarf_add call.
	* xcoff.c (xcoff_add): Same.

---
 libbacktrace/dwarf.c    |  6 +++++-
 libbacktrace/elf.c      | 23 ++++++++++++++---------
 libbacktrace/internal.h |  5 ++++-
 libbacktrace/pecoff.c   |  3 ++-
 libbacktrace/xcoff.c    |  3 ++-
 5 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index dca5d909d9f..190c6fc131f 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -3064,7 +3064,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,
+		     struct dwarf_data **fileline_entry)
 {
   struct dwarf_data *fdata;
 
@@ -3076,6 +3077,9 @@ backtrace_dwarf_add (struct backtrace_state *state,
   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 e363e470525..2841c06cdb2 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -2638,8 +2638,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, const char *with_buildid_data,
-	 uint32_t with_buildid_size)
+	 struct dwarf_data **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;
@@ -3042,7 +3042,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	    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, NULL, 0);
+			 fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL,
+			 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3080,7 +3081,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	    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, NULL, 0);
+			 fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL,
+			 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3106,8 +3108,9 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	  int ret;
 
 	  ret = elf_add (state, filename, d, base_address, error_callback, data,
-			 fileline_fn, found_sym, found_dwarf, 0, 1,
-			 debugaltlink_buildid_data, debugaltlink_buildid_size);
+			 fileline_fn, found_sym, found_dwarf, NULL,
+			 0, 1, debugaltlink_buildid_data,
+			 debugaltlink_buildid_size);
 	  backtrace_release_view (state, &debugaltlink_view, error_callback,
 				  data);
 	  debugaltlink_view_valid = 0;
@@ -3269,7 +3272,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))
     goto fail;
 
   *found_dwarf = 1;
@@ -3359,7 +3363,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, NULL, 0))
+	       &found_dwarf, NULL, 0, 0, NULL, 0))
     {
       if (found_dwarf)
 	{
@@ -3387,7 +3391,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, NULL, 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 bf3e7d1989f..d9ab401ce41 100644
--- a/libbacktrace/internal.h
+++ b/libbacktrace/internal.h
@@ -286,6 +286,8 @@ extern int backtrace_initialize (struct backtrace_state *state,
 				 void *data,
 				 fileline *fileline_fn);
 
+struct dwarf_data;
+
 /* Add file/line information for a DWARF module.  */
 
 extern int backtrace_dwarf_add (struct backtrace_state *state,
@@ -302,7 +304,8 @@ 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,
+				struct dwarf_data **fileline_entry);
 
 /* A test-only hook for elf_uncompress_zdebug.  */
 
diff --git a/libbacktrace/pecoff.c b/libbacktrace/pecoff.c
index f51fc0f13c5..cd20cbe17a7 100644
--- a/libbacktrace/pecoff.c
+++ b/libbacktrace/pecoff.c
@@ -867,7 +867,8 @@ coff_add (struct backtrace_state *state, int descriptor,
 			    sections[DEBUG_STR].data,
 			    sections[DEBUG_STR].size,
 			    0, /* FIXME */
-			    error_callback, data, fileline_fn))
+			    error_callback, data, fileline_fn,
+			    NULL))
     goto fail;
 
   *found_dwarf = 1;
diff --git a/libbacktrace/xcoff.c b/libbacktrace/xcoff.c
index 111134d4d21..095800b4f71 100644
--- a/libbacktrace/xcoff.c
+++ b/libbacktrace/xcoff.c
@@ -1315,7 +1315,8 @@ xcoff_add (struct backtrace_state *state, int descriptor, off_t offset,
 				dwsect[DWSECT_STR].data,
 				dwsect[DWSECT_STR].size,
 				1, /* big endian */
-				error_callback, data, fileline_fn))
+				error_callback, data, fileline_fn,
+				NULL))
 	goto fail;
     }
 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data
  2019-01-16 16:34       ` Tom de Vries
@ 2019-01-16 22:20         ` Tom de Vries
  2019-01-16 22:25           ` Ian Lance Taylor
  0 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-16 22:20 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2911 bytes --]

On 16-01-19 17:34, Tom de Vries wrote:
> On 16-01-19 17:33, Tom de Vries wrote:
>> On 16-01-19 02:02, Ian Lance Taylor wrote:
>>> On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
>>>>
>>>> Add an altlink field to struct dwarf_data, and initialize it with the pointer
>>>> to the struct dwarf_data for the .gnu_debugaltlink.
>>>>
>>>> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>>>>
>>>>         * dwarf.c (struct dwarf_data): Add altlink field.
>>>>         (backtrace_dwarf_add): Add and handle fileline_entry and
>>>>         fileline_altlink parameters.
>>>>         * elf.c (elf_add): Add and handle fileline_entry parameter.  Add args to
>>>>         backtrace_dwarf_add call.
>>>>         (phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
>>>>         * internal.h (backtrace_dwarf_add): Add fileline_entry and
>>>>         fileline_altlink parameters.
>>>>         * pecoff.c (coff_add): Add args to backtrace_dwarf_add call.
>>>>         * xcoff.c (xcoff_add): Same.
>>>
>>>
>>>> @@ -2968,7 +2970,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)
>>>>  {
>>>
>>> error_callback and data should remain the last two parameters, as they
>>> are for many of the functions in this file.
>>>
>>>
>>
>> Done.
>>
>>>>   @@ -3031,7 +3034,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)
>>>
>>> The new fileline_altlink parameter should come before error_callback,
>>> as it is not error_callback/data and is not a result parameter.
>>>
>>
>> Done.
>>
>>> What is fileline_entry for? 
>>
>> There are two bits to this patch:
>> - add fileline_entry parameter to elf_add.  This allows the callers of
>>   elf_add access to the struct dwarf_data pointer corresponding to the
>>   added elf.
>> - add an altlink field to struct dwarf_data, and initialize it with the
>>   pointer to the struct dwarf_data for the .gnu_debugaltlink.
>>
>> I've split the patch up this way now, hoping it will make things clearer
>> and/or easier to review.
>>
>>> Why is it void**?
>>
>> It's really struct dwarf_data *, but struct dwarf_data is a type
>> declared in dwarf.c, so it's not known in other files.
>>
>> Thanks,
>> - Tom
>>
>> Here's the first part.
>>
> 
> And here's the second part.

Updated to use 'struct dwarf_data' instead of 'void'.

Thanks,
- Tom
> 

[-- Attachment #2: 0004-libbacktrace-Add-altlink-field-to-struct-dwarf_data.patch --]
[-- Type: text/x-patch, Size: 4996 bytes --]

[libbacktrace] Add altlink field to struct dwarf_data

Add an altlink field to struct dwarf_data, and initialize it with the pointer
to the struct dwarf_data for the .gnu_debugaltlink.

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

	* dwarf.c (struct dwarf_data): Add altlink field.
	(backtrace_dwarf_add): Add and handle fileline_altlink parameter.
	* elf.c	(elf_add): Add argument to backtrace_dwarf_add call.
	(phdr_callback, backtrace_initialize): Add argument to elf_add calls.
	* internal.h (backtrace_dwarf_add): Add fileline_altlink parameter.
	* pecoff.c (coff_add): Add argument to backtrace_dwarf_add call.
	* xcoff.c (xcoff_add): Same.

---
 libbacktrace/dwarf.c    | 7 ++++++-
 libbacktrace/elf.c      | 4 +++-
 libbacktrace/internal.h | 1 +
 libbacktrace/pecoff.c   | 1 +
 libbacktrace/xcoff.c    | 1 +
 5 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 190c6fc131f..83cdb52ef26 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.  */
@@ -3000,6 +3002,7 @@ build_dwarf_data (struct backtrace_state *state,
 		  const unsigned char *dwarf_str,
 		  size_t dwarf_str_size,
 		  int is_bigendian,
+		  struct dwarf_data *altlink,
 		  backtrace_error_callback error_callback,
 		  void *data)
 {
@@ -3028,6 +3031,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;
@@ -3063,6 +3067,7 @@ backtrace_dwarf_add (struct backtrace_state *state,
 		     const unsigned char *dwarf_str,
 		     size_t dwarf_str_size,
 		     int is_bigendian,
+		     struct dwarf_data *fileline_altlink,
 		     backtrace_error_callback error_callback,
 		     void *data, fileline *fileline_fn,
 		     struct dwarf_data **fileline_entry)
@@ -3073,7 +3078,7 @@ 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);
+			    fileline_altlink, error_callback, data);
   if (fdata == NULL)
     return 0;
 
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index 2841c06cdb2..36b20cba149 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -3097,6 +3097,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
       debuglink_view_valid = 0;
     }
 
+  struct dwarf_data *fileline_altlink = NULL;
   if (debugaltlink_name != NULL)
     {
       int d;
@@ -3108,7 +3109,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	  int ret;
 
 	  ret = elf_add (state, filename, d, base_address, error_callback, data,
-			 fileline_fn, found_sym, found_dwarf, NULL,
+			 fileline_fn, found_sym, found_dwarf, &fileline_altlink,
 			 0, 1, debugaltlink_buildid_data,
 			 debugaltlink_buildid_size);
 	  backtrace_release_view (state, &debugaltlink_view, error_callback,
@@ -3272,6 +3273,7 @@ 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,
+			    fileline_altlink,
 			    error_callback, data, fileline_fn,
 			    fileline_entry))
     goto fail;
diff --git a/libbacktrace/internal.h b/libbacktrace/internal.h
index d9ab401ce41..e8389779322 100644
--- a/libbacktrace/internal.h
+++ b/libbacktrace/internal.h
@@ -303,6 +303,7 @@ extern int backtrace_dwarf_add (struct backtrace_state *state,
 				const unsigned char *dwarf_str,
 				size_t dwarf_str_size,
 				int is_bigendian,
+				struct dwarf_data *fileline_altlink,
 				backtrace_error_callback error_callback,
 				void *data, fileline *fileline_fn,
 				struct dwarf_data **fileline_entry);
diff --git a/libbacktrace/pecoff.c b/libbacktrace/pecoff.c
index cd20cbe17a7..da1982fd3ca 100644
--- a/libbacktrace/pecoff.c
+++ b/libbacktrace/pecoff.c
@@ -867,6 +867,7 @@ coff_add (struct backtrace_state *state, int descriptor,
 			    sections[DEBUG_STR].data,
 			    sections[DEBUG_STR].size,
 			    0, /* FIXME */
+			    NULL,
 			    error_callback, data, fileline_fn,
 			    NULL))
     goto fail;
diff --git a/libbacktrace/xcoff.c b/libbacktrace/xcoff.c
index 095800b4f71..d50b5bc517e 100644
--- a/libbacktrace/xcoff.c
+++ b/libbacktrace/xcoff.c
@@ -1315,6 +1315,7 @@ xcoff_add (struct backtrace_state *state, int descriptor, off_t offset,
 				dwsect[DWSECT_STR].data,
 				dwsect[DWSECT_STR].size,
 				1, /* big endian */
+				NULL,
 				error_callback, data, fileline_fn,
 				NULL))
 	goto fail;

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data
  2019-01-16 22:20         ` Tom de Vries
@ 2019-01-16 22:25           ` Ian Lance Taylor
  0 siblings, 0 replies; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-16 22:25 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Wed, Jan 16, 2019 at 2:20 PM Tom de Vries <tdevries@suse.de> wrote:
>
> On 16-01-19 17:34, Tom de Vries wrote:
> > On 16-01-19 17:33, Tom de Vries wrote:
> >> On 16-01-19 02:02, Ian Lance Taylor wrote:
> >>> On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
> >>>>
> >>>> Add an altlink field to struct dwarf_data, and initialize it with the pointer
> >>>> to the struct dwarf_data for the .gnu_debugaltlink.
> >>>>
> >>>> 2018-11-11  Tom de Vries  <tdevries@suse.de>
> >>>>
> >>>>         * dwarf.c (struct dwarf_data): Add altlink field.
> >>>>         (backtrace_dwarf_add): Add and handle fileline_entry and
> >>>>         fileline_altlink parameters.
> >>>>         * elf.c (elf_add): Add and handle fileline_entry parameter.  Add args to
> >>>>         backtrace_dwarf_add call.
> >>>>         (phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
> >>>>         * internal.h (backtrace_dwarf_add): Add fileline_entry and
> >>>>         fileline_altlink parameters.
> >>>>         * pecoff.c (coff_add): Add args to backtrace_dwarf_add call.
> >>>>         * xcoff.c (xcoff_add): Same.
> >>>
> >>>
> >>>> @@ -2968,7 +2970,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)
> >>>>  {
> >>>
> >>> error_callback and data should remain the last two parameters, as they
> >>> are for many of the functions in this file.
> >>>
> >>>
> >>
> >> Done.
> >>
> >>>>   @@ -3031,7 +3034,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)
> >>>
> >>> The new fileline_altlink parameter should come before error_callback,
> >>> as it is not error_callback/data and is not a result parameter.
> >>>
> >>
> >> Done.
> >>
> >>> What is fileline_entry for?
> >>
> >> There are two bits to this patch:
> >> - add fileline_entry parameter to elf_add.  This allows the callers of
> >>   elf_add access to the struct dwarf_data pointer corresponding to the
> >>   added elf.
> >> - add an altlink field to struct dwarf_data, and initialize it with the
> >>   pointer to the struct dwarf_data for the .gnu_debugaltlink.
> >>
> >> I've split the patch up this way now, hoping it will make things clearer
> >> and/or easier to review.
> >>
> >>> Why is it void**?
> >>
> >> It's really struct dwarf_data *, but struct dwarf_data is a type
> >> declared in dwarf.c, so it's not known in other files.
> >>
> >> Thanks,
> >> - Tom
> >>
> >> Here's the first part.
> >>
> >
> > And here's the second part.
>
> Updated to use 'struct dwarf_data' instead of 'void'.

I think you need to explicitly add a standalone line

struct dwarf_data;

 in internal.h before the declaration of backtrace_dwarf_add to avoid
compiler warnings in some cases.  (Like the declaration of
backtrace_state in backtrace.h.)

This is OK with that change.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data
  2019-01-16 22:18         ` Tom de Vries
@ 2019-01-16 22:40           ` Ian Lance Taylor
  0 siblings, 0 replies; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-16 22:40 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Wed, Jan 16, 2019 at 2:18 PM Tom de Vries <tdevries@suse.de> wrote:
>
> On 16-01-19 18:17, Ian Lance Taylor wrote:
> > On Wed, Jan 16, 2019 at 8:33 AM Tom de Vries <tdevries@suse.de> wrote:
> >>
> >>> Why is it void**?
> >>
> >> It's really struct dwarf_data *, but struct dwarf_data is a type
> >> declared in dwarf.c, so it's not known in other files.
> >
> > It woud be OK to add "struct dwarf_data;" to internal.h and refer to
> > the struct, without dereferencing it, in elf.c.
>
> Updated accordingly.

This is OK.

Thanks.

I see that the struct declaration is in this patch.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 1/9] [libbacktrace] Read .gnu_debugaltlink
  2019-01-16 17:15       ` Ian Lance Taylor via gcc-patches
@ 2019-01-16 22:48         ` Tom de Vries
  2019-01-16 23:21           ` Ian Lance Taylor
  0 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-16 22:48 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 7429 bytes --]

On 16-01-19 18:14, Ian Lance Taylor wrote:
> On Wed, Jan 16, 2019 at 8:26 AM Tom de Vries <tdevries@suse.de> wrote:
>>
>> On 16-01-19 01:56, Ian Lance Taylor wrote:
>>> On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
>>>>
>>>> Read the elf file pointed at by the .gnu_debugaltlink section, and verify that
>>>> the build id matches.
>>>>
>>>> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>>>>
>>>>         * elf.c (elf_add): Add and handle with_buildid_data and
>>>>         with_buildid_size parameters.  Handle .gnu_debugaltlink section.
>>>>         (phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
>>>> ---
>>>
>>>
>>>
>>> @@ -2899,6 +2918,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;
>>>> +       }
>>>> +
>>>
>>> This doesn't look quite right.  debugaltlink_buildid_size is unsigned.
>>> If there is some misunderstanding of the format it's possible for
>>> strnlen to return shdr->sh_size.  If it does,
>>> debugaltlink_buildid_size will be set to a very large value.
>>>
>>
>> I see, thanks for finding that.
>>
>> Fixed like this:
>> ...
>>     debugaltlink_name_len = strnlen (debugaltlink_data, shdr->sh_size);
>>     if (debugaltlink_name_len < shdr->sh_size)
>>       {
>>         /* Include terminating zero.  */
>>         debugaltlink_name_len =+ 1;
>>
>>         debugaltlink_buildid_data
>>           = debugaltlink_data + debugaltlink_name_len;
>>         debugaltlink_buildid_size
>>           = shdr->sh_size - debugaltlink_name_len;
>>       }
>> ...
>>
>>>> +  if (debugaltlink_name != NULL)
>>>> +    {
>>>> +      int d;
>>>> +
>>>> +      d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name,
>>>> +                                          0, 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, 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;
>>>> +           }
>>>> +       }
>>>> +      else
>>>> +       {
>>>> +         error_callback (data,
>>>> +                         "Could not open .gnu_debugaltlink", 0);
>>>> +         /* Don't goto fail, but try continue without the info in the
>>>> +            .gnu_debugaltlink.  */
>>>> +       }
>>>> +    }
>>>
>>> The strings passed to error_callback always start with a lowercase
>>> letter (unless they start with something like ELF) because the
>>> callback will most likely print them with some prefix.
>>>
>>
>> Fixed.
>>
>>> More seriously, we don't call error_callback in any cases that
>>> correspond to this.  We just carry on.
>>
>> Indeed, I noticed that, and filed PR88244 - "[libbacktrace] Failure to
>> open .gnu_debuglink is silent".
>>
>> [ The scenario there is: an executable has a .gnu_debuglink, but the
>> file the .gnu_debuglink is pointing to is absent, because f.i. it has
>> been removed, or moved to a different location. If a user runs this
>> executable and a backtrace is triggered, the information relating to the
>> functions in the executable will be missing in the backtrace, but
>> there's no error explaining to the user why that information is missing.
>>  Note: there is a default error "no debug info in ELF executable" in
>> elf_nodebug, but AFAIU this is not triggered if debug info for one of
>> the shared libraries is present. ]
>>
>> BTW, though in the code above an error_callback is called, we don't
>> error out, but do carry on afterwards (as the comment explicitly states).
>>
>>> Is there any reason to call
>>> error_callback here?
>>
>> A similar scenario: an executable has a .gnu_altdebuglink, but the file
>> the .gnu_debugaltlink is pointing to is absent, because f.i. it has been
>> removed, or moved to a different location. If a user runs this
>> executable and a backtrace is triggered, the information stored in the
>> .gnu_debugaltlink file will be missing in the backtrace, but there's no
>> error explaining to the user why that information is missing.
> 
> The problem is that libbacktrace is often run in cases where it needs
> to present best effort information.  But the error_callback is
> currently only called for cases where it can't present any information
> at all.  You are suggesting that we call it and then carry on.  But
> currently we don't do that (as far as I know); we call it and then
> fail.  For example, in libgo, if the error_callback function is
> called, the program will print the error and then crash.

Aha, I see.

> So while I
> understand your desire to present a warning message to the user about
> a missing file, I don't think we should use the existing
> error_callback mechanism to do so.

Agreed.

> I think we'll need to introduce
> some way to let error_callback know that this is a warning rather than
> an error.  Unfortunately changing the actual API at this point would
> be somewhat painful.  Still, we should either do that, or introduce
> some convention like "if MSG starts with a '-' then this is just a
> warning."  Any thoughts?

I think the "if MSG starts with a '-' then this is just a warning"
convention will break existing clients.

An easy solution that would be backward compatible would be to add
versions of each function that accepts an error callback, that also
accepts a warning call back, say for:
...
extern struct backtrace_state *backtrace_create_state (
    const char *filename,
    int threaded,
    backtrace_error_callback error_callback,
    void *data);
...

we add:
...
extern struct backtrace_state *backtrace_create_state_with_warning (
    const char *filename,
    int threaded,
    backtrace_error_callback error_callback,
    backtrace_warning_callback warning_call,
    void *data);
...

Each client would continue to work as before. And if a client want
warnings it could enable this by using the _with_warning variants of the
API functions.

For now, I've dropped the error callback for .gnu_debugaltlink.

Thanks,
- Tom


[-- Attachment #2: 0002-libbacktrace-Read-.gnu_debugaltlink.patch --]
[-- Type: text/x-patch, Size: 7405 bytes --]

[libbacktrace] Read .gnu_debugaltlink

Read the elf file pointed at by the .gnu_debugaltlink section, and verify that
the build id matches.

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

	* elf.c (elf_add): Add and handle with_buildid_data and
	with_buildid_size parameters.  Handle .gnu_debugaltlink section.
	(phdr_callback, backtrace_initialize): Add arguments to elf_add calls.

---
 libbacktrace/Makefile.in |  2 +-
 libbacktrace/elf.c       | 93 +++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 89 insertions(+), 6 deletions(-)

diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index c595a8b4a3e..17e7ea86879 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -15,7 +15,7 @@
 @SET_MAKE@
 
 # Makefile.am -- Backtrace Makefile.
-# Copyright (C) 2012-2018 Free Software Foundation, Inc.
+# Copyright (C) 2012-2019 Free Software Foundation, Inc.
 
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index 85a323c5876..abe4cded5e9 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -2638,7 +2638,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)
+	 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 +2671,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 +2700,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 +2883,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 +2918,32 @@ 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);
+	  if (debugaltlink_name_len < shdr->sh_size)
+	    {
+	      /* Include terminating zero.  */
+	      debugaltlink_name_len =+ 1;
+
+	      debugaltlink_buildid_data
+		= debugaltlink_data + debugaltlink_name_len;
+	      debugaltlink_buildid_size = shdr->sh_size - debugaltlink_name_len;
+	    }
+	}
+
       /* Read the .opd section on PowerPC64 ELFv1.  */
       if (ehdr.e_machine == EM_PPC64
 	  && (ehdr.e_flags & EF_PPC64_ABI) < 2
@@ -2993,8 +3038,11 @@ 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, 0, 1, NULL, 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3028,8 +3076,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 
 	  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, 0, 1, NULL, 0);
 	  if (ret < 0)
 	    backtrace_close (d, error_callback, data);
 	  else
@@ -3044,6 +3095,36 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
       debuglink_view_valid = 0;
     }
 
+  if (debugaltlink_name != NULL)
+    {
+      int d;
+
+      d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name,
+					   0, 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, 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.  */
 
@@ -3199,6 +3280,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 +3352,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, 0, 0, NULL, 0))
     {
       if (found_dwarf)
 	{
@@ -3297,7 +3380,7 @@ 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, 1, 0, NULL, 0);
   if (!ret)
     return 0;
 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 1/9] [libbacktrace] Read .gnu_debugaltlink
  2019-01-16 22:48         ` Tom de Vries
@ 2019-01-16 23:21           ` Ian Lance Taylor
  0 siblings, 0 replies; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-16 23:21 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Wed, Jan 16, 2019 at 2:48 PM Tom de Vries <tdevries@suse.de> wrote:
>
> For now, I've dropped the error callback for .gnu_debugaltlink.

This version is OK.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 7/9] [libbacktrace] Handle DW_FORM_GNU_ref_alt
  2018-12-11 10:14 ` [PATCH 7/9] [libbacktrace] Handle DW_FORM_GNU_ref_alt Tom de Vries
@ 2019-01-17  0:17   ` Tom de Vries
  2019-01-17  0:36     ` Ian Lance Taylor
  0 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-17  0:17 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ian Lance Taylor

Hi,

this handles DW_FORM_GNU_ref_alt which references the .debug_info
section in the .gnu_debugaltlink file.

OK for trunk?

Thanks,
- Tom

On 11-12-18 11:14, Tom de Vries wrote:
> 2018-12-10  Tom de Vries  <tdevries@suse.de>
> 
> 	* dwarf.c (enum attr_val_encoding): Add ATTR_VAL_REF_ALT_INFO.
> 	(struct unit): Add low and high fields.
> 	(struct unit_vector): New type.
> 	(struct dwarf_data): Add units and units_counts fields.
> 	(read_attribute): Handle DW_FORM_GNU_ref_alt using
> 	ATTR_VAL_REF_ALT_INFO.
> 	(find_unit): New function.
> 	(find_address_ranges): Add and handle unit_tag parameter.
> 	(build_address_map): Add and handle units_vec parameter.
> 	(read_referenced_name_1): Handle DW_FORM_GNU_ref_alt.
> 	(build_dwarf_data): Pass units_vec to build_address_map.  Store resulting
> 	units vector.
> ---
>  libbacktrace/dwarf.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 91 insertions(+), 10 deletions(-)
> 
> diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
> index 99e5f4c3f51..9a0b93120c8 100644
> --- a/libbacktrace/dwarf.c
> +++ b/libbacktrace/dwarf.c
> @@ -143,6 +143,8 @@ enum attr_val_encoding
>    ATTR_VAL_REF_UNIT,
>    /* An offset to other data within the .dwarf_info section.  */
>    ATTR_VAL_REF_INFO,
> +  /* An offset to other data within the alt .dwarf_info section.  */
> +  ATTR_VAL_REF_ALT_INFO,
>    /* An offset to data in some other section.  */
>    ATTR_VAL_REF_SECTION,
>    /* A type signature.  */
> @@ -281,6 +283,10 @@ struct unit
>    /* The offset of UNIT_DATA from the start of the information for
>       this compilation unit.  */
>    size_t unit_data_offset;
> +  /* Start of the compilation unit.  */
> +  size_t low;
> +  /* End of the compilation unit.  */
> +  size_t high;
>    /* DWARF version.  */
>    int version;
>    /* Whether unit is DWARF64.  */
> @@ -339,6 +345,14 @@ struct unit_addrs_vector
>    size_t count;
>  };
>  
> +/* A growable vector of compilation unit pointer.  */
> +
> +struct unit_vector
> +{
> +  struct backtrace_vector vec;
> +  size_t count;
> +};
> +
>  /* The information we need to map a PC to a file and line.  */
>  
>  struct dwarf_data
> @@ -353,6 +367,10 @@ struct dwarf_data
>    struct unit_addrs *addrs;
>    /* Number of address ranges in list.  */
>    size_t addrs_count;
> +  /* A sorted list of units.  */
> +  struct unit **units;
> +  /* Number of units in the list.  */
> +  size_t units_count;
>    /* The unparsed .debug_info section.  */
>    const unsigned char *dwarf_info;
>    size_t dwarf_info_size;
> @@ -840,7 +858,7 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
>  	  val->encoding = ATTR_VAL_NONE;
>  	  return 1;
>  	}
> -      val->encoding = ATTR_VAL_REF_SECTION;
> +      val->encoding = ATTR_VAL_REF_ALT_INFO;
>        return 1;
>      case DW_FORM_GNU_strp_alt:
>        {
> @@ -866,6 +884,34 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
>      }
>  }
>  
> +/* Compare a unit offset against a unit for bsearch.  */
> +
> +static int
> +units_search (const void *vkey, const void *ventry)
> +{
> +  const uintptr_t *key = (const uintptr_t *) vkey;
> +  const struct unit *entry = *((const struct unit *const *) ventry);
> +  uintptr_t offset;
> +
> +  offset = *key;
> +  if (offset < entry->low)
> +    return -1;
> +  else if (offset >= entry->high)
> +    return 1;
> +  else
> +    return 0;
> +}
> +
> +/* Find a unit in PU containing OFFSET.  */
> +
> +static struct unit *
> +find_unit (struct unit **pu, size_t units_count, size_t offset)
> +{
> +  struct unit **u;
> +  u = bsearch (&offset, pu, units_count, sizeof (struct unit *), units_search);
> +  return u == NULL ? NULL : *u;
> +}
> +
>  /* Compare function_addrs for qsort.  When ranges are nested, make the
>     smallest one sort last.  */
>  
> @@ -1299,7 +1345,7 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
>  		     int is_bigendian, backtrace_error_callback error_callback,
>  		     void *data, struct unit *u,
>  		     struct unit_addrs_vector *addrs,
> -		     struct dwarf_data *altlink)
> +		     struct dwarf_data *altlink, enum dwarf_tag *unit_tag)
>  {
>    while (unit_buf->left > 0)
>      {
> @@ -1322,6 +1368,9 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
>        if (abbrev == NULL)
>  	return 0;
>  
> +      if (unit_tag != NULL)
> +	*unit_tag = abbrev->tag;
> +
>        lowpc = 0;
>        have_lowpc = 0;
>        highpc = 0;
> @@ -1434,7 +1483,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, altlink))
> +				    u, addrs, altlink, NULL))
>  	    return 0;
>  	}
>      }
> @@ -1454,6 +1503,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
>  		   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,
> +		   struct unit_vector *unit_vec,
>  		   struct dwarf_data *altlink)
>  {
>    struct dwarf_buf info;
> @@ -1462,9 +1512,12 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
>    size_t i;
>    struct unit **pu;
>    size_t prev_addrs_count;
> +  size_t unit_offset = 0;
>  
>    memset (&addrs->vec, 0, sizeof addrs->vec);
> +  memset (&unit_vec->vec, 0, sizeof unit_vec->vec);
>    addrs->count = 0;
> +  unit_vec->count = 0;
>    prev_addrs_count = 0;
>  
>    /* Read through the .debug_info section.  FIXME: Should we use the
> @@ -1493,6 +1546,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
>        uint64_t abbrev_offset;
>        int addrsize;
>        struct unit *u;
> +      enum dwarf_tag unit_tag;
>  
>        if (info.reported_underflow)
>  	goto fail;
> @@ -1535,6 +1589,9 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
>  
>        addrsize = read_byte (&unit_buf);
>  
> +      u->low = unit_offset;
> +      unit_offset += len + (is_dwarf64 ? 12 : 4);
> +      u->high = unit_offset;
>        u->unit_data = unit_buf.buf;
>        u->unit_data_len = unit_buf.left;
>        u->unit_data_offset = unit_buf.buf - unit_data_start;
> @@ -1556,13 +1613,13 @@ 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, altlink))
> +				u, addrs, altlink, &unit_tag))
>  	goto fail;
>  
>        if (unit_buf.reported_underflow)
>  	goto fail;
>  
> -      if (addrs->count == prev_addrs_count)
> +      if (unit_tag != DW_TAG_partial_unit && addrs->count == prev_addrs_count)
>  	{
>  	  --units_count;
>  	  units.size -= sizeof (u);
> @@ -1576,11 +1633,8 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
>    if (info.reported_underflow)
>      goto fail;
>  
> -  // We only kept the list of units to free them on failure.  On
> -  // success the units are retained, pointed to by the entries in
> -  // addrs.
> -  backtrace_vector_free (state, &units, error_callback, data);
> -
> +  unit_vec->vec = units;
> +  unit_vec->count = units_count;
>    return 1;
>  
>   fail:
> @@ -2144,6 +2198,22 @@ read_referenced_name_1 (struct dwarf_data *ddata, struct unit *u,
>        || val->encoding == ATTR_VAL_REF_UNIT)
>      return read_referenced_name (ddata, u, val->u.uint, error_callback, data);
>  
> +  if (val->encoding == ATTR_VAL_REF_ALT_INFO)
> +    {
> +      struct unit *alt_unit
> +	= find_unit (ddata->altlink->units, ddata->altlink->units_count,
> +		     val->u.uint);
> +      if (alt_unit == NULL)
> +	{
> +	  error_callback (data,
> +			  "Could not find unit for DW_FORM_GNU_ref_alt", 0);
> +	  return NULL;
> +	}
> +      uint64_t unit_offset = val->u.uint - alt_unit->low;
> +      return read_referenced_name (ddata->altlink, alt_unit, unit_offset,
> +				   error_callback, data);
> +    }
> +
>    return NULL;
>  }
>  
> @@ -3028,21 +3098,30 @@ build_dwarf_data (struct backtrace_state *state,
>    struct unit_addrs_vector addrs_vec;
>    struct unit_addrs *addrs;
>    size_t addrs_count;
> +  struct unit_vector units_vec;
> +  struct unit **units;
> +  size_t units_count;
>    struct dwarf_data *fdata;
>  
>    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,
> +			  &units_vec,
>  			  altlink))
>      return NULL;
>  
>    if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))
>      return NULL;
> +  if (!backtrace_vector_release (state, &units_vec.vec, error_callback, data))
> +    return NULL;
>    addrs = (struct unit_addrs *) addrs_vec.vec.base;
> +  units = (struct unit **) units_vec.vec.base;
>    addrs_count = addrs_vec.count;
> +  units_count = units_vec.count;
>    backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs),
>  		   unit_addrs_compare);
> +  /* No qsort for units required, already sorted.  */
>  
>    fdata = ((struct dwarf_data *)
>  	   backtrace_alloc (state, sizeof (struct dwarf_data),
> @@ -3055,6 +3134,8 @@ build_dwarf_data (struct backtrace_state *state,
>    fdata->base_address = base_address;
>    fdata->addrs = addrs;
>    fdata->addrs_count = addrs_count;
> +  fdata->units = units;
> +  fdata->units_count = units_count;
>    fdata->dwarf_info = dwarf_info;
>    fdata->dwarf_info_size = dwarf_info_size;
>    fdata->dwarf_line = dwarf_line;
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 7/9] [libbacktrace] Handle DW_FORM_GNU_ref_alt
  2019-01-17  0:17   ` Tom de Vries
@ 2019-01-17  0:36     ` Ian Lance Taylor
  2019-01-17 14:14       ` Tom de Vries
  0 siblings, 1 reply; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-17  0:36 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Wed, Jan 16, 2019 at 4:17 PM Tom de Vries <tdevries@suse.de> wrote:
>
> this handles DW_FORM_GNU_ref_alt which references the .debug_info
> section in the .gnu_debugaltlink file.
>
> OK for trunk?
>
> Thanks,
> - Tom
>
> On 11-12-18 11:14, Tom de Vries wrote:
> > 2018-12-10  Tom de Vries  <tdevries@suse.de>
> >
> >       * dwarf.c (enum attr_val_encoding): Add ATTR_VAL_REF_ALT_INFO.
> >       (struct unit): Add low and high fields.
> >       (struct unit_vector): New type.
> >       (struct dwarf_data): Add units and units_counts fields.
> >       (read_attribute): Handle DW_FORM_GNU_ref_alt using
> >       ATTR_VAL_REF_ALT_INFO.
> >       (find_unit): New function.
> >       (find_address_ranges): Add and handle unit_tag parameter.
> >       (build_address_map): Add and handle units_vec parameter.
> >       (read_referenced_name_1): Handle DW_FORM_GNU_ref_alt.
> >       (build_dwarf_data): Pass units_vec to build_address_map.  Store resulting
> >       units vector.


> > @@ -281,6 +283,10 @@ struct unit
> >    /* The offset of UNIT_DATA from the start of the information for
> >       this compilation unit.  */
> >    size_t unit_data_offset;
> > +  /* Start of the compilation unit.  */
> > +  size_t low;
> > +  /* End of the compilation unit.  */
> > +  size_t high;

The comments should say what low and high are measured in, which I
guess is file offset.  Or is it offset from the start of UNIT_DATA?
Either way, If that is right, then the fields should be named
low_offset and high_offset.  Otherwise it seems easy to confuse with
function_addrs, where low and high refer to PC values.

Also if they are offsets from UNIT_DATA then size_t is OK, but if the
are file offsets they should be off_t.


> > @@ -2144,6 +2198,22 @@ read_referenced_name_1 (struct dwarf_data *ddata, struct unit *u,
> >        || val->encoding == ATTR_VAL_REF_UNIT)
> >      return read_referenced_name (ddata, u, val->u.uint, error_callback, data);
> >
> > +  if (val->encoding == ATTR_VAL_REF_ALT_INFO)
> > +    {
> > +      struct unit *alt_unit
> > +     = find_unit (ddata->altlink->units, ddata->altlink->units_count,
> > +                  val->u.uint);
> > +      if (alt_unit == NULL)
> > +     {
> > +       error_callback (data,
> > +                       "Could not find unit for DW_FORM_GNU_ref_alt", 0);

s/Could/could/

or maybe just skip this error_callback call as discussed earlier.


> > +       return NULL;
> > +     }
> > +      uint64_t unit_offset = val->u.uint - alt_unit->low;

Earlier a unit_offset was the offset of the unit within unit_data, but
here this is an offset within a single unit.  This should just be
called offset, which is the name used by read_referenced_name.

This is OK with those changes.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 9/9] [libbacktrace] Add printdwarftest_dwz_cmp.sh test-case
  2018-12-11 10:14 ` [PATCH 9/9] [libbacktrace] Add printdwarftest_dwz_cmp.sh test-case Tom de Vries
@ 2019-01-17 13:58   ` Tom de Vries
  2019-01-18 14:24     ` Ian Lance Taylor via gcc-patches
  0 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-17 13:58 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ian Lance Taylor

[-- Attachment #1: Type: text/plain, Size: 141 bytes --]

Hi,

now that the rest of the patch series has been committed, here's an
updated version of this patch that applies to trunk.

Thanks,
- Tom

[-- Attachment #2: 0001-libbacktrace-Add-printdwarftest_dwz_cmp.sh-test-case.patch --]
[-- Type: text/x-patch, Size: 16692 bytes --]

[libbacktrace] Add printdwarftest_dwz_cmp.sh test-case

Add test-case that verifies that libbacktrace can find the same debug
information with and without dwz compression.

2018-12-10  Tom de Vries  <tdevries@suse.de>

	* Makefile.am (TESTS): Add printdwarftest_dwz_cmp.sh.
	* Makefile.in: Regenerate.
	* printdwarftest.c: New file.
	* printdwarftest_dwz_cmp.sh: New file.

---
 libbacktrace/Makefile.am               |  11 ++
 libbacktrace/Makefile.in               |  71 +++++++---
 libbacktrace/printdwarftest.c          | 241 +++++++++++++++++++++++++++++++++
 libbacktrace/printdwarftest_dwz_cmp.sh |   8 ++
 4 files changed, 313 insertions(+), 18 deletions(-)

diff --git a/libbacktrace/Makefile.am b/libbacktrace/Makefile.am
index bf90ebdb2d5..61dfca6256e 100644
--- a/libbacktrace/Makefile.am
+++ b/libbacktrace/Makefile.am
@@ -190,6 +190,17 @@ if HAVE_DWZ
 
 TESTS += btest_dwz
 
+printdwarftest.lo: dwarf.c
+
+printdwarftest_SOURCES = printdwarftest.c testlib.c
+printdwarftest_LDADD = libbacktrace.la
+
+check_PROGRAMS += printdwarftest
+
+printdwarftest_dwz_cmp.sh: printdwarftest_dwz
+
+TESTS += printdwarftest_dwz_cmp.sh
+
 endif HAVE_DWZ
 
 stest_SOURCES = stest.c
diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index d55e0501171..06edf592f34 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -120,18 +120,22 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
-check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
+check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
+	$(am__EXEEXT_4) $(am__EXEEXT_5)
 @NATIVE_TRUE@am__append_1 = test_elf test_xcoff_32 test_xcoff_64 \
 @NATIVE_TRUE@	test_pecoff test_unknown unittest unittest_alloc \
-@NATIVE_TRUE@	allocfail btest btest_alloc stest stest_alloc \
-@NATIVE_TRUE@	ztest ztest_alloc edtest edtest_alloc
+@NATIVE_TRUE@	allocfail btest btest_alloc
 @NATIVE_TRUE@am__append_2 = allocfail.sh
-@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_3 = btest_dwz
-@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_4 = -lz
-@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_5 = -lz
-@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_6 = ttest ttest_alloc
-@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_7 = dtest
-@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_8 = ctestg ctesta \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_3 = btest_dwz \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	printdwarftest_dwz_cmp.sh
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_4 = printdwarftest
+@NATIVE_TRUE@am__append_5 = stest stest_alloc ztest ztest_alloc edtest \
+@NATIVE_TRUE@	edtest_alloc
+@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_6 = -lz
+@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_7 = -lz
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_8 = ttest ttest_alloc
+@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_9 = dtest
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_10 = ctestg ctesta \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctestg_alloc \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctesta_alloc
 subdir = .
@@ -184,13 +188,14 @@ libbacktrace_noformat_la_OBJECTS =  \
 @NATIVE_TRUE@	test_xcoff_64$(EXEEXT) test_pecoff$(EXEEXT) \
 @NATIVE_TRUE@	test_unknown$(EXEEXT) unittest$(EXEEXT) \
 @NATIVE_TRUE@	unittest_alloc$(EXEEXT) allocfail$(EXEEXT) \
-@NATIVE_TRUE@	btest$(EXEEXT) btest_alloc$(EXEEXT) \
-@NATIVE_TRUE@	stest$(EXEEXT) stest_alloc$(EXEEXT) \
+@NATIVE_TRUE@	btest$(EXEEXT) btest_alloc$(EXEEXT)
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__EXEEXT_2 = printdwarftest$(EXEEXT)
+@NATIVE_TRUE@am__EXEEXT_3 = stest$(EXEEXT) stest_alloc$(EXEEXT) \
 @NATIVE_TRUE@	ztest$(EXEEXT) ztest_alloc$(EXEEXT) \
 @NATIVE_TRUE@	edtest$(EXEEXT) edtest_alloc$(EXEEXT)
-@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__EXEEXT_2 = ttest$(EXEEXT) \
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__EXEEXT_4 = ttest$(EXEEXT) \
 @HAVE_PTHREAD_TRUE@@NATIVE_TRUE@	ttest_alloc$(EXEEXT)
-@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__EXEEXT_3 =  \
+@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) \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctestg_alloc$(EXEEXT) \
@@ -258,6 +263,12 @@ edtest_OBJECTS = $(am_edtest_OBJECTS)
 @NATIVE_TRUE@am_edtest_alloc_OBJECTS = $(am__objects_5)
 edtest_alloc_OBJECTS = $(am_edtest_alloc_OBJECTS)
 @NATIVE_TRUE@edtest_alloc_DEPENDENCIES = libbacktrace_alloc.la
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am_printdwarftest_OBJECTS =  \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	printdwarftest.$(OBJEXT) \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	testlib.$(OBJEXT)
+printdwarftest_OBJECTS = $(am_printdwarftest_OBJECTS)
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest_DEPENDENCIES =  \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	libbacktrace.la
 @NATIVE_TRUE@am_stest_OBJECTS = stest.$(OBJEXT)
 stest_OBJECTS = $(am_stest_OBJECTS)
 @NATIVE_TRUE@stest_DEPENDENCIES = libbacktrace.la
@@ -373,8 +384,8 @@ SOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \
 	$(btest_SOURCES) $(btest_alloc_SOURCES) $(ctesta_SOURCES) \
 	$(ctesta_alloc_SOURCES) $(ctestg_SOURCES) \
 	$(ctestg_alloc_SOURCES) $(edtest_SOURCES) \
-	$(edtest_alloc_SOURCES) $(stest_SOURCES) \
-	$(stest_alloc_SOURCES) $(test_elf_SOURCES) \
+	$(edtest_alloc_SOURCES) $(printdwarftest_SOURCES) \
+	$(stest_SOURCES) $(stest_alloc_SOURCES) $(test_elf_SOURCES) \
 	$(test_pecoff_SOURCES) $(test_unknown_SOURCES) \
 	$(test_xcoff_32_SOURCES) $(test_xcoff_64_SOURCES) \
 	$(ttest_SOURCES) $(ttest_alloc_SOURCES) $(unittest_SOURCES) \
@@ -789,7 +800,7 @@ libbacktrace_la_LIBADD = \
 
 libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
 TESTS = $(check_PROGRAMS) $(am__append_2) $(am__append_3) \
-	$(am__append_7)
+	$(am__append_9)
 @NATIVE_TRUE@check_LTLIBRARIES = libbacktrace_alloc.la \
 @NATIVE_TRUE@	libbacktrace_noformat.la \
 @NATIVE_TRUE@	libbacktrace_instrumented_alloc.la
@@ -828,15 +839,17 @@ TESTS = $(check_PROGRAMS) $(am__append_2) $(am__append_3) \
 @NATIVE_TRUE@btest_alloc_SOURCES = $(btest_SOURCES)
 @NATIVE_TRUE@btest_alloc_CFLAGS = $(btest_CFLAGS)
 @NATIVE_TRUE@btest_alloc_LDADD = libbacktrace_alloc.la
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest_SOURCES = printdwarftest.c testlib.c
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest_LDADD = libbacktrace.la
 @NATIVE_TRUE@stest_SOURCES = stest.c
 @NATIVE_TRUE@stest_LDADD = libbacktrace.la
 @NATIVE_TRUE@stest_alloc_SOURCES = $(stest_SOURCES)
 @NATIVE_TRUE@stest_alloc_LDADD = libbacktrace_alloc.la
 @NATIVE_TRUE@ztest_SOURCES = ztest.c testlib.c
 @NATIVE_TRUE@ztest_CFLAGS = -DSRCDIR=\"$(srcdir)\"
-@NATIVE_TRUE@ztest_LDADD = libbacktrace.la $(am__append_4) \
+@NATIVE_TRUE@ztest_LDADD = libbacktrace.la $(am__append_6) \
 @NATIVE_TRUE@	$(CLOCK_GETTIME_LINK)
-@NATIVE_TRUE@ztest_alloc_LDADD = libbacktrace_alloc.la $(am__append_5) \
+@NATIVE_TRUE@ztest_alloc_LDADD = libbacktrace_alloc.la $(am__append_7) \
 @NATIVE_TRUE@	$(CLOCK_GETTIME_LINK)
 @NATIVE_TRUE@ztest_alloc_SOURCES = $(ztest_SOURCES)
 @NATIVE_TRUE@ztest_alloc_CFLAGS = $(ztest_CFLAGS)
@@ -1021,6 +1034,10 @@ edtest_alloc$(EXEEXT): $(edtest_alloc_OBJECTS) $(edtest_alloc_DEPENDENCIES) $(EX
 	@rm -f edtest_alloc$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(edtest_alloc_OBJECTS) $(edtest_alloc_LDADD) $(LIBS)
 
+printdwarftest$(EXEEXT): $(printdwarftest_OBJECTS) $(printdwarftest_DEPENDENCIES) $(EXTRA_printdwarftest_DEPENDENCIES) 
+	@rm -f printdwarftest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(printdwarftest_OBJECTS) $(printdwarftest_LDADD) $(LIBS)
+
 stest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) $(EXTRA_stest_DEPENDENCIES) 
 	@rm -f stest$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(stest_OBJECTS) $(stest_LDADD) $(LIBS)
@@ -1487,6 +1504,13 @@ btest_alloc.log: btest_alloc$(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)
+printdwarftest.log: printdwarftest$(EXEEXT)
+	@p='printdwarftest$(EXEEXT)'; \
+	b='printdwarftest'; \
+	$(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'; \
@@ -1585,6 +1609,13 @@ btest_dwz.log: btest_dwz
 	--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)
+printdwarftest_dwz_cmp.sh.log: printdwarftest_dwz_cmp.sh
+	@p='printdwarftest_dwz_cmp.sh'; \
+	b='printdwarftest_dwz_cmp.sh'; \
+	$(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'; \
@@ -1761,6 +1792,10 @@ uninstall-am:
 @HAVE_DWZ_TRUE@@NATIVE_TRUE@	rm -f $@_2
 @HAVE_DWZ_TRUE@@NATIVE_TRUE@	mv $@_1 $@
 
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest.lo: dwarf.c
+
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest_dwz_cmp.sh: printdwarftest_dwz
+
 @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/printdwarftest.c b/libbacktrace/printdwarftest.c
new file mode 100644
index 00000000000..ba5473e4584
--- /dev/null
+++ b/libbacktrace/printdwarftest.c
@@ -0,0 +1,241 @@
+/* printdwarftest.c -- Print dwarf info cached by libbacktrace.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+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.  */
+
+/* Add all dwarf.c includes here, to make sure once-included headers are
+   included here (before defining backtrace_dwarf_add) rather than at the
+   #include "dwarf.c" below.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "dwarf2.h"
+#include "filenames.h"
+
+#include "backtrace.h"
+#include "internal.h"
+
+#include "testlib.h"
+#include "backtrace-supported.h"
+
+/* Include dwarf.c, using dwarf.c as header file defining struct dwarf_data.
+   Rename the only external function to prevent conflict with dwarf.o.  */
+
+extern int dummy_backtrace_dwarf_add (struct backtrace_state *state,
+				      uintptr_t base_address,
+				      const unsigned char* dwarf_info,
+				      size_t dwarf_info_size,
+				      const unsigned char *dwarf_line,
+				      size_t dwarf_line_size,
+				      const unsigned char *dwarf_abbrev,
+				      size_t dwarf_abbrev_size,
+				      const unsigned char *dwarf_ranges,
+				      size_t dwarf_range_size,
+				      const unsigned char *dwarf_str,
+				      size_t dwarf_str_size,
+				      int is_bigendian,
+				      struct dwarf_data *fileline_altlink,
+				      backtrace_error_callback error_callback,
+				      void *data, fileline *fileline_fn,
+				      struct dwarf_data **fileline_entry);
+
+#define backtrace_dwarf_add dummy_backtrace_dwarf_add
+#include "dwarf.c"
+
+static void
+error_callback (void *vdata ATTRIBUTE_UNUSED, const char *msg ATTRIBUTE_UNUSED,
+		int errnum ATTRIBUTE_UNUSED)
+{
+}
+
+static int
+dummmy_callback (void *data ATTRIBUTE_UNUSED, uintptr_t pc ATTRIBUTE_UNUSED,
+		 const char *filename ATTRIBUTE_UNUSED,
+		 int lineno ATTRIBUTE_UNUSED,
+		 const char *function ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+struct print_callback_data
+{
+  uintptr_t base_address;
+  uintptr_t pc;
+  const char *filename;
+  int lineno;
+  const char *function;
+  uintptr_t d1_pc;
+  const char *d1_filename;
+  int d1_lineno;
+  const char *d1_function;
+  int depth;
+  int stack_printed;
+  int skip;
+};
+
+static int
+print_callback (void *data, uintptr_t pc ATTRIBUTE_UNUSED,
+		const char *filename ATTRIBUTE_UNUSED,
+		int lineno ATTRIBUTE_UNUSED,
+		const char *function ATTRIBUTE_UNUSED)
+{
+  struct print_callback_data *prev = (struct print_callback_data *)data;
+
+  prev->depth++;
+  if (prev->depth == 1)
+    {
+      if (prev->stack_printed)
+	prev->skip = 1;
+    }
+  else
+    {
+      if (prev->skip)
+	return 0;
+
+      fprintf (stderr, " %s@%d", function, prev->depth);
+      fprintf (stderr, " %d", lineno);
+      prev->stack_printed = 1;
+
+      return 0;
+    }
+
+  if (function == NULL)
+    return 0;
+
+  if (prev->pc == 0)
+    {
+      fprintf (stderr, "%p", (void *)(pc - prev->base_address));
+      fprintf (stderr, " %s@%d", function, prev->depth);
+      fprintf (stderr, " %s", filename);
+      fprintf (stderr, "\n  %d", lineno);
+      fprintf (stderr, "@%p", (void *)(pc - prev->base_address));
+      goto update;
+    }
+
+  if (function != prev->function)
+    {
+      if (pc != prev->pc)
+	{
+	  fprintf (stderr, "\n");
+	  fprintf (stderr, "%p", (void *)(pc - prev->base_address));
+	  fprintf (stderr, " %s@%d", function, prev->depth);
+	}
+      else
+	fprintf (stderr, " %s@%d", function, prev->depth);
+    }
+
+  if (filename != prev->filename)
+    fprintf (stderr, " %s", filename);
+
+  if (lineno != prev->lineno)
+    {
+      prev->stack_printed = 0;
+      prev->skip = 0;
+      fprintf (stderr, "\n  %d", lineno);
+      fprintf (stderr, "@%p", (void *)(pc - prev->base_address));
+    }
+
+ update:
+  prev->pc = pc;
+  prev->filename = filename;
+  prev->lineno = lineno;
+  prev->function = function;
+  if (prev->depth == 1)
+    {
+      prev->d1_pc = pc;
+      prev->d1_filename = filename;
+      prev->d1_lineno = lineno;
+      prev->d1_function = function;
+    }
+  return 0;
+}
+
+static void
+print_dwarf_data (struct backtrace_state *state, void *data)
+{
+  struct dwarf_data *fdata;
+  unsigned int i;
+
+  fdata = (struct dwarf_data *)data;
+
+  for (i = 0; i < fdata->addrs_count; ++i)
+    {
+      struct unit_addrs *addr = &fdata->addrs[i];
+      uintptr_t pc;
+
+      struct print_callback_data tdata;
+      tdata.base_address = fdata->base_address;
+      tdata.pc = 0;
+      tdata.stack_printed = 0;
+      tdata.skip = 0;
+      for (pc = addr->low; pc < addr->high; ++pc)
+	{
+	  int found;
+	  tdata.depth = 0;
+	  dwarf_lookup_pc (state, fdata, pc, print_callback, error_callback,
+			   &tdata, &found);
+	  if (!found)
+	    fprintf (stderr, "not found: %p\n", (void *)pc);
+	}
+      if (tdata.pc != 0)
+	fprintf (stderr, "\n");
+    }
+}
+
+static void
+print_dwarf_cache (struct backtrace_state *state)
+{
+  struct dwarf_data **pp;
+
+  if (state->fileline_data == NULL)
+    backtrace_pcinfo (state, (uintptr_t)print_callback, dummmy_callback,
+		      NULL, NULL);
+
+  for (pp = (struct dwarf_data **) (void *) &state->fileline_data;
+       *pp != NULL;
+       pp = &(*pp)->next)
+    print_dwarf_data (state, *pp);
+}
+
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv)
+{
+  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
+				  error_callback_create, NULL);
+
+  print_dwarf_cache ((struct backtrace_state *)state);
+
+  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/libbacktrace/printdwarftest_dwz_cmp.sh b/libbacktrace/printdwarftest_dwz_cmp.sh
new file mode 100755
index 00000000000..617de00ece8
--- /dev/null
+++ b/libbacktrace/printdwarftest_dwz_cmp.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+log1=printdwarftest_dwz.1.log
+log2=printdwarftest_dwz.2.log
+
+./printdwarftest 2> $log1
+./printdwarftest_dwz 2> $log2
+cmp $log1 $log2

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 7/9] [libbacktrace] Handle DW_FORM_GNU_ref_alt
  2019-01-17  0:36     ` Ian Lance Taylor
@ 2019-01-17 14:14       ` Tom de Vries
  2019-01-17 14:16         ` Tom de Vries
  2019-01-18 14:26         ` Ian Lance Taylor
  0 siblings, 2 replies; 47+ messages in thread
From: Tom de Vries @ 2019-01-17 14:14 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3365 bytes --]

On 17-01-19 01:35, Ian Lance Taylor wrote:
> On Wed, Jan 16, 2019 at 4:17 PM Tom de Vries <tdevries@suse.de> wrote:
>>
>> this handles DW_FORM_GNU_ref_alt which references the .debug_info
>> section in the .gnu_debugaltlink file.
>>
>> OK for trunk?
>>
>> Thanks,
>> - Tom
>>
>> On 11-12-18 11:14, Tom de Vries wrote:
>>> 2018-12-10  Tom de Vries  <tdevries@suse.de>
>>>
>>>       * dwarf.c (enum attr_val_encoding): Add ATTR_VAL_REF_ALT_INFO.
>>>       (struct unit): Add low and high fields.
>>>       (struct unit_vector): New type.
>>>       (struct dwarf_data): Add units and units_counts fields.
>>>       (read_attribute): Handle DW_FORM_GNU_ref_alt using
>>>       ATTR_VAL_REF_ALT_INFO.
>>>       (find_unit): New function.
>>>       (find_address_ranges): Add and handle unit_tag parameter.
>>>       (build_address_map): Add and handle units_vec parameter.
>>>       (read_referenced_name_1): Handle DW_FORM_GNU_ref_alt.
>>>       (build_dwarf_data): Pass units_vec to build_address_map.  Store resulting
>>>       units vector.
> 
> 
>>> @@ -281,6 +283,10 @@ struct unit
>>>    /* The offset of UNIT_DATA from the start of the information for
>>>       this compilation unit.  */
>>>    size_t unit_data_offset;
>>> +  /* Start of the compilation unit.  */
>>> +  size_t low;
>>> +  /* End of the compilation unit.  */
>>> +  size_t high;
> 
> The comments should say what low and high are measured in, which I
> guess is file offset.  Or is it offset from the start of UNIT_DATA?
> Either way, If that is right, then the fields should be named
> low_offset and high_offset.  Otherwise it seems easy to confuse with
> function_addrs, where low and high refer to PC values.
> 

Done.

> Also if they are offsets from UNIT_DATA then size_t is OK, but if the
> are file offsets they should be off_t.
> 

AFAIU, in the case where off_t vs size_t would make a difference, we're
running into trouble much earlier.  I've filed PR 88890 - "libbacktrace
on 32-bit system with _FILE_OFFSET_BITS == 64" (
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88890 ) about this.

Anyway, I've made the conservative choice of using off_t for now (but I
could argue that it's a memory offset, given that the assumption is that
the entire debug section is read into memory).

>>> @@ -2144,6 +2198,22 @@ read_referenced_name_1 (struct dwarf_data *ddata, struct unit *u,
>>>        || val->encoding == ATTR_VAL_REF_UNIT)
>>>      return read_referenced_name (ddata, u, val->u.uint, error_callback, data);
>>>
>>> +  if (val->encoding == ATTR_VAL_REF_ALT_INFO)
>>> +    {
>>> +      struct unit *alt_unit
>>> +     = find_unit (ddata->altlink->units, ddata->altlink->units_count,
>>> +                  val->u.uint);
>>> +      if (alt_unit == NULL)
>>> +     {
>>> +       error_callback (data,
>>> +                       "Could not find unit for DW_FORM_GNU_ref_alt", 0);
> 
> s/Could/could/
> 
> or maybe just skip this error_callback call as discussed earlier.
> 
> 

Skipped.

>>> +       return NULL;
>>> +     }
>>> +      uint64_t unit_offset = val->u.uint - alt_unit->low;
> 
> Earlier a unit_offset was the offset of the unit within unit_data, but
> here this is an offset within a single unit.  This should just be
> called offset, which is the name used by read_referenced_name.
> 

Done.

> This is OK with those changes.

Committed in two parts.

First part ...



[-- Attachment #2: 0001-libbacktrace-Add-find_unit.patch --]
[-- Type: text/x-patch, Size: 7856 bytes --]

[libbacktrace] Add find_unit

Add a function that finds the unit given an offset into .debug_info.

2018-12-10  Tom de Vries  <tdevries@suse.de>

	* dwarf.c (struct unit): Add low_offset and high_offset fields.
	(struct unit_vector): New type.
	(struct dwarf_data): Add units and units_counts fields.
	(find_unit): New function.
	(find_address_ranges): Add and handle unit_tag parameter.
	(build_address_map): Add and handle units_vec parameter.
	(build_dwarf_data): Pass units_vec to build_address_map.  Store resulting
	units vector.

---
 libbacktrace/dwarf.c | 87 +++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 76 insertions(+), 11 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 45691b4ba69..6f56c46774b 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -281,6 +281,12 @@ struct unit
   /* The offset of UNIT_DATA from the start of the information for
      this compilation unit.  */
   size_t unit_data_offset;
+  /* Offset of the start of the compilation unit from the start of the
+     .debug_info section.  */
+  off_t low_offset;
+  /* Offset of the end of the compilation unit from the start of the
+     .debug_info section.  */
+  off_t high_offset;
   /* DWARF version.  */
   int version;
   /* Whether unit is DWARF64.  */
@@ -339,6 +345,14 @@ struct unit_addrs_vector
   size_t count;
 };
 
+/* A growable vector of compilation unit pointer.  */
+
+struct unit_vector
+{
+  struct backtrace_vector vec;
+  size_t count;
+};
+
 /* The information we need to map a PC to a file and line.  */
 
 struct dwarf_data
@@ -353,6 +367,10 @@ struct dwarf_data
   struct unit_addrs *addrs;
   /* Number of address ranges in list.  */
   size_t addrs_count;
+  /* A sorted list of units.  */
+  struct unit **units;
+  /* Number of units in the list.  */
+  size_t units_count;
   /* The unparsed .debug_info section.  */
   const unsigned char *dwarf_info;
   size_t dwarf_info_size;
@@ -866,6 +884,34 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
     }
 }
 
+/* Compare a unit offset against a unit for bsearch.  */
+
+static int
+units_search (const void *vkey, const void *ventry)
+{
+  const off_t *key = (const off_t *) vkey;
+  const struct unit *entry = *((const struct unit *const *) ventry);
+  off_t offset;
+
+  offset = *key;
+  if (offset < entry->low_offset)
+    return -1;
+  else if (offset >= entry->high_offset)
+    return 1;
+  else
+    return 0;
+}
+
+/* Find a unit in PU containing OFFSET.  */
+
+static struct unit *
+find_unit (struct unit **pu, size_t units_count, off_t offset)
+{
+  struct unit **u;
+  u = bsearch (&offset, pu, units_count, sizeof (struct unit *), units_search);
+  return u == NULL ? NULL : *u;
+}
+
 /* Compare function_addrs for qsort.  When ranges are nested, make the
    smallest one sort last.  */
 
@@ -1298,7 +1344,8 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 		     size_t dwarf_ranges_size,
 		     int is_bigendian, struct dwarf_data *altlink,
 		     backtrace_error_callback error_callback, void *data,
-		     struct unit *u, struct unit_addrs_vector *addrs)
+		     struct unit *u, struct unit_addrs_vector *addrs,
+		     enum dwarf_tag *unit_tag)
 {
   while (unit_buf->left > 0)
     {
@@ -1321,6 +1368,9 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
       if (abbrev == NULL)
 	return 0;
 
+      if (unit_tag != NULL)
+	*unit_tag = abbrev->tag;
+
       lowpc = 0;
       have_lowpc = 0;
       highpc = 0;
@@ -1433,7 +1483,7 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 				    dwarf_str, dwarf_str_size,
 				    dwarf_ranges, dwarf_ranges_size,
 				    is_bigendian, altlink, error_callback, data,
-				    u, addrs))
+				    u, addrs, NULL))
 	    return 0;
 	}
     }
@@ -1453,7 +1503,8 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
 		   const unsigned char *dwarf_str, size_t dwarf_str_size,
 		   int is_bigendian, struct dwarf_data *altlink,
 		   backtrace_error_callback error_callback, void *data,
-		   struct unit_addrs_vector *addrs)
+		   struct unit_addrs_vector *addrs,
+		   struct unit_vector *unit_vec)
 {
   struct dwarf_buf info;
   struct backtrace_vector units;
@@ -1461,9 +1512,12 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
   size_t i;
   struct unit **pu;
   size_t prev_addrs_count;
+  off_t unit_offset = 0;
 
   memset (&addrs->vec, 0, sizeof addrs->vec);
+  memset (&unit_vec->vec, 0, sizeof unit_vec->vec);
   addrs->count = 0;
+  unit_vec->count = 0;
   prev_addrs_count = 0;
 
   /* Read through the .debug_info section.  FIXME: Should we use the
@@ -1492,6 +1546,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
       uint64_t abbrev_offset;
       int addrsize;
       struct unit *u;
+      enum dwarf_tag unit_tag;
 
       if (info.reported_underflow)
 	goto fail;
@@ -1534,6 +1589,9 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
 
       addrsize = read_byte (&unit_buf);
 
+      u->low_offset = unit_offset;
+      unit_offset += len + (is_dwarf64 ? 12 : 4);
+      u->high_offset = unit_offset;
       u->unit_data = unit_buf.buf;
       u->unit_data_len = unit_buf.left;
       u->unit_data_offset = unit_buf.buf - unit_data_start;
@@ -1555,13 +1613,13 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
 				dwarf_str, dwarf_str_size,
 				dwarf_ranges, dwarf_ranges_size,
 				is_bigendian, altlink, error_callback, data,
-				u, addrs))
+				u, addrs, &unit_tag))
 	goto fail;
 
       if (unit_buf.reported_underflow)
 	goto fail;
 
-      if (addrs->count > prev_addrs_count)
+      if (addrs->count > prev_addrs_count || unit_tag == DW_TAG_partial_unit)
 	prev_addrs_count = addrs->count;
       else
 	{
@@ -1576,11 +1634,8 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
   if (info.reported_underflow)
     goto fail;
 
-  // We only kept the list of units to free them on failure.  On
-  // success the units are retained, pointed to by the entries in
-  // addrs.
-  backtrace_vector_free (state, &units, error_callback, data);
-
+  unit_vec->vec = units;
+  unit_vec->count = units_count;
   return 1;
 
  fail:
@@ -3031,21 +3086,29 @@ build_dwarf_data (struct backtrace_state *state,
   struct unit_addrs_vector addrs_vec;
   struct unit_addrs *addrs;
   size_t addrs_count;
+  struct unit_vector units_vec;
+  struct unit **units;
+  size_t units_count;
   struct dwarf_data *fdata;
 
   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, altlink, error_callback, data,
-			  &addrs_vec))
+			  &addrs_vec, &units_vec))
     return NULL;
 
   if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))
     return NULL;
+  if (!backtrace_vector_release (state, &units_vec.vec, error_callback, data))
+    return NULL;
   addrs = (struct unit_addrs *) addrs_vec.vec.base;
+  units = (struct unit **) units_vec.vec.base;
   addrs_count = addrs_vec.count;
+  units_count = units_vec.count;
   backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs),
 		   unit_addrs_compare);
+  /* No qsort for units required, already sorted.  */
 
   fdata = ((struct dwarf_data *)
 	   backtrace_alloc (state, sizeof (struct dwarf_data),
@@ -3058,6 +3121,8 @@ build_dwarf_data (struct backtrace_state *state,
   fdata->base_address = base_address;
   fdata->addrs = addrs;
   fdata->addrs_count = addrs_count;
+  fdata->units = units;
+  fdata->units_count = units_count;
   fdata->dwarf_info = dwarf_info;
   fdata->dwarf_info_size = dwarf_info_size;
   fdata->dwarf_line = dwarf_line;

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 7/9] [libbacktrace] Handle DW_FORM_GNU_ref_alt
  2019-01-17 14:14       ` Tom de Vries
@ 2019-01-17 14:16         ` Tom de Vries
  2019-01-18 14:26         ` Ian Lance Taylor
  1 sibling, 0 replies; 47+ messages in thread
From: Tom de Vries @ 2019-01-17 14:16 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3551 bytes --]

On 17-01-19 15:14, Tom de Vries wrote:
> On 17-01-19 01:35, Ian Lance Taylor wrote:
>> On Wed, Jan 16, 2019 at 4:17 PM Tom de Vries <tdevries@suse.de> wrote:
>>>
>>> this handles DW_FORM_GNU_ref_alt which references the .debug_info
>>> section in the .gnu_debugaltlink file.
>>>
>>> OK for trunk?
>>>
>>> Thanks,
>>> - Tom
>>>
>>> On 11-12-18 11:14, Tom de Vries wrote:
>>>> 2018-12-10  Tom de Vries  <tdevries@suse.de>
>>>>
>>>>       * dwarf.c (enum attr_val_encoding): Add ATTR_VAL_REF_ALT_INFO.
>>>>       (struct unit): Add low and high fields.
>>>>       (struct unit_vector): New type.
>>>>       (struct dwarf_data): Add units and units_counts fields.
>>>>       (read_attribute): Handle DW_FORM_GNU_ref_alt using
>>>>       ATTR_VAL_REF_ALT_INFO.
>>>>       (find_unit): New function.
>>>>       (find_address_ranges): Add and handle unit_tag parameter.
>>>>       (build_address_map): Add and handle units_vec parameter.
>>>>       (read_referenced_name_1): Handle DW_FORM_GNU_ref_alt.
>>>>       (build_dwarf_data): Pass units_vec to build_address_map.  Store resulting
>>>>       units vector.
>>
>>
>>>> @@ -281,6 +283,10 @@ struct unit
>>>>    /* The offset of UNIT_DATA from the start of the information for
>>>>       this compilation unit.  */
>>>>    size_t unit_data_offset;
>>>> +  /* Start of the compilation unit.  */
>>>> +  size_t low;
>>>> +  /* End of the compilation unit.  */
>>>> +  size_t high;
>>
>> The comments should say what low and high are measured in, which I
>> guess is file offset.  Or is it offset from the start of UNIT_DATA?
>> Either way, If that is right, then the fields should be named
>> low_offset and high_offset.  Otherwise it seems easy to confuse with
>> function_addrs, where low and high refer to PC values.
>>
> 
> Done.
> 
>> Also if they are offsets from UNIT_DATA then size_t is OK, but if the
>> are file offsets they should be off_t.
>>
> 
> AFAIU, in the case where off_t vs size_t would make a difference, we're
> running into trouble much earlier.  I've filed PR 88890 - "libbacktrace
> on 32-bit system with _FILE_OFFSET_BITS == 64" (
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88890 ) about this.
> 
> Anyway, I've made the conservative choice of using off_t for now (but I
> could argue that it's a memory offset, given that the assumption is that
> the entire debug section is read into memory).
> 
>>>> @@ -2144,6 +2198,22 @@ read_referenced_name_1 (struct dwarf_data *ddata, struct unit *u,
>>>>        || val->encoding == ATTR_VAL_REF_UNIT)
>>>>      return read_referenced_name (ddata, u, val->u.uint, error_callback, data);
>>>>
>>>> +  if (val->encoding == ATTR_VAL_REF_ALT_INFO)
>>>> +    {
>>>> +      struct unit *alt_unit
>>>> +     = find_unit (ddata->altlink->units, ddata->altlink->units_count,
>>>> +                  val->u.uint);
>>>> +      if (alt_unit == NULL)
>>>> +     {
>>>> +       error_callback (data,
>>>> +                       "Could not find unit for DW_FORM_GNU_ref_alt", 0);
>>
>> s/Could/could/
>>
>> or maybe just skip this error_callback call as discussed earlier.
>>
>>
> 
> Skipped.
> 
>>>> +       return NULL;
>>>> +     }
>>>> +      uint64_t unit_offset = val->u.uint - alt_unit->low;
>>
>> Earlier a unit_offset was the offset of the unit within unit_data, but
>> here this is an offset within a single unit.  This should just be
>> called offset, which is the name used by read_referenced_name.
>>
> 
> Done.
> 
>> This is OK with those changes.
> 
> Committed in two parts.
> 
> First part ...
> 

And second part.

Thanks,
- Tom




[-- Attachment #2: 0002-libbacktrace-Handle-DW_FORM_GNU_ref_alt.patch --]
[-- Type: text/x-patch, Size: 1935 bytes --]

[libbacktrace] Handle DW_FORM_GNU_ref_alt

Handle DW_FORM_GNU_ref_alt which references the .debug_info section in the
.gnu_debugaltlink file.

2018-12-10  Tom de Vries  <tdevries@suse.de>

	PR libbacktrace/82857
	* dwarf.c (enum attr_val_encoding): Add ATTR_VAL_REF_ALT_INFO.
	(read_attribute): Handle DW_FORM_GNU_ref_alt using
	ATTR_VAL_REF_ALT_INFO.
	(read_referenced_name_from_attr): Handle DW_FORM_GNU_ref_alt.

---
 libbacktrace/dwarf.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 6f56c46774b..aacbd3a453d 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -143,6 +143,8 @@ enum attr_val_encoding
   ATTR_VAL_REF_UNIT,
   /* An offset to other data within the .dwarf_info section.  */
   ATTR_VAL_REF_INFO,
+  /* An offset to other data within the alt .dwarf_info section.  */
+  ATTR_VAL_REF_ALT_INFO,
   /* An offset to data in some other section.  */
   ATTR_VAL_REF_SECTION,
   /* A type signature.  */
@@ -858,7 +860,7 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
 	  val->encoding = ATTR_VAL_NONE;
 	  return 1;
 	}
-      val->encoding = ATTR_VAL_REF_SECTION;
+      val->encoding = ATTR_VAL_REF_ALT_INFO;
       return 1;
     case DW_FORM_GNU_strp_alt:
       {
@@ -2200,6 +2202,19 @@ read_referenced_name_from_attr (struct dwarf_data *ddata, struct unit *u,
       || val->encoding == ATTR_VAL_REF_UNIT)
     return read_referenced_name (ddata, u, val->u.uint, error_callback, data);
 
+  if (val->encoding == ATTR_VAL_REF_ALT_INFO)
+    {
+      struct unit *alt_unit
+	= find_unit (ddata->altlink->units, ddata->altlink->units_count,
+		     val->u.uint);
+      if (alt_unit == NULL)
+	return NULL;
+
+      uint64_t offset = val->u.uint - alt_unit->low_offset;
+      return read_referenced_name (ddata->altlink, alt_unit, offset,
+				   error_callback, data);
+    }
+
   return NULL;
 }
 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 9/9] [libbacktrace] Add printdwarftest_dwz_cmp.sh test-case
  2019-01-17 13:58   ` Tom de Vries
@ 2019-01-18 14:24     ` Ian Lance Taylor via gcc-patches
  2019-01-19  0:45       ` Tom de Vries
  0 siblings, 1 reply; 47+ messages in thread
From: Ian Lance Taylor via gcc-patches @ 2019-01-18 14:24 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches, Ian Lance Taylor

On Thu, Jan 17, 2019 at 5:59 AM Tom de Vries <tdevries@suse.de> wrote:
>
> now that the rest of the patch series has been committed, here's an
> updated version of this patch that applies to trunk.

I would much rather put dwarf_data into internal.h than to #include
"dwarf.c" from a different file.  Using #include with a .c file is
just a bad path to walk down.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 7/9] [libbacktrace] Handle DW_FORM_GNU_ref_alt
  2019-01-17 14:14       ` Tom de Vries
  2019-01-17 14:16         ` Tom de Vries
@ 2019-01-18 14:26         ` Ian Lance Taylor
  2019-01-22 22:17           ` [libbacktrace] Use size_t for low_offset/high_offset fields of struct unit Tom de Vries
  1 sibling, 1 reply; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-18 14:26 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Thu, Jan 17, 2019 at 6:14 AM Tom de Vries <tdevries@suse.de> wrote:
>
> On 17-01-19 01:35, Ian Lance Taylor wrote:
> > On Wed, Jan 16, 2019 at 4:17 PM Tom de Vries <tdevries@suse.de> wrote:
> >>
> >> this handles DW_FORM_GNU_ref_alt which references the .debug_info
> >> section in the .gnu_debugaltlink file.
> >>
> >> OK for trunk?
> >>
> >> Thanks,
> >> - Tom
> >>
> >> On 11-12-18 11:14, Tom de Vries wrote:
> >>> 2018-12-10  Tom de Vries  <tdevries@suse.de>
> >>>
> >>>       * dwarf.c (enum attr_val_encoding): Add ATTR_VAL_REF_ALT_INFO.
> >>>       (struct unit): Add low and high fields.
> >>>       (struct unit_vector): New type.
> >>>       (struct dwarf_data): Add units and units_counts fields.
> >>>       (read_attribute): Handle DW_FORM_GNU_ref_alt using
> >>>       ATTR_VAL_REF_ALT_INFO.
> >>>       (find_unit): New function.
> >>>       (find_address_ranges): Add and handle unit_tag parameter.
> >>>       (build_address_map): Add and handle units_vec parameter.
> >>>       (read_referenced_name_1): Handle DW_FORM_GNU_ref_alt.
> >>>       (build_dwarf_data): Pass units_vec to build_address_map.  Store resulting
> >>>       units vector.
> >
> >
> >>> @@ -281,6 +283,10 @@ struct unit
> >>>    /* The offset of UNIT_DATA from the start of the information for
> >>>       this compilation unit.  */
> >>>    size_t unit_data_offset;
> >>> +  /* Start of the compilation unit.  */
> >>> +  size_t low;
> >>> +  /* End of the compilation unit.  */
> >>> +  size_t high;
> >
> > The comments should say what low and high are measured in, which I
> > guess is file offset.  Or is it offset from the start of UNIT_DATA?
> > Either way, If that is right, then the fields should be named
> > low_offset and high_offset.  Otherwise it seems easy to confuse with
> > function_addrs, where low and high refer to PC values.
> >
>
> Done.
>
> > Also if they are offsets from UNIT_DATA then size_t is OK, but if the
> > are file offsets they should be off_t.
> >
>
> AFAIU, in the case where off_t vs size_t would make a difference, we're
> running into trouble much earlier.  I've filed PR 88890 - "libbacktrace
> on 32-bit system with _FILE_OFFSET_BITS == 64" (
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88890 ) about this.
>
> Anyway, I've made the conservative choice of using off_t for now (but I
> could argue that it's a memory offset, given that the assumption is that
> the entire debug section is read into memory).

Since the entire debug section is read into memory, if they are
offsets from UNIT_DATA, they should be size_t, not off_t.  I wasn't
trying to say that we should make a conservative choice here, I was
trying to say that we should make a correct choice.  An offset from
UNIT_DATA should be size_t, a file offset should be off_t.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 9/9] [libbacktrace] Add printdwarftest_dwz_cmp.sh test-case
  2019-01-18 14:24     ` Ian Lance Taylor via gcc-patches
@ 2019-01-19  0:45       ` Tom de Vries
  2019-01-19  0:54         ` Ian Lance Taylor via gcc-patches
  0 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-19  0:45 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches, Ian Lance Taylor

[-- Attachment #1: Type: text/plain, Size: 505 bytes --]

On 18-01-19 15:23, Ian Lance Taylor wrote:
> On Thu, Jan 17, 2019 at 5:59 AM Tom de Vries <tdevries@suse.de> wrote:
>>
>> now that the rest of the patch series has been committed, here's an
>> updated version of this patch that applies to trunk.
> 
> I would much rather put dwarf_data into internal.h than to #include
> "dwarf.c" from a different file.  Using #include with a .c file is
> just a bad path to walk down.

This version avoids the include of dwarf.c.

Does that look better?

Thanks,
- Tom


[-- Attachment #2: 0001-libbacktrace-Add-printdwarftest_dwz_cmp.sh-test-case.patch --]
[-- Type: text/x-patch, Size: 22264 bytes --]

[libbacktrace] Add printdwarftest_dwz_cmp.sh test-case

Add test-case that verifies that libbacktrace can find the same debug
information with and without dwz compression.

2018-12-10  Tom de Vries  <tdevries@suse.de>

	* Makefile.am (TESTS): Add printdwarftest_dwz_cmp.sh.
	* Makefile.in: Regenerate.
	* printdwarftest.c: New file.
	* printdwarftest_dwz_cmp.sh: New file.
	* dwarf.c (struct function_vector, struct unit_addrs)
	(struct dwarf_info): Move ...
	* internal.h: ... here.

---
 libbacktrace/Makefile.am               |  11 ++
 libbacktrace/Makefile.in               |  70 ++++++++---
 libbacktrace/dwarf.c                   |  64 +---------
 libbacktrace/internal.h                |  68 +++++++++++
 libbacktrace/printdwarftest.c          | 208 +++++++++++++++++++++++++++++++++
 libbacktrace/printdwarftest_dwz_cmp.sh |   8 ++
 6 files changed, 348 insertions(+), 81 deletions(-)

diff --git a/libbacktrace/Makefile.am b/libbacktrace/Makefile.am
index bf90ebdb2d5..7843229304d 100644
--- a/libbacktrace/Makefile.am
+++ b/libbacktrace/Makefile.am
@@ -190,6 +190,15 @@ if HAVE_DWZ
 
 TESTS += btest_dwz
 
+printdwarftest_SOURCES =
+printdwarftest_LDADD = libbacktrace.la printdwarftest.lo testlib.lo
+
+check_PROGRAMS += printdwarftest
+
+printdwarftest_dwz_cmp.sh: printdwarftest_dwz
+
+TESTS += printdwarftest_dwz_cmp.sh
+
 endif HAVE_DWZ
 
 stest_SOURCES = stest.c
@@ -319,11 +328,13 @@ nounwind.lo: config.h internal.h
 pecoff.lo: config.h backtrace.h internal.h
 posix.lo: config.h backtrace.h internal.h
 print.lo: config.h backtrace.h internal.h
+printdwarftest.lo: config.h backtrace.h internal.h testlib.h
 read.lo: config.h backtrace.h internal.h
 simple.lo: config.h backtrace.h internal.h
 sort.lo: config.h backtrace.h internal.h
 stest.lo: config.h backtrace.h internal.h
 state.lo: config.h backtrace.h backtrace-supported.h internal.h
+testlib.lo: $(INCDIR)/filenames.h backtrace.h testlib.h
 unknown.lo: config.h backtrace.h internal.h
 xcoff.lo: config.h backtrace.h internal.h
 
diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index d55e0501171..427a0c36161 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -120,18 +120,22 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
-check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
+check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
+	$(am__EXEEXT_4) $(am__EXEEXT_5)
 @NATIVE_TRUE@am__append_1 = test_elf test_xcoff_32 test_xcoff_64 \
 @NATIVE_TRUE@	test_pecoff test_unknown unittest unittest_alloc \
-@NATIVE_TRUE@	allocfail btest btest_alloc stest stest_alloc \
-@NATIVE_TRUE@	ztest ztest_alloc edtest edtest_alloc
+@NATIVE_TRUE@	allocfail btest btest_alloc
 @NATIVE_TRUE@am__append_2 = allocfail.sh
-@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_3 = btest_dwz
-@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_4 = -lz
-@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_5 = -lz
-@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_6 = ttest ttest_alloc
-@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_7 = dtest
-@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_8 = ctestg ctesta \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_3 = btest_dwz \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	printdwarftest_dwz_cmp.sh
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_4 = printdwarftest
+@NATIVE_TRUE@am__append_5 = stest stest_alloc ztest ztest_alloc edtest \
+@NATIVE_TRUE@	edtest_alloc
+@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_6 = -lz
+@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_7 = -lz
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_8 = ttest ttest_alloc
+@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_9 = dtest
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_10 = ctestg ctesta \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctestg_alloc \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctesta_alloc
 subdir = .
@@ -184,13 +188,14 @@ libbacktrace_noformat_la_OBJECTS =  \
 @NATIVE_TRUE@	test_xcoff_64$(EXEEXT) test_pecoff$(EXEEXT) \
 @NATIVE_TRUE@	test_unknown$(EXEEXT) unittest$(EXEEXT) \
 @NATIVE_TRUE@	unittest_alloc$(EXEEXT) allocfail$(EXEEXT) \
-@NATIVE_TRUE@	btest$(EXEEXT) btest_alloc$(EXEEXT) \
-@NATIVE_TRUE@	stest$(EXEEXT) stest_alloc$(EXEEXT) \
+@NATIVE_TRUE@	btest$(EXEEXT) btest_alloc$(EXEEXT)
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__EXEEXT_2 = printdwarftest$(EXEEXT)
+@NATIVE_TRUE@am__EXEEXT_3 = stest$(EXEEXT) stest_alloc$(EXEEXT) \
 @NATIVE_TRUE@	ztest$(EXEEXT) ztest_alloc$(EXEEXT) \
 @NATIVE_TRUE@	edtest$(EXEEXT) edtest_alloc$(EXEEXT)
-@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__EXEEXT_2 = ttest$(EXEEXT) \
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__EXEEXT_4 = ttest$(EXEEXT) \
 @HAVE_PTHREAD_TRUE@@NATIVE_TRUE@	ttest_alloc$(EXEEXT)
-@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__EXEEXT_3 =  \
+@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) \
 @HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctestg_alloc$(EXEEXT) \
@@ -258,6 +263,11 @@ edtest_OBJECTS = $(am_edtest_OBJECTS)
 @NATIVE_TRUE@am_edtest_alloc_OBJECTS = $(am__objects_5)
 edtest_alloc_OBJECTS = $(am_edtest_alloc_OBJECTS)
 @NATIVE_TRUE@edtest_alloc_DEPENDENCIES = libbacktrace_alloc.la
+am_printdwarftest_OBJECTS =
+printdwarftest_OBJECTS = $(am_printdwarftest_OBJECTS)
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest_DEPENDENCIES =  \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	libbacktrace.la printdwarftest.lo \
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@	testlib.lo
 @NATIVE_TRUE@am_stest_OBJECTS = stest.$(OBJEXT)
 stest_OBJECTS = $(am_stest_OBJECTS)
 @NATIVE_TRUE@stest_DEPENDENCIES = libbacktrace.la
@@ -373,8 +383,8 @@ SOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \
 	$(btest_SOURCES) $(btest_alloc_SOURCES) $(ctesta_SOURCES) \
 	$(ctesta_alloc_SOURCES) $(ctestg_SOURCES) \
 	$(ctestg_alloc_SOURCES) $(edtest_SOURCES) \
-	$(edtest_alloc_SOURCES) $(stest_SOURCES) \
-	$(stest_alloc_SOURCES) $(test_elf_SOURCES) \
+	$(edtest_alloc_SOURCES) $(printdwarftest_SOURCES) \
+	$(stest_SOURCES) $(stest_alloc_SOURCES) $(test_elf_SOURCES) \
 	$(test_pecoff_SOURCES) $(test_unknown_SOURCES) \
 	$(test_xcoff_32_SOURCES) $(test_xcoff_64_SOURCES) \
 	$(ttest_SOURCES) $(ttest_alloc_SOURCES) $(unittest_SOURCES) \
@@ -789,7 +799,7 @@ libbacktrace_la_LIBADD = \
 
 libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
 TESTS = $(check_PROGRAMS) $(am__append_2) $(am__append_3) \
-	$(am__append_7)
+	$(am__append_9)
 @NATIVE_TRUE@check_LTLIBRARIES = libbacktrace_alloc.la \
 @NATIVE_TRUE@	libbacktrace_noformat.la \
 @NATIVE_TRUE@	libbacktrace_instrumented_alloc.la
@@ -828,15 +838,17 @@ TESTS = $(check_PROGRAMS) $(am__append_2) $(am__append_3) \
 @NATIVE_TRUE@btest_alloc_SOURCES = $(btest_SOURCES)
 @NATIVE_TRUE@btest_alloc_CFLAGS = $(btest_CFLAGS)
 @NATIVE_TRUE@btest_alloc_LDADD = libbacktrace_alloc.la
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest_SOURCES = 
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest_LDADD = libbacktrace.la printdwarftest.lo testlib.lo
 @NATIVE_TRUE@stest_SOURCES = stest.c
 @NATIVE_TRUE@stest_LDADD = libbacktrace.la
 @NATIVE_TRUE@stest_alloc_SOURCES = $(stest_SOURCES)
 @NATIVE_TRUE@stest_alloc_LDADD = libbacktrace_alloc.la
 @NATIVE_TRUE@ztest_SOURCES = ztest.c testlib.c
 @NATIVE_TRUE@ztest_CFLAGS = -DSRCDIR=\"$(srcdir)\"
-@NATIVE_TRUE@ztest_LDADD = libbacktrace.la $(am__append_4) \
+@NATIVE_TRUE@ztest_LDADD = libbacktrace.la $(am__append_6) \
 @NATIVE_TRUE@	$(CLOCK_GETTIME_LINK)
-@NATIVE_TRUE@ztest_alloc_LDADD = libbacktrace_alloc.la $(am__append_5) \
+@NATIVE_TRUE@ztest_alloc_LDADD = libbacktrace_alloc.la $(am__append_7) \
 @NATIVE_TRUE@	$(CLOCK_GETTIME_LINK)
 @NATIVE_TRUE@ztest_alloc_SOURCES = $(ztest_SOURCES)
 @NATIVE_TRUE@ztest_alloc_CFLAGS = $(ztest_CFLAGS)
@@ -1021,6 +1033,10 @@ edtest_alloc$(EXEEXT): $(edtest_alloc_OBJECTS) $(edtest_alloc_DEPENDENCIES) $(EX
 	@rm -f edtest_alloc$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(edtest_alloc_OBJECTS) $(edtest_alloc_LDADD) $(LIBS)
 
+printdwarftest$(EXEEXT): $(printdwarftest_OBJECTS) $(printdwarftest_DEPENDENCIES) $(EXTRA_printdwarftest_DEPENDENCIES) 
+	@rm -f printdwarftest$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(printdwarftest_OBJECTS) $(printdwarftest_LDADD) $(LIBS)
+
 stest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) $(EXTRA_stest_DEPENDENCIES) 
 	@rm -f stest$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(stest_OBJECTS) $(stest_LDADD) $(LIBS)
@@ -1487,6 +1503,13 @@ btest_alloc.log: btest_alloc$(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)
+printdwarftest.log: printdwarftest$(EXEEXT)
+	@p='printdwarftest$(EXEEXT)'; \
+	b='printdwarftest'; \
+	$(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'; \
@@ -1585,6 +1608,13 @@ btest_dwz.log: btest_dwz
 	--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)
+printdwarftest_dwz_cmp.sh.log: printdwarftest_dwz_cmp.sh
+	@p='printdwarftest_dwz_cmp.sh'; \
+	b='printdwarftest_dwz_cmp.sh'; \
+	$(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'; \
@@ -1761,6 +1791,8 @@ uninstall-am:
 @HAVE_DWZ_TRUE@@NATIVE_TRUE@	rm -f $@_2
 @HAVE_DWZ_TRUE@@NATIVE_TRUE@	mv $@_1 $@
 
+@HAVE_DWZ_TRUE@@NATIVE_TRUE@printdwarftest_dwz_cmp.sh: printdwarftest_dwz
+
 @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
@@ -1783,11 +1815,13 @@ nounwind.lo: config.h internal.h
 pecoff.lo: config.h backtrace.h internal.h
 posix.lo: config.h backtrace.h internal.h
 print.lo: config.h backtrace.h internal.h
+printdwarftest.lo: config.h backtrace.h internal.h testlib.h
 read.lo: config.h backtrace.h internal.h
 simple.lo: config.h backtrace.h internal.h
 sort.lo: config.h backtrace.h internal.h
 stest.lo: config.h backtrace.h internal.h
 state.lo: config.h backtrace.h backtrace-supported.h internal.h
+testlib.lo: $(INCDIR)/filenames.h backtrace.h testlib.h
 unknown.lo: config.h backtrace.h internal.h
 xcoff.lo: config.h backtrace.h internal.h
 
diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index aacbd3a453d..2d4d9a5ab69 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -261,16 +261,6 @@ struct function_addrs
   struct function *function;
 };
 
-/* A growable vector of function address ranges.  */
-
-struct function_vector
-{
-  /* Memory.  This is an array of struct function_addrs.  */
-  struct backtrace_vector vec;
-  /* Number of address ranges present.  */
-  size_t count;
-};
-
 /* A DWARF compilation unit.  This only holds the information we need
    to map a PC to a file and line.  */
 
@@ -322,21 +312,6 @@ struct unit
   size_t function_addrs_count;
 };
 
-/* An address range for a compilation unit.  This maps a PC value to a
-   specific compilation unit.  Note that we invert the representation
-   in DWARF: instead of listing the units and attaching a list of
-   ranges, we list the ranges and have each one point to the unit.
-   This lets us do a binary search to find the unit.  */
-
-struct unit_addrs
-{
-  /* Range is LOW <= PC < HIGH.  */
-  uint64_t low;
-  uint64_t high;
-  /* Compilation unit for this address range.  */
-  struct unit *u;
-};
-
 /* A growable vector of compilation unit address ranges.  */
 
 struct unit_addrs_vector
@@ -355,43 +330,6 @@ struct unit_vector
   size_t count;
 };
 
-/* The information we need to map a PC to a file and line.  */
-
-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.  */
-  struct unit_addrs *addrs;
-  /* Number of address ranges in list.  */
-  size_t addrs_count;
-  /* A sorted list of units.  */
-  struct unit **units;
-  /* Number of units in the list.  */
-  size_t units_count;
-  /* The unparsed .debug_info section.  */
-  const unsigned char *dwarf_info;
-  size_t dwarf_info_size;
-  /* The unparsed .debug_line section.  */
-  const unsigned char *dwarf_line;
-  size_t dwarf_line_size;
-  /* The unparsed .debug_ranges section.  */
-  const unsigned char *dwarf_ranges;
-  size_t dwarf_ranges_size;
-  /* The unparsed .debug_str section.  */
-  const unsigned char *dwarf_str;
-  size_t dwarf_str_size;
-  /* Whether the data is big-endian or not.  */
-  int is_bigendian;
-  /* A vector used for function addresses.  We keep this here so that
-     we can grow the vector as we read more functions.  */
-  struct function_vector fvec;
-};
-
 /* Report an error for a DWARF buffer.  */
 
 static void
@@ -2809,7 +2747,7 @@ report_inlined_functions (uintptr_t pc, struct function *function,
    ERROR_CALLBACK and return 0.  Sets *FOUND to 1 if the PC is found,
    0 if not.  */
 
-static int
+int
 dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
 		 uintptr_t pc, backtrace_full_callback callback,
 		 backtrace_error_callback error_callback, void *data,
diff --git a/libbacktrace/internal.h b/libbacktrace/internal.h
index e8389779322..cfaf177647d 100644
--- a/libbacktrace/internal.h
+++ b/libbacktrace/internal.h
@@ -317,4 +317,72 @@ extern int backtrace_uncompress_zdebug (struct backtrace_state *,
 					unsigned char **uncompressed,
 					size_t *uncompressed_size);
 
+extern int dwarf_lookup_pc (struct backtrace_state *, struct dwarf_data *,
+			    uintptr_t, backtrace_full_callback,
+			    backtrace_error_callback, void *, int *);
+
+struct unit;
+
+/* An address range for a compilation unit.  This maps a PC value to a
+   specific compilation unit.  Note that we invert the representation
+   in DWARF: instead of listing the units and attaching a list of
+   ranges, we list the ranges and have each one point to the unit.
+   This lets us do a binary search to find the unit.  */
+
+struct unit_addrs
+{
+  /* Range is LOW <= PC < HIGH.  */
+  uint64_t low;
+  uint64_t high;
+  /* Compilation unit for this address range.  */
+  struct unit *u;
+};
+
+/* A growable vector of function address ranges.  */
+
+struct function_vector
+{
+  /* Memory.  This is an array of struct function_addrs.  */
+  struct backtrace_vector vec;
+  /* Number of address ranges present.  */
+  size_t count;
+};
+
+/* The information we need to map a PC to a file and line.  */
+
+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.  */
+  struct unit_addrs *addrs;
+  /* Number of address ranges in list.  */
+  size_t addrs_count;
+  /* A sorted list of units.  */
+  struct unit **units;
+  /* Number of units in the list.  */
+  size_t units_count;
+  /* The unparsed .debug_info section.  */
+  const unsigned char *dwarf_info;
+  size_t dwarf_info_size;
+  /* The unparsed .debug_line section.  */
+  const unsigned char *dwarf_line;
+  size_t dwarf_line_size;
+  /* The unparsed .debug_ranges section.  */
+  const unsigned char *dwarf_ranges;
+  size_t dwarf_ranges_size;
+  /* The unparsed .debug_str section.  */
+  const unsigned char *dwarf_str;
+  size_t dwarf_str_size;
+  /* Whether the data is big-endian or not.  */
+  int is_bigendian;
+  /* A vector used for function addresses.  We keep this here so that
+     we can grow the vector as we read more functions.  */
+  struct function_vector fvec;
+};
+
 #endif
diff --git a/libbacktrace/printdwarftest.c b/libbacktrace/printdwarftest.c
new file mode 100644
index 00000000000..775e23d4ed3
--- /dev/null
+++ b/libbacktrace/printdwarftest.c
@@ -0,0 +1,208 @@
+/* printdwarftest.c -- Print dwarf info cached by libbacktrace.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+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.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+#include "testlib.h"
+
+static void
+error_callback (void *vdata ATTRIBUTE_UNUSED, const char *msg ATTRIBUTE_UNUSED,
+		int errnum ATTRIBUTE_UNUSED)
+{
+}
+
+static int
+dummmy_callback (void *data ATTRIBUTE_UNUSED, uintptr_t pc ATTRIBUTE_UNUSED,
+		 const char *filename ATTRIBUTE_UNUSED,
+		 int lineno ATTRIBUTE_UNUSED,
+		 const char *function ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+struct print_callback_data
+{
+  uintptr_t base_address;
+  uintptr_t pc;
+  const char *filename;
+  int lineno;
+  const char *function;
+  uintptr_t d1_pc;
+  const char *d1_filename;
+  int d1_lineno;
+  const char *d1_function;
+  int depth;
+  int stack_printed;
+  int skip;
+};
+
+static int
+print_callback (void *data, uintptr_t pc ATTRIBUTE_UNUSED,
+		const char *filename ATTRIBUTE_UNUSED,
+		int lineno ATTRIBUTE_UNUSED,
+		const char *function ATTRIBUTE_UNUSED)
+{
+  struct print_callback_data *prev = (struct print_callback_data *)data;
+
+  prev->depth++;
+  if (prev->depth == 1)
+    {
+      if (prev->stack_printed)
+	prev->skip = 1;
+    }
+  else
+    {
+      if (prev->skip)
+	return 0;
+
+      fprintf (stderr, " %s@%d", function, prev->depth);
+      fprintf (stderr, " %d", lineno);
+      prev->stack_printed = 1;
+
+      return 0;
+    }
+
+  if (function == NULL)
+    return 0;
+
+  if (prev->pc == 0)
+    {
+      fprintf (stderr, "%p", (void *)(pc - prev->base_address));
+      fprintf (stderr, " %s@%d", function, prev->depth);
+      fprintf (stderr, " %s", filename);
+      fprintf (stderr, "\n  %d", lineno);
+      fprintf (stderr, "@%p", (void *)(pc - prev->base_address));
+      goto update;
+    }
+
+  if (function != prev->function)
+    {
+      if (pc != prev->pc)
+	{
+	  fprintf (stderr, "\n");
+	  fprintf (stderr, "%p", (void *)(pc - prev->base_address));
+	  fprintf (stderr, " %s@%d", function, prev->depth);
+	}
+      else
+	fprintf (stderr, " %s@%d", function, prev->depth);
+    }
+
+  if (filename != prev->filename)
+    fprintf (stderr, " %s", filename);
+
+  if (lineno != prev->lineno)
+    {
+      prev->stack_printed = 0;
+      prev->skip = 0;
+      fprintf (stderr, "\n  %d", lineno);
+      fprintf (stderr, "@%p", (void *)(pc - prev->base_address));
+    }
+
+ update:
+  prev->pc = pc;
+  prev->filename = filename;
+  prev->lineno = lineno;
+  prev->function = function;
+  if (prev->depth == 1)
+    {
+      prev->d1_pc = pc;
+      prev->d1_filename = filename;
+      prev->d1_lineno = lineno;
+      prev->d1_function = function;
+    }
+  return 0;
+}
+
+static void
+print_dwarf_data (struct backtrace_state *state, void *data)
+{
+  struct dwarf_data *fdata;
+  unsigned int i;
+
+  fdata = (struct dwarf_data *)data;
+
+  for (i = 0; i < fdata->addrs_count; ++i)
+    {
+      struct unit_addrs *addr = &fdata->addrs[i];
+      uintptr_t pc;
+
+      struct print_callback_data tdata;
+      tdata.base_address = fdata->base_address;
+      tdata.pc = 0;
+      tdata.stack_printed = 0;
+      tdata.skip = 0;
+      for (pc = addr->low; pc < addr->high; ++pc)
+	{
+	  int found;
+	  tdata.depth = 0;
+	  dwarf_lookup_pc (state, fdata, pc, print_callback, error_callback,
+			   &tdata, &found);
+	  if (!found)
+	    fprintf (stderr, "not found: %p\n", (void *)pc);
+	}
+      if (tdata.pc != 0)
+	fprintf (stderr, "\n");
+    }
+}
+
+static void
+print_dwarf_cache (struct backtrace_state *state)
+{
+  struct dwarf_data **pp;
+
+  if (state->fileline_data == NULL)
+    backtrace_pcinfo (state, (uintptr_t)print_callback, dummmy_callback,
+		      NULL, NULL);
+
+  for (pp = (struct dwarf_data **) (void *) &state->fileline_data;
+       *pp != NULL;
+       pp = &(*pp)->next)
+    print_dwarf_data (state, *pp);
+}
+
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv)
+{
+  state = backtrace_create_state (argv[0], 0, error_callback_create, NULL);
+
+  print_dwarf_cache ((struct backtrace_state *)state);
+
+  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/libbacktrace/printdwarftest_dwz_cmp.sh b/libbacktrace/printdwarftest_dwz_cmp.sh
new file mode 100755
index 00000000000..617de00ece8
--- /dev/null
+++ b/libbacktrace/printdwarftest_dwz_cmp.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+log1=printdwarftest_dwz.1.log
+log2=printdwarftest_dwz.2.log
+
+./printdwarftest 2> $log1
+./printdwarftest_dwz 2> $log2
+cmp $log1 $log2

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 9/9] [libbacktrace] Add printdwarftest_dwz_cmp.sh test-case
  2019-01-19  0:45       ` Tom de Vries
@ 2019-01-19  0:54         ` Ian Lance Taylor via gcc-patches
  2019-01-22 22:03           ` Tom de Vries
  0 siblings, 1 reply; 47+ messages in thread
From: Ian Lance Taylor via gcc-patches @ 2019-01-19  0:54 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches, Ian Lance Taylor

On Fri, Jan 18, 2019 at 4:45 PM Tom de Vries <tdevries@suse.de> wrote:
>
> On 18-01-19 15:23, Ian Lance Taylor wrote:
> > On Thu, Jan 17, 2019 at 5:59 AM Tom de Vries <tdevries@suse.de> wrote:
> >>
> >> now that the rest of the patch series has been committed, here's an
> >> updated version of this patch that applies to trunk.
> >
> > I would much rather put dwarf_data into internal.h than to #include
> > "dwarf.c" from a different file.  Using #include with a .c file is
> > just a bad path to walk down.
>
> This version avoids the include of dwarf.c.
>
> Does that look better?

> +printdwarftest_SOURCES =
> +printdwarftest_LDADD = libbacktrace.la printdwarftest.lo testlib.lo

Seems like you could write

printdwarftest_SOURCES = printdwarftest.c testlib.c
printdwarftest_LDADD = libbacktrace.la

> -static int
> +int
>  dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,

Ah, I didn't consider this.  We can't do this.  It will break code
like libsanitizer/libbacktrace/backtrace-rename.h.

Is there a way that we could run a similar test looking at the output
of readelf --debug?

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 9/9] [libbacktrace] Add printdwarftest_dwz_cmp.sh test-case
  2019-01-19  0:54         ` Ian Lance Taylor via gcc-patches
@ 2019-01-22 22:03           ` Tom de Vries
  2019-01-29 15:31             ` Ian Lance Taylor
  0 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-22 22:03 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches, Ian Lance Taylor

On 19-01-19 01:54, Ian Lance Taylor wrote:
> On Fri, Jan 18, 2019 at 4:45 PM Tom de Vries <tdevries@suse.de> wrote:
>>
>> On 18-01-19 15:23, Ian Lance Taylor wrote:
>>> On Thu, Jan 17, 2019 at 5:59 AM Tom de Vries <tdevries@suse.de> wrote:
>>>>
>>>> now that the rest of the patch series has been committed, here's an
>>>> updated version of this patch that applies to trunk.
>>>
>>> I would much rather put dwarf_data into internal.h than to #include
>>> "dwarf.c" from a different file.  Using #include with a .c file is
>>> just a bad path to walk down.
>>
>> This version avoids the include of dwarf.c.
>>
>> Does that look better?
> 
>> +printdwarftest_SOURCES =
>> +printdwarftest_LDADD = libbacktrace.la printdwarftest.lo testlib.lo
> 
> Seems like you could write
> 
> printdwarftest_SOURCES = printdwarftest.c testlib.c
> printdwarftest_LDADD = libbacktrace.la
> 

That's what I had initially, but I realized that that makes it harder to
keep dependencies correct.  That is, now I've added the dependencies:
...
+printdwarftest.lo: config.h backtrace.h internal.h testlib.h
+testlib.lo: $(INCDIR)/filenames.h backtrace.h testlib.h
...
and that works for "printdwarftest_LDADD = ... printdwarftest.lo
testlib.lo".

When doing this instead:
...
printdwarftest_SOURCES = printdwarftest.c testlib.c
printdwarftest_LDADD = libbacktrace.la
...
no printdwarftest.lo or testlib.lo is generated.

So, I could rewrite the dependencies to:
...
+printdwarftest.o: config.h backtrace.h internal.h testlib.h
+printdwarftest.obj: config.h backtrace.h internal.h testlib.h
+testlib.o: $(INCDIR)/filenames.h backtrace.h testlib.h
+testlib.obj: $(INCDIR)/filenames.h backtrace.h testlib.h
...
but that looks somewhat fragile, because when adding:
...
+printdwarftest_CFLAGS = -fno-tree-tail-merge
...
we need to rewrite the dependencies to:
...
+printdwarftest-printdwarftest.o: config.h backtrace.h internal.h testlib.h
+printdwarftest-printdwarftest.obj: config.h backtrace.h internal.h
testlib.h
+printdwarftest-testlib.o: $(INCDIR)/filenames.h backtrace.h testlib.h
+printdwarftest-testlib.obj: $(INCDIR)/filenames.h backtrace.h testlib.h
...

>> -static int
>> +int
>>  dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
> 
> Ah, I didn't consider this.  We can't do this.  It will break code
> like libsanitizer/libbacktrace/backtrace-rename.h.
> 
> Is there a way that we could run a similar test looking at the output
> of readelf --debug?

No, not really. We're not interested in the contents of the debug
information as such. We're interested in the representation of that
information that libbacktrace builds from it, and the test compares that
representation with and without dwz, to make sure no information got
lost (which could indicate a dwz bug, or a lacking feature in libbacktrace).

With a normal backtrace test, you just ask for information about a
couple of locations.  With this test, you ask for all the information,
giving libbacktrace a probing you just can't get with a normal test, so
I think it's a good idea to have it.

What is an acceptable way to proceed here? I could add a
libbacktrace_nodwarf.la, and have the test-case add a -DFOR_TESTING or
some such when compiling dwarf.c, and add the necessary handling in
dwarf.c conditional on FOR_TESTING. WDYT?

Thanks,
- Tom

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [libbacktrace] Use size_t for low_offset/high_offset fields of struct unit
  2019-01-18 14:26         ` Ian Lance Taylor
@ 2019-01-22 22:17           ` Tom de Vries
  2019-01-22 23:05             ` Ian Lance Taylor
  0 siblings, 1 reply; 47+ messages in thread
From: Tom de Vries @ 2019-01-22 22:17 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3151 bytes --]

[ was: Re: [PATCH 7/9] [libbacktrace] Handle DW_FORM_GNU_ref_alt ]
On 18-01-19 15:25, Ian Lance Taylor wrote:
> On Thu, Jan 17, 2019 at 6:14 AM Tom de Vries <tdevries@suse.de> wrote:
>>
>> On 17-01-19 01:35, Ian Lance Taylor wrote:
>>> On Wed, Jan 16, 2019 at 4:17 PM Tom de Vries <tdevries@suse.de> wrote:
>>>>
>>>> this handles DW_FORM_GNU_ref_alt which references the .debug_info
>>>> section in the .gnu_debugaltlink file.
>>>>
>>>> OK for trunk?
>>>>
>>>> Thanks,
>>>> - Tom
>>>>
>>>> On 11-12-18 11:14, Tom de Vries wrote:
>>>>> 2018-12-10  Tom de Vries  <tdevries@suse.de>
>>>>>
>>>>>       * dwarf.c (enum attr_val_encoding): Add ATTR_VAL_REF_ALT_INFO.
>>>>>       (struct unit): Add low and high fields.
>>>>>       (struct unit_vector): New type.
>>>>>       (struct dwarf_data): Add units and units_counts fields.
>>>>>       (read_attribute): Handle DW_FORM_GNU_ref_alt using
>>>>>       ATTR_VAL_REF_ALT_INFO.
>>>>>       (find_unit): New function.
>>>>>       (find_address_ranges): Add and handle unit_tag parameter.
>>>>>       (build_address_map): Add and handle units_vec parameter.
>>>>>       (read_referenced_name_1): Handle DW_FORM_GNU_ref_alt.
>>>>>       (build_dwarf_data): Pass units_vec to build_address_map.  Store resulting
>>>>>       units vector.
>>>
>>>
>>>>> @@ -281,6 +283,10 @@ struct unit
>>>>>    /* The offset of UNIT_DATA from the start of the information for
>>>>>       this compilation unit.  */
>>>>>    size_t unit_data_offset;
>>>>> +  /* Start of the compilation unit.  */
>>>>> +  size_t low;
>>>>> +  /* End of the compilation unit.  */
>>>>> +  size_t high;
>>>
>>> The comments should say what low and high are measured in, which I
>>> guess is file offset.  Or is it offset from the start of UNIT_DATA?
>>> Either way, If that is right, then the fields should be named
>>> low_offset and high_offset.  Otherwise it seems easy to confuse with
>>> function_addrs, where low and high refer to PC values.
>>>
>>
>> Done.
>>
>>> Also if they are offsets from UNIT_DATA then size_t is OK, but if the
>>> are file offsets they should be off_t.
>>>
>>
>> AFAIU, in the case where off_t vs size_t would make a difference, we're
>> running into trouble much earlier.  I've filed PR 88890 - "libbacktrace
>> on 32-bit system with _FILE_OFFSET_BITS == 64" (
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88890 ) about this.
>>
>> Anyway, I've made the conservative choice of using off_t for now (but I
>> could argue that it's a memory offset, given that the assumption is that
>> the entire debug section is read into memory).
> 
> Since the entire debug section is read into memory, if they are
> offsets from UNIT_DATA, they should be size_t, not off_t.  I wasn't
> trying to say that we should make a conservative choice here, I was
> trying to say that we should make a correct choice.  An offset from
> UNIT_DATA should be size_t, a file offset should be off_t.

These are offsets from the start of the .debug_info section, so AFAIU
that means these could be size_t.

Tested with x86_64 build and host libbacktrace make check.

OK for trunk if bootstrap and reg-test on x86_64 succeeds?

Thanks,
- Tom


[-- Attachment #2: 0001-libbacktrace-Use-size_t-for-low_offset-high_offset-fields-of-struct-unit.patch --]
[-- Type: text/x-patch, Size: 2055 bytes --]

[libbacktrace] Use size_t for low_offset/high_offset fields of struct unit

2019-01-22  Tom de Vries  <tdevries@suse.de>

	* dwarf.c (struct unit): Use size_t for low_offset/high_offset fields.
	(units_search, find_unit): Use size_t for offset.
	(build_address_map): Use size_t for unit_offset.

---
 libbacktrace/dwarf.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index aacbd3a453d..e78d36b0b43 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -285,10 +285,10 @@ struct unit
   size_t unit_data_offset;
   /* Offset of the start of the compilation unit from the start of the
      .debug_info section.  */
-  off_t low_offset;
+  size_t low_offset;
   /* Offset of the end of the compilation unit from the start of the
      .debug_info section.  */
-  off_t high_offset;
+  size_t high_offset;
   /* DWARF version.  */
   int version;
   /* Whether unit is DWARF64.  */
@@ -891,9 +891,9 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
 static int
 units_search (const void *vkey, const void *ventry)
 {
-  const off_t *key = (const off_t *) vkey;
+  const size_t *key = (const size_t *) vkey;
   const struct unit *entry = *((const struct unit *const *) ventry);
-  off_t offset;
+  size_t offset;
 
   offset = *key;
   if (offset < entry->low_offset)
@@ -907,7 +907,7 @@ units_search (const void *vkey, const void *ventry)
 /* Find a unit in PU containing OFFSET.  */
 
 static struct unit *
-find_unit (struct unit **pu, size_t units_count, off_t offset)
+find_unit (struct unit **pu, size_t units_count, size_t offset)
 {
   struct unit **u;
   u = bsearch (&offset, pu, units_count, sizeof (struct unit *), units_search);
@@ -1514,7 +1514,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
   size_t i;
   struct unit **pu;
   size_t prev_addrs_count;
-  off_t unit_offset = 0;
+  size_t unit_offset = 0;
 
   memset (&addrs->vec, 0, sizeof addrs->vec);
   memset (&unit_vec->vec, 0, sizeof unit_vec->vec);

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [libbacktrace] Use size_t for low_offset/high_offset fields of struct unit
  2019-01-22 22:17           ` [libbacktrace] Use size_t for low_offset/high_offset fields of struct unit Tom de Vries
@ 2019-01-22 23:05             ` Ian Lance Taylor
  0 siblings, 0 replies; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-22 23:05 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Tue, Jan 22, 2019 at 2:03 PM Tom de Vries <tdevries@suse.de> wrote:
>
> [ was: Re: [PATCH 7/9] [libbacktrace] Handle DW_FORM_GNU_ref_alt ]
> On 18-01-19 15:25, Ian Lance Taylor wrote:
> > On Thu, Jan 17, 2019 at 6:14 AM Tom de Vries <tdevries@suse.de> wrote:
> >>
> >> On 17-01-19 01:35, Ian Lance Taylor wrote:
> >>> On Wed, Jan 16, 2019 at 4:17 PM Tom de Vries <tdevries@suse.de> wrote:
> >>>>
> >>>> this handles DW_FORM_GNU_ref_alt which references the .debug_info
> >>>> section in the .gnu_debugaltlink file.
> >>>>
> >>>> OK for trunk?
> >>>>
> >>>> Thanks,
> >>>> - Tom
> >>>>
> >>>> On 11-12-18 11:14, Tom de Vries wrote:
> >>>>> 2018-12-10  Tom de Vries  <tdevries@suse.de>
> >>>>>
> >>>>>       * dwarf.c (enum attr_val_encoding): Add ATTR_VAL_REF_ALT_INFO.
> >>>>>       (struct unit): Add low and high fields.
> >>>>>       (struct unit_vector): New type.
> >>>>>       (struct dwarf_data): Add units and units_counts fields.
> >>>>>       (read_attribute): Handle DW_FORM_GNU_ref_alt using
> >>>>>       ATTR_VAL_REF_ALT_INFO.
> >>>>>       (find_unit): New function.
> >>>>>       (find_address_ranges): Add and handle unit_tag parameter.
> >>>>>       (build_address_map): Add and handle units_vec parameter.
> >>>>>       (read_referenced_name_1): Handle DW_FORM_GNU_ref_alt.
> >>>>>       (build_dwarf_data): Pass units_vec to build_address_map.  Store resulting
> >>>>>       units vector.
> >>>
> >>>
> >>>>> @@ -281,6 +283,10 @@ struct unit
> >>>>>    /* The offset of UNIT_DATA from the start of the information for
> >>>>>       this compilation unit.  */
> >>>>>    size_t unit_data_offset;
> >>>>> +  /* Start of the compilation unit.  */
> >>>>> +  size_t low;
> >>>>> +  /* End of the compilation unit.  */
> >>>>> +  size_t high;
> >>>
> >>> The comments should say what low and high are measured in, which I
> >>> guess is file offset.  Or is it offset from the start of UNIT_DATA?
> >>> Either way, If that is right, then the fields should be named
> >>> low_offset and high_offset.  Otherwise it seems easy to confuse with
> >>> function_addrs, where low and high refer to PC values.
> >>>
> >>
> >> Done.
> >>
> >>> Also if they are offsets from UNIT_DATA then size_t is OK, but if the
> >>> are file offsets they should be off_t.
> >>>
> >>
> >> AFAIU, in the case where off_t vs size_t would make a difference, we're
> >> running into trouble much earlier.  I've filed PR 88890 - "libbacktrace
> >> on 32-bit system with _FILE_OFFSET_BITS == 64" (
> >> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88890 ) about this.
> >>
> >> Anyway, I've made the conservative choice of using off_t for now (but I
> >> could argue that it's a memory offset, given that the assumption is that
> >> the entire debug section is read into memory).
> >
> > Since the entire debug section is read into memory, if they are
> > offsets from UNIT_DATA, they should be size_t, not off_t.  I wasn't
> > trying to say that we should make a conservative choice here, I was
> > trying to say that we should make a correct choice.  An offset from
> > UNIT_DATA should be size_t, a file offset should be off_t.
>
> These are offsets from the start of the .debug_info section, so AFAIU
> that means these could be size_t.
>
> Tested with x86_64 build and host libbacktrace make check.
>
> OK for trunk if bootstrap and reg-test on x86_64 succeeds?

This is OK.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 9/9] [libbacktrace] Add printdwarftest_dwz_cmp.sh test-case
  2019-01-22 22:03           ` Tom de Vries
@ 2019-01-29 15:31             ` Ian Lance Taylor
  0 siblings, 0 replies; 47+ messages in thread
From: Ian Lance Taylor @ 2019-01-29 15:31 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gcc-patches

On Tue, Jan 22, 2019 at 1:43 PM Tom de Vries <tdevries@suse.de> wrote:
>
> What is an acceptable way to proceed here? I could add a
> libbacktrace_nodwarf.la, and have the test-case add a -DFOR_TESTING or
> some such when compiling dwarf.c, and add the necessary handling in
> dwarf.c conditional on FOR_TESTING. WDYT?

I guess we could try it.

I'm very seriously concerned with the additional complexity being
added to this package.  It has to live in a very constrained space and
it's already complex.  Sacrificing maintainability for testing is a
bad tradeoff in the long run.  But we can try it.

Ian

^ permalink raw reply	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2019-01-29 15:29 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-11 10:14 [PATCH 0/9] [libbacktrace] Handle .gnu_debugaltlink Tom de Vries
2018-12-11 10:14 ` [PATCH 2/9] [libbacktrace] Add altlink field to struct dwarf_data Tom de Vries
2019-01-16  1:02   ` Ian Lance Taylor
2019-01-16 16:33     ` Tom de Vries
2019-01-16 16:34       ` Tom de Vries
2019-01-16 22:20         ` Tom de Vries
2019-01-16 22:25           ` Ian Lance Taylor
2019-01-16 17:17       ` Ian Lance Taylor
2019-01-16 22:18         ` Tom de Vries
2019-01-16 22:40           ` Ian Lance Taylor
2018-12-11 10:14 ` [PATCH 9/9] [libbacktrace] Add printdwarftest_dwz_cmp.sh test-case Tom de Vries
2019-01-17 13:58   ` Tom de Vries
2019-01-18 14:24     ` Ian Lance Taylor via gcc-patches
2019-01-19  0:45       ` Tom de Vries
2019-01-19  0:54         ` Ian Lance Taylor via gcc-patches
2019-01-22 22:03           ` Tom de Vries
2019-01-29 15:31             ` Ian Lance Taylor
2018-12-11 10:14 ` [PATCH 4/9] [libbacktrace] Handle DW_FORM_GNU_strp_alt Tom de Vries
2019-01-16  1:07   ` Ian Lance Taylor via gcc-patches
2018-12-11 10:14 ` [PATCH 6/9] [libbacktrace] Factor out read_referenced_name_1 Tom de Vries
2019-01-16  1:15   ` Ian Lance Taylor via gcc-patches
2019-01-16 16:37     ` Tom de Vries
2019-01-16 18:26       ` Ian Lance Taylor
2018-12-11 10:14 ` [PATCH 3/9] [libbacktrace] Handle alt FORMS without .gnu_debugaltlink Tom de Vries
2019-01-16  1:06   ` Ian Lance Taylor
2019-01-16 16:34     ` Tom de Vries
2019-01-16 18:24       ` Ian Lance Taylor
2018-12-11 10:14 ` [PATCH 1/9] [libbacktrace] Read .gnu_debugaltlink Tom de Vries
2019-01-16  0:56   ` Ian Lance Taylor via gcc-patches
2019-01-16 16:26     ` Tom de Vries
2019-01-16 17:15       ` Ian Lance Taylor via gcc-patches
2019-01-16 22:48         ` Tom de Vries
2019-01-16 23:21           ` Ian Lance Taylor
2018-12-11 10:14 ` [PATCH 5/9] [libbacktrace] Unify function name preference handling Tom de Vries
2019-01-16  1:10   ` Ian Lance Taylor via gcc-patches
2018-12-11 10:14 ` [PATCH 8/9] [libbacktrace] Add btest_dwz test-case Tom de Vries
2019-01-16  1:19   ` Ian Lance Taylor
2019-01-16 16:39     ` Tom de Vries
2019-01-16 18:30       ` Ian Lance Taylor
2018-12-11 10:14 ` [PATCH 7/9] [libbacktrace] Handle DW_FORM_GNU_ref_alt Tom de Vries
2019-01-17  0:17   ` Tom de Vries
2019-01-17  0:36     ` Ian Lance Taylor
2019-01-17 14:14       ` Tom de Vries
2019-01-17 14:16         ` Tom de Vries
2019-01-18 14:26         ` Ian Lance Taylor
2019-01-22 22:17           ` [libbacktrace] Use size_t for low_offset/high_offset fields of struct unit Tom de Vries
2019-01-22 23:05             ` Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).