[libbacktrace] Handle DW_FORM_GNU_ref_alt

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

2019-01-17  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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@268031 138bc75d-0d04-0410-961f-82ee72b054a4
diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog
index 1fd307b..191bfa3 100644
--- a/libbacktrace/ChangeLog
+++ b/libbacktrace/ChangeLog
@@ -1,5 +1,13 @@
 2019-01-17  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.
+
+2019-01-17  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.
diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 6f56c46..aacbd3a 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -143,6 +143,8 @@
   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 @@
 	  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 @@
       || 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;
 }