public inbox for dwz@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Split DWARF support for DWZ
@ 2021-08-23  5:35 Sharma, Alok Kumar
  2021-10-03 12:37 ` Sharma, Alok Kumar
  0 siblings, 1 reply; 2+ messages in thread
From: Sharma, Alok Kumar @ 2021-08-23  5:35 UTC (permalink / raw)
  To: dwz; +Cc: George, Jini Susan, Achra, Nitika, E, Nagajyothi, Joseph, Ancel

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

Hi all,

I request you to please review the source modification done to support split DWARF.

    Existing DWZ when deals with executable having split DWARF information
    in separate file (DW_AT_GNU_dwo_name/DW_AT_dwo_name), it ignores the
    separate file and only attempts to optimize main executable which has
    very less information as almost all the debug information is present
    in sepaterate file.

    Now DWZ is modified to extract the separate file name from
    atributes DW_AT_GNU_dwo_name/DW_AT_dwo_name in main executable and
    calls function DWZ on separate file as well.

    While processing DWO file, information is read from corresponding ".dwo"
    sections in place of original one. This is assisted by macros
    DEFINE_DEBUG (defining section enum) and DEFINE_SECTION (defining section
    names along with other fields) in a way that very next section to the
    original one is the ".dwo" variant of it. When we process DWO file we
    access section using macro "INDEX(DEBUG_SECTION)", which is defined as
    "(DEBUG_SECTION + is_dwo_file)". This way we avoid any duplicacy and
    use existing code.

Regards,
Alok

[-- Attachment #2: 0001-Split-DWARF-support-for-DWZ.patch --]
[-- Type: application/octet-stream, Size: 81705 bytes --]

From b3f5ed99085a08455c13688f214e10a1f22c570b Mon Sep 17 00:00:00 2001
From: Alok Kumar Sharma <AlokKumar.Sharma@amd.com>
Date: Fri, 12 Feb 2021 16:44:04 +0530
Subject: [PATCH 1/9] Split DWARF support for DWZ

Existing DWZ when deals with executable having split DWARF information
in separate file (DW_AT_GNU_dwo_name/DW_AT_dwo_name), it ignores the
separate file and only attempts to optimize main executable which has
very less information as almost all the debug information is present
in sepaterate file.

Now DWZ is modified to extract the separate file name from
atributes DW_AT_GNU_dwo_name/DW_AT_dwo_name in main executable and
calls function DWZ on separate file as well.

While processing DWO file, information is read from corresponding ".dwo"
sections in place of original one. This is assisted by macros
DEFINE_DEBUG (defining section enum) and DEFINE_SECTION (defining section
names along with other fields) in a way that very next section to the
original one is the ".dwo" variant of it. When we process DWO file we
access section using macro "INDEX(DEBUG_SECTION)", which is defined as
"(DEBUG_SECTION + is_dwo_file)". This way we avoid any duplicacy and
use existing code.
---
 dwz.c | 853 +++++++++++++++++++++++++++++++---------------------------
 1 file changed, 461 insertions(+), 392 deletions(-)

diff --git a/dwz.c b/dwz.c
index a3b289f..87d526b 100644
--- a/dwz.c
+++ b/dwz.c
@@ -112,6 +112,15 @@
 # define NT_GNU_BUILD_ID 3
 #endif
 
+/* Name of DWO file is stored in 'dwofile' from DW_AT_dwo_name or
+   DW_AT_GNU_dwo_name of DW_TAG_compile_unit die from main executable.  */
+static char *dwofile = NULL;
+
+/* If 'dwofile' is found in DW_TAG_compile_unit, additionally dwz is called
+   for 'dwofile' as well, which has all the debug info and opportuity for
+   optimizations.  */
+static int is_dwo_file = false;
+
 /* Print memory amount M (in kb) in both exact and human readable, like so:
    1382508 (1.3G).  */
 static void
@@ -712,36 +721,55 @@ get_DW_LNCT_str (unsigned int lnct)
   return buf;
 }
 
+/* The macro DEFINE_DEBUG is used to declare dwo variant along with original
+   enum.  Ex {DEBUG_INFO, DEBUG_INFO_DWO, DEBUG_ABBREV, DEBUG_ABBREV_DWO, ... */
+#define DEFINE_DEBUG(kind) kind, kind##_DWO
 /* This must match the debug_sections array content
    below.  */
 enum debug_section_kind
 {
-  DEBUG_INFO,
-  DEBUG_ABBREV,
-  DEBUG_LINE,
-  DEBUG_STR,
-  DEBUG_MACRO,
-  DEBUG_TYPES,
-  DEBUG_ARANGES,
-  DEBUG_PUBNAMES,
-  DEBUG_PUBTYPES,
-  DEBUG_GNU_PUBNAMES,
-  DEBUG_GNU_PUBTYPES,
-  DEBUG_MACINFO,
-  DEBUG_LOC,
-  DEBUG_LOCLISTS,
-  DEBUG_FRAME,
-  DEBUG_RANGES,
-  DEBUG_RNGLISTS,
-  DEBUG_LINE_STR,
-  DEBUG_SUP,
-  DEBUG_GDB_SCRIPTS,
-  GDB_INDEX,
-  GNU_DEBUGALTLINK,
+  DEFINE_DEBUG(DEBUG_INFO),
+  DEFINE_DEBUG(DEBUG_ABBREV),
+  DEFINE_DEBUG(DEBUG_LINE),
+  DEFINE_DEBUG(DEBUG_STR),
+  DEFINE_DEBUG(DEBUG_MACRO),
+  DEFINE_DEBUG(DEBUG_TYPES),
+  DEFINE_DEBUG(DEBUG_ARANGES),
+  DEFINE_DEBUG(DEBUG_PUBNAMES),
+  DEFINE_DEBUG(DEBUG_PUBTYPES),
+  DEFINE_DEBUG(DEBUG_GNU_PUBNAMES),
+  DEFINE_DEBUG(DEBUG_GNU_PUBTYPES),
+  DEFINE_DEBUG(DEBUG_MACINFO),
+  DEFINE_DEBUG(DEBUG_LOC),
+  DEFINE_DEBUG(DEBUG_LOCLISTS),
+  DEFINE_DEBUG(DEBUG_FRAME),
+  DEFINE_DEBUG(DEBUG_RANGES),
+  DEFINE_DEBUG(DEBUG_RNGLISTS),
+  DEFINE_DEBUG(DEBUG_LINE_STR),
+  DEFINE_DEBUG(DEBUG_SUP),
+  DEFINE_DEBUG(DEBUG_GDB_SCRIPTS),
+  DEFINE_DEBUG(GDB_INDEX),
+  DEFINE_DEBUG(GNU_DEBUGALTLINK),
   SECTION_COUNT,
-  SAVED_SECTIONS = DEBUG_TYPES + 1
+  SAVED_SECTIONS = DEBUG_TYPES_DWO + 1,
 };
 
+/* Macro DEFINE_DEBUG sure ".dwo" sections are preseved just next to the
+   corresponding original section. is_dwo_file is 1 when processing dwo file  */
+#define INDEX(DEBUG_SECTION) (DEBUG_SECTION + is_dwo_file)
+
+/* Original and corresponding .dwo sections are kept together.
+   Ex.
+        {".debug_info", NULL, NULL, 0, 0, 0 },
+        {".debug_info.dwo", NULL, NULL, 0, 0, 0 },
+        {".debug_abbrev", NULL, NULL, 0, 0, 0 },
+        {".debug_abbrev.dwo", NULL, NULL, 0, 0, 0 },
+*/
+
+#define DEFINE_SECTION(name) \
+        {#name, NULL, NULL, 0, 0, 0 }, \
+        {#name".dwo", NULL, NULL, 0, 0, 0 }
+
 /* Details about standard DWARF sections.  */
 static struct
 {
@@ -753,28 +781,28 @@ static struct
   int sec;
 } debug_sections[] =
   {
-    { ".debug_info", NULL, NULL, 0, 0, 0 },
-    { ".debug_abbrev", NULL, NULL, 0, 0, 0 },
-    { ".debug_line", NULL, NULL, 0, 0, 0 },
-    { ".debug_str", NULL, NULL, 0, 0, 0 },
-    { ".debug_macro", NULL, NULL, 0, 0, 0 },
-    { ".debug_types", NULL, NULL, 0, 0, 0 },
-    { ".debug_aranges", NULL, NULL, 0, 0, 0 },
-    { ".debug_pubnames", NULL, NULL, 0, 0, 0 },
-    { ".debug_pubtypes", NULL, NULL, 0, 0, 0 },
-    { ".debug_gnu_pubnames", NULL, NULL, 0, 0, 0 },
-    { ".debug_gnu_pubtypes", NULL, NULL, 0, 0, 0 },
-    { ".debug_macinfo", NULL, NULL, 0, 0, 0 },
-    { ".debug_loc", NULL, NULL, 0, 0, 0 },
-    { ".debug_loclists", NULL, NULL, 0, 0, 0 },
-    { ".debug_frame", NULL, NULL, 0, 0, 0 },
-    { ".debug_ranges", NULL, NULL, 0, 0, 0 },
-    { ".debug_rnglists", NULL, NULL, 0, 0, 0 },
-    { ".debug_line_str", NULL, NULL, 0, 0, 0 },
-    { ".debug_sup", NULL, NULL, 0, 0, 0 },
-    { ".debug_gdb_scripts", NULL, NULL, 0, 0, 0 },
-    { ".gdb_index", NULL, NULL, 0, 0, 0 },
-    { ".gnu_debugaltlink", NULL, NULL, 0, 0, 0 },
+    DEFINE_SECTION(.debug_info),
+    DEFINE_SECTION(.debug_abbrev),
+    DEFINE_SECTION(.debug_line),
+    DEFINE_SECTION(.debug_str),
+    DEFINE_SECTION(.debug_macro),
+    DEFINE_SECTION(.debug_types),
+    DEFINE_SECTION(.debug_aranges),
+    DEFINE_SECTION(.debug_pubnames),
+    DEFINE_SECTION(.debug_pubtypes),
+    DEFINE_SECTION(.debug_gnu_pubnames),
+    DEFINE_SECTION(.debug_gnu_pubtypes),
+    DEFINE_SECTION(.debug_macinfo),
+    DEFINE_SECTION(.debug_loc),
+    DEFINE_SECTION(.debug_loclists),
+    DEFINE_SECTION(.debug_frame),
+    DEFINE_SECTION(.debug_ranges),
+    DEFINE_SECTION(.debug_rnglists),
+    DEFINE_SECTION(.debug_line_str),
+    DEFINE_SECTION(.debug_sup),
+    DEFINE_SECTION(.debug_gdb_scripts),
+    DEFINE_SECTION(.gdb_index),
+    DEFINE_SECTION(.gnu_debugaltlink),
     { NULL, NULL, NULL, 0, 0, 0 }
   };
 
@@ -1380,9 +1408,9 @@ skip_attr_no_dw_form_indirect (unsigned int cu_version, uint32_t form,
 static int
 read_debug_line (DSO *dso, dw_cu_ref cu, uint32_t off)
 {
-  unsigned char *ptr = debug_sections[DEBUG_LINE].data, *dir, *file;
+  unsigned char *ptr = debug_sections[INDEX(DEBUG_LINE)].data, *dir, *file;
   unsigned char **dirt;
-  unsigned char *endsec = ptr + debug_sections[DEBUG_LINE].size;
+  unsigned char *endsec = ptr + debug_sections[INDEX(DEBUG_LINE)].size;
   unsigned char *endcu, *endprol;
   unsigned char opcode_base;
   unsigned int culen;
@@ -1397,7 +1425,7 @@ read_debug_line (DSO *dso, dw_cu_ref cu, uint32_t off)
   int size_ndx = -1;
   uint16_t elems[256];
 
-  if (off >= debug_sections[DEBUG_LINE].size - 4)
+  if (off >= debug_sections[INDEX(DEBUG_LINE)].size - 4)
     {
       error (0, 0, "%s: .debug_line reference above end of section",
 	     dso->filename);
@@ -1551,22 +1579,22 @@ read_debug_line (DSO *dso, dw_cu_ref cu, uint32_t off)
 		    case DW_FORM_strp:
 		      {
 			unsigned int strp = do_read_32 (ptr);
-			if (strp >= debug_sections[DEBUG_STR].size)
+			if (strp >= debug_sections[INDEX(DEBUG_STR)].size)
 			  d = NULL;
 			else
 			  d = ((unsigned char *)
-			       debug_sections[DEBUG_STR].data
+			       debug_sections[INDEX(DEBUG_STR)].data
 			       + strp);
 		      }
 		      break;
 		    case DW_FORM_line_strp:
 		      {
 			unsigned int line_strp = do_read_32 (ptr);
-			if (line_strp >= debug_sections[DEBUG_LINE_STR].size)
+			if (line_strp >= debug_sections[INDEX(DEBUG_LINE_STR)].size)
 			  d = NULL;
 			else
 			  d = ((unsigned char *)
-			       debug_sections[DEBUG_LINE_STR].data
+			       debug_sections[INDEX(DEBUG_LINE_STR)].data
 			       + line_strp);
 		      }
 		      break;
@@ -1774,11 +1802,11 @@ read_debug_line (DSO *dso, dw_cu_ref cu, uint32_t off)
 		    case DW_FORM_strp:
 		      {
 			unsigned int strp = do_read_32 (ptr);
-			if (strp >= debug_sections[DEBUG_STR].size)
+			if (strp >= debug_sections[INDEX(DEBUG_STR)].size)
 			  f = NULL;
 			else
 			  {
-			    f = ((char *) debug_sections[DEBUG_STR].data
+			    f = ((char *) debug_sections[INDEX(DEBUG_STR)].data
 				 + strp);
 			    end = f + strlen (f) + 1;
 			  }
@@ -1787,11 +1815,11 @@ read_debug_line (DSO *dso, dw_cu_ref cu, uint32_t off)
 		    case DW_FORM_line_strp:
 		      {
 			unsigned int line_strp = do_read_32 (ptr);
-			if (line_strp >= debug_sections[DEBUG_LINE_STR].size)
+			if (line_strp >= debug_sections[INDEX(DEBUG_LINE_STR)].size)
 			  f = NULL;
 			else
 			  {
-			    f = ((char *) debug_sections[DEBUG_LINE_STR].data
+			    f = ((char *) debug_sections[INDEX(DEBUG_LINE_STR)].data
 				 + line_strp);
 			    end = f + strlen (f) + 1;
 			  }
@@ -1883,7 +1911,8 @@ static unsigned int
 estimate_nr_dies (void)
 {
   unsigned int average_die_size = 11;
-  unsigned int nr_dies = debug_sections[DEBUG_INFO].size / average_die_size;
+  unsigned int nr_dies =
+      debug_sections[INDEX(DEBUG_INFO)].size / average_die_size;
   return nr_dies;
 }
 
@@ -2100,11 +2129,11 @@ get_AT (dw_die_ref die, enum dwarf_attribute at, enum dwarf_form *formp)
   unsigned char *ptr;
   dw_cu_ref cu = die_cu (die);
   if (unlikely (fi_multifile) && cu->cu_kind == CU_ALT)
-    ptr = alt_data[DEBUG_INFO];
+    ptr = alt_data[INDEX(DEBUG_INFO)];
   else if (cu->cu_kind == CU_TYPES)
-    ptr = debug_sections[DEBUG_TYPES].data;
+    ptr = debug_sections[INDEX(DEBUG_INFO)].data;
   else
-    ptr = debug_sections[DEBUG_INFO].data;
+    ptr = debug_sections[INDEX(DEBUG_INFO)].data;
   ptr += die->die_offset;
   skip_leb128 (ptr);
   for (i = 0; i < t->nattr; ++i)
@@ -2193,21 +2222,21 @@ get_AT_string (dw_die_ref die, enum dwarf_attribute at)
 	unsigned int strp = read_32 (ptr);
 	if (unlikely (fi_multifile) && die_cu (die)->cu_kind == CU_ALT)
 	  {
-	    if (strp >= alt_size[DEBUG_STR])
+	    if (strp >= alt_size[INDEX(DEBUG_STR)])
 	      return NULL;
-	    return (char *) alt_data[DEBUG_STR] + strp;
+	    return (char *) alt_data[INDEX(DEBUG_STR)] + strp;
 	  }
-	if (strp >= debug_sections[DEBUG_STR].size)
+	if (strp >= debug_sections[INDEX(DEBUG_STR)].size)
 	  return NULL;
-	return (char *) debug_sections[DEBUG_STR].data + strp;
+	return (char *) debug_sections[INDEX(DEBUG_STR)].data + strp;
       }
     case DW_FORM_line_strp:
       {
 	unsigned int line_strp = read_32 (ptr);
-	if (line_strp >= debug_sections[DEBUG_LINE_STR].size)
+	if (line_strp >= debug_sections[INDEX(DEBUG_LINE_STR)].size)
 	  return NULL;
 	else
-	  return (char *) debug_sections[DEBUG_LINE_STR].data + line_strp;
+	  return (char *) debug_sections[INDEX(DEBUG_LINE_STR)].data + line_strp;
       }
     default:
       return NULL;
@@ -2682,7 +2711,7 @@ read_loclist_low_mem_phase1 (DSO *dso, dw_cu_ref cu, dw_die_ref die,
   size_t len = 0;
   int sec;
 
-  sec = cu->cu_version < 5 ? DEBUG_LOC : DEBUG_LOCLISTS;
+  sec = cu->cu_version < 5 ? INDEX(DEBUG_LOC) : INDEX(DEBUG_LOCLISTS);
   ptr = debug_sections[sec].data;
   if (ptr == NULL)
     {
@@ -2702,7 +2731,7 @@ read_loclist_low_mem_phase1 (DSO *dso, dw_cu_ref cu, dw_die_ref die,
 again:
   while (ptr < endsec)
     {
-      if (sec == DEBUG_LOC)
+      if (sec == INDEX(DEBUG_LOC))
 	{
 	  low = read_size (ptr, ptr_size);
 	  high = read_size (ptr + ptr_size, ptr_size);
@@ -2938,7 +2967,7 @@ read_loclist (DSO *dso, dw_cu_ref cu, dw_die_ref die, GElf_Addr offset)
   bool need_adjust = false;
 
   die->die_ck_state = CK_BAD;
-  sec = cu->cu_version < 5 ? DEBUG_LOC : DEBUG_LOCLISTS;
+  sec = cu->cu_version < 5 ? INDEX(DEBUG_LOC) : INDEX(DEBUG_LOCLISTS);
   ptr = debug_sections[sec].data;
   if (ptr == NULL)
     {
@@ -2958,7 +2987,7 @@ read_loclist (DSO *dso, dw_cu_ref cu, dw_die_ref die, GElf_Addr offset)
 again:
   while (ptr < endsec)
     {
-      if (cu->cu_version < 5)
+      if (cu->cu_version < 5 && !is_dwo_file)
 	{
 	  low = read_size (ptr, ptr_size);
 	  high = read_size (ptr + ptr_size, ptr_size);
@@ -3060,7 +3089,7 @@ done:
       adj.start_offset = offset;
       adj.end_offset = ptr - debug_sections[sec].data;
       adj.cu = cu;
-      if (sec == DEBUG_LOC)
+      if (sec == INDEX(DEBUG_LOC))
 	{
 	  if (loc_htab == NULL)
 	    {
@@ -3154,7 +3183,7 @@ set_die_odr_state (dw_cu_ref cu, dw_die_ref die)
       return;
     }
 
-  ptr = debug_sections[DEBUG_INFO].data + die->die_offset;
+  ptr = debug_sections[INDEX(DEBUG_INFO)].data + die->die_offset;
   skip_leb128 (ptr);
 
   t = die->die_abbrev;
@@ -3250,7 +3279,7 @@ checksum_die (DSO *dso, dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die)
       || die->die_tag == DW_TAG_imported_unit)
     die->die_ck_state = CK_BAD;
   t = die->die_abbrev;
-  ptr = debug_sections[DEBUG_INFO].data + die->die_offset;
+  ptr = debug_sections[INDEX(DEBUG_INFO)].data + die->die_offset;
   skip_leb128 (ptr);
   s = die->die_tag;
   die->u.p1.die_hash = iterative_hash_object (s, die->u.p1.die_hash);
@@ -3388,7 +3417,7 @@ checksum_die (DSO *dso, dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die)
 	    {
 	      unsigned char *new_ptr = ptr;
 	      ptr = old_ptr;
-	      if (value > cu->cu_nfiles)
+	      if (!is_dwo_file && (value > cu->cu_nfiles))
 		{
 		  error (0, 0, "%s: Invalid %s file number %d",
 			 dso->filename, get_DW_AT_str (t->attr[i].attr),
@@ -3397,7 +3426,7 @@ checksum_die (DSO *dso, dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die)
 		}
 	      if (value == 0)
 		handled = false;
-	      else if (!ignore_locus && die->die_ck_state != CK_BAD)
+	      else if (!is_dwo_file && !ignore_locus && die->die_ck_state != CK_BAD)
 		{
 		  struct dw_file *cu_file = &cu->cu_files[value - 1];
 		  size_t file_len = strlen (cu_file->file);
@@ -3651,11 +3680,11 @@ checksum_die (DSO *dso, dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die)
 	      && die->die_ck_state != CK_BAD)
 	    {
 	      value = read_32 (ptr);
-	      if (value >= debug_sections[DEBUG_STR].size)
+	      if (value >= debug_sections[INDEX(DEBUG_STR)].size)
 		die->die_ck_state = CK_BAD;
 	      else
 		{
-		  unsigned char *p = debug_sections[DEBUG_STR].data + value;
+		  unsigned char *p = debug_sections[INDEX(DEBUG_STR)].data + value;
 		  unsigned int l = strlen ((char *) p) + 1;
 		  s = t->attr[i].attr;
 		  die->u.p1.die_hash
@@ -3983,7 +4012,7 @@ checksum_ref_die (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die,
 	}
   if (i == -1U)
     {
-      ptr = debug_sections[DEBUG_INFO].data + die->die_offset;
+      ptr = debug_sections[INDEX(DEBUG_INFO)].data + die->die_offset;
       skip_leb128 (ptr);
       for (i = 0; i < t->nattr; ++i)
 	{
@@ -4360,9 +4389,9 @@ expand_child (dw_die_ref top_die, bool checksum)
   unsigned int tick = checksum ? top_die->u.p1.die_enter + 1 : 0;
 
   if (unlikely (cu->cu_kind == CU_TYPES))
-    base = debug_sections[DEBUG_TYPES].data;
+    base = debug_sections[INDEX(DEBUG_TYPES)].data;
   else
-    base = debug_sections[DEBUG_INFO].data;
+    base = debug_sections[INDEX(DEBUG_INFO)].data;
   ptr = base + top_die->die_offset;
   if (likely (checksum))
     ptr += top_die->die_size;
@@ -4554,20 +4583,20 @@ die_eq_1 (dw_cu_ref cu1, dw_cu_ref cu2,
   t2 = die2->die_abbrev;
   if (likely (!fi_multifile))
     {
-      ptr1 = debug_sections[DEBUG_INFO].data + die1->die_offset;
-      ptr2 = debug_sections[DEBUG_INFO].data + die2->die_offset;
+      ptr1 = debug_sections[INDEX(DEBUG_INFO)].data + die1->die_offset;
+      ptr2 = debug_sections[INDEX(DEBUG_INFO)].data + die2->die_offset;
     }
   else
     {
       if (cu1->cu_kind == CU_ALT)
-	ptr1 = alt_data[DEBUG_INFO];
+	ptr1 = alt_data[INDEX(DEBUG_INFO)];
       else
-	ptr1 = debug_sections[DEBUG_INFO].data;
+	ptr1 = debug_sections[INDEX(DEBUG_INFO)].data;
       ptr1 += die1->die_offset;
       if (cu2->cu_kind == CU_ALT)
-	ptr2 = alt_data[DEBUG_INFO];
+	ptr2 = alt_data[INDEX(DEBUG_INFO)];
       else
-	ptr2 = debug_sections[DEBUG_INFO].data;
+	ptr2 = debug_sections[INDEX(DEBUG_INFO)].data;
       ptr2 += die2->die_offset;
     }
   skip_leb128 (ptr1);
@@ -4911,20 +4940,20 @@ die_eq_1 (dw_cu_ref cu1, dw_cu_ref cu2,
 	      if (fi_multifile)
 		{
 		  if (strcmp ((char *) (cu1->cu_kind == CU_ALT
-					? alt_data[DEBUG_STR]
-					: debug_sections[DEBUG_STR].data)
+					? alt_data[INDEX(DEBUG_STR)]
+					: debug_sections[INDEX(DEBUG_STR)].data)
 			      + value1,
 			      (char *) (cu2->cu_kind == CU_ALT
-					? alt_data[DEBUG_STR]
-					: debug_sections[DEBUG_STR].data)
+					? alt_data[INDEX(DEBUG_STR)]
+					: debug_sections[INDEX(DEBUG_STR)].data)
 			      + value2) != 0)
 		    FAIL;
 		  i++;
 		  j++;
 		  continue;
 		}
-	      if (strcmp ((char *) debug_sections[DEBUG_STR].data + value1,
-			  (char *) debug_sections[DEBUG_STR].data + value2)
+	      if (strcmp ((char *) debug_sections[INDEX(DEBUG_STR)].data + value1,
+			  (char *) debug_sections[INDEX(DEBUG_STR)].data + value2)
 		  != 0)
 		FAIL;
 	      i++;
@@ -5532,8 +5561,8 @@ strp_eq2 (const void *p, const void *q)
   struct strp_entry *s1 = (struct strp_entry *)p;
   struct strp_entry *s2 = (struct strp_entry *)q;
 
-  return strcmp ((char *) debug_sections[DEBUG_STR].data + s1->off,
-		 (char *) debug_sections[DEBUG_STR].data + s2->off) == 0;
+  return strcmp ((char *) debug_sections[INDEX(DEBUG_STR)].data + s1->off,
+		 (char *) debug_sections[INDEX(DEBUG_STR)].data + s2->off) == 0;
 }
 
 /* Hash function in strp_htab used from finalize_strp onwards,
@@ -5569,7 +5598,7 @@ note_strp_offset (unsigned int off)
       unsigned int len;
       hashval_t hash;
 
-      p = debug_sections[DEBUG_STR].data + off;
+      p = debug_sections[INDEX(DEBUG_STR)].data + off;
       len = strlen ((char *) p);
       hash = iterative_hash (p, len, 0);
       if (alt_strp_htab)
@@ -5579,7 +5608,7 @@ note_strp_offset (unsigned int off)
 	}
       if (strp_htab == NULL)
 	{
-	  unsigned int strp_count = debug_sections[DEBUG_STR].size / 64;
+	  unsigned int strp_count = debug_sections[INDEX(DEBUG_STR)].size / 64;
 
 	  if (strp_count < 100)
 	    strp_count = 100;
@@ -5601,9 +5630,9 @@ note_strp_offset (unsigned int off)
 	}
       return;
     }
-  if (off >= debug_sections[DEBUG_STR].size || off == 0)
+  if (off >= debug_sections[INDEX(DEBUG_STR)].size || off == 0)
     return;
-  if (debug_sections[DEBUG_STR].data[off - 1] == '\0')
+  if (debug_sections[INDEX(DEBUG_STR)].data[off - 1] == '\0')
     return;
   if (strp_htab == NULL)
     {
@@ -5612,7 +5641,7 @@ note_strp_offset (unsigned int off)
       strp_htab = htab_try_create (50, strp_hash, strp_eq, NULL);
       if (strp_htab == NULL)
 	dwz_oom ();
-      max_strp_off = debug_sections[DEBUG_STR].size;
+      max_strp_off = debug_sections[INDEX(DEBUG_STR)].size;
     }
   se.off = off;
   slot = htab_find_slot_with_hash (strp_htab, &se, off, INSERT);
@@ -5623,7 +5652,7 @@ note_strp_offset (unsigned int off)
       struct strp_entry *s = pool_alloc (strp_entry, sizeof (*s));
       s->off = off;
       s->new_off = max_strp_off;
-      max_strp_off += strlen ((char *) debug_sections[DEBUG_STR].data
+      max_strp_off += strlen ((char *) debug_sections[INDEX(DEBUG_STR)].data
 			      + off) + 1;
       if (max_strp_off < s->new_off)
 	{
@@ -5651,7 +5680,7 @@ lookup_strp_offset (unsigned int off)
       unsigned int len;
       hashval_t hash;
 
-      p = debug_sections[DEBUG_STR].data + off;
+      p = debug_sections[INDEX(DEBUG_STR)].data + off;
       len = strlen ((char *) p);
       hash = iterative_hash (p, len, 0);
       if (alt_strp_htab)
@@ -5659,16 +5688,16 @@ lookup_strp_offset (unsigned int off)
 	  unsigned char *q = (unsigned char *)
 			     htab_find_with_hash (alt_strp_htab, p, hash);
 	  if (q != NULL)
-	    return q - alt_data[DEBUG_STR];
+	    return q - alt_data[INDEX(DEBUG_STR)];
 	}
       assert (strp_htab);
       p = (unsigned char *) htab_find_with_hash (strp_htab, p, hash);
       assert (p != NULL);
-      return p - debug_sections[DEBUG_STR].new_data;
+      return p - debug_sections[INDEX(DEBUG_STR)].new_data;
     }
-  if (off >= debug_sections[DEBUG_STR].size || off == 0)
+  if (off >= debug_sections[INDEX(DEBUG_STR)].size || off == 0)
     return off + multi_str_off;
-  if (debug_sections[DEBUG_STR].data[off - 1] == '\0')
+  if (debug_sections[INDEX(DEBUG_STR)].data[off - 1] == '\0')
     return off + multi_str_off;
   se.off = off;
   s = (struct strp_entry *) htab_find_with_hash (strp_htab, &se, off);
@@ -5692,7 +5721,7 @@ note_strp_offset2 (unsigned int off)
 
       if (alt_strp_htab)
 	{
-	  p = debug_sections[DEBUG_STR].data + off;
+	  p = debug_sections[INDEX(DEBUG_STR)].data + off;
 	  len = strlen ((char *) p);
 	  hash = iterative_hash (p, len, 0);
 	  if (htab_find_with_hash (alt_strp_htab, p, hash))
@@ -5700,9 +5729,9 @@ note_strp_offset2 (unsigned int off)
 	}
       return DW_FORM_strp;
     }
-  if (off >= debug_sections[DEBUG_STR].size)
+  if (off >= debug_sections[INDEX(DEBUG_STR)].size)
     return DW_FORM_strp;
-  p = debug_sections[DEBUG_STR].data + off;
+  p = debug_sections[INDEX(DEBUG_STR)].data + off;
   q = (unsigned char *) strchr ((char *) p, '\0');
   hash = iterative_hash (p, q - p, 0);
   se.off = off;
@@ -5734,8 +5763,8 @@ strrevcmp (const void *p, const void *q)
   unsigned int len1 = s1->new_off & ~1U;
   unsigned int len2 = s2->new_off & ~1U;
   unsigned int len;
-  unsigned char *p1 = debug_sections[DEBUG_STR].data + s1->off;
-  unsigned char *p2 = debug_sections[DEBUG_STR].data + s2->off;
+  unsigned char *p1 = debug_sections[INDEX(DEBUG_STR)].data + s1->off;
+  unsigned char *p2 = debug_sections[INDEX(DEBUG_STR)].data + s2->off;
 
   if (p1[len1])
     len1++;
@@ -5779,8 +5808,8 @@ finalize_strp (bool build_tail_offset_list)
 
   if (strp_htab == NULL)
     {
-      debug_sections[DEBUG_STR].new_data = NULL;
-      debug_sections[DEBUG_STR].new_size = 0;
+      debug_sections[INDEX(DEBUG_STR)].new_data = NULL;
+      debug_sections[INDEX(DEBUG_STR)].new_size = 0;
       return NULL;
     }
   count = htab_elements (strp_htab);
@@ -5790,7 +5819,7 @@ finalize_strp (bool build_tail_offset_list)
   htab_traverse (strp_htab, list_strp_entries, (void *) &end);
   for (i = 0; i < count; i++)
     {
-      unsigned int len = strlen ((char *) debug_sections[DEBUG_STR].data
+      unsigned int len = strlen ((char *) debug_sections[INDEX(DEBUG_STR)].data
 				 + arr[i]->off);
       arr[i]->new_off = (len & ~1U) | (arr[i]->new_off & 1);
     }
@@ -5810,7 +5839,7 @@ finalize_strp (bool build_tail_offset_list)
 	unsigned int len1, len2, lastlen, j;
 	unsigned char *p1, *p2;
 	len1 = arr[i]->new_off & ~1U;
-	p1 = debug_sections[DEBUG_STR].data + arr[i]->off;
+	p1 = debug_sections[INDEX(DEBUG_STR)].data + arr[i]->off;
 	if (p1[len1])
 	  len1++;
 	lastlen = len1;
@@ -5819,7 +5848,7 @@ finalize_strp (bool build_tail_offset_list)
 	for (j = i + 1; j < count; j++)
 	  {
 	    len2 = arr[j]->new_off & ~1U;
-	    p2 = debug_sections[DEBUG_STR].data + arr[j]->off;
+	    p2 = debug_sections[INDEX(DEBUG_STR)].data + arr[j]->off;
 	    if (p2[len2])
 	      len2++;
 	    if (len2 >= lastlen)
@@ -5832,10 +5861,10 @@ finalize_strp (bool build_tail_offset_list)
 	  }
 	i = j - 1;
       }
-  debug_sections[DEBUG_STR].new_data = malloc (strp_index);
-  if (debug_sections[DEBUG_STR].new_data == NULL)
+  debug_sections[INDEX(DEBUG_STR)].new_data = malloc (strp_index);
+  if (debug_sections[INDEX(DEBUG_STR)].new_data == NULL)
     dwz_oom ();
-  debug_sections[DEBUG_STR].new_size = strp_index;
+  debug_sections[INDEX(DEBUG_STR)].new_size = strp_index;
   strp_htab = htab_try_create (new_count < 32 ? 32 : new_count,
 			       strp_hash3, strp_eq3, NULL);
   if (strp_htab == NULL)
@@ -5848,17 +5877,17 @@ finalize_strp (bool build_tail_offset_list)
       if (tail_offset_list == MAP_FAILED)
 	dwz_oom ();
     }
-  for (i = 0, k = 0, p = debug_sections[DEBUG_STR].new_data; i < count; i++)
+  for (i = 0, k = 0, p = debug_sections[INDEX(DEBUG_STR)].new_data; i < count; i++)
     if (arr[i]->off == -1U && arr[i]->new_off == -1U)
       continue;
     else
       {
-	unsigned int len = strlen ((char *) debug_sections[DEBUG_STR].data
+	unsigned int len = strlen ((char *) debug_sections[INDEX(DEBUG_STR)].data
 				   + arr[i]->off) + 1;
 	unsigned int j;
 	void **slot;
 
-	memcpy (p, debug_sections[DEBUG_STR].data + arr[i]->off, len);
+	memcpy (p, debug_sections[INDEX(DEBUG_STR)].data + arr[i]->off, len);
 	slot = htab_find_slot_with_hash (strp_htab, p,
 					 iterative_hash (p, len - 1, 0),
 					 INSERT);
@@ -5886,7 +5915,7 @@ finalize_strp (bool build_tail_offset_list)
 	p += len;
 	i = j - 1;
       }
-  assert (p == debug_sections[DEBUG_STR].new_data + strp_index);
+  assert (p == debug_sections[INDEX(DEBUG_STR)].new_data + strp_index);
   if (tail_offset_list != NULL)
     {
       tail_offset_list[k++] = 0;
@@ -5934,9 +5963,9 @@ mark_refs (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die, int mode)
   if (i == -1U)
     {
       if (unlikely (cu->cu_kind == CU_TYPES))
-	ptr = debug_sections[DEBUG_TYPES].data;
+	ptr = debug_sections[INDEX(DEBUG_TYPES)].data;
       else
-	ptr = debug_sections[DEBUG_INFO].data;
+	ptr = debug_sections[INDEX(DEBUG_INFO)].data;
       ptr += die->die_offset;
       skip_leb128 (ptr);
       for (i = 0; i < t->nattr; ++i)
@@ -6281,7 +6310,7 @@ try_debug_info (DSO *dso)
   struct abbrev_tag tag, *t;
   unsigned int ndies;
   unsigned ret = 1;
-  int kind = DEBUG_INFO;
+  int kind = INDEX(DEBUG_INFO);
   bool low_mem_die_limit_hit = false;
 
   if (unlikely (progress_p))
@@ -6302,7 +6331,7 @@ try_debug_info (DSO *dso)
       int cu_version;
 
       /* Note header is one bigger with DWARF version 5.  */
-      if (ptr + (kind == DEBUG_TYPES ? 23 : 11) > endsec)
+      if (ptr + (kind == INDEX(DEBUG_TYPES) ? 23 : 11) > endsec)
 	{
 	  error (0, 0, "%s: %s CU header too small", dso->filename,
 		 debug_sections[kind].name);
@@ -6326,7 +6355,7 @@ try_debug_info (DSO *dso)
 	}
 
       cu_version = read_16 (ptr);
-      if (kind == DEBUG_TYPES && (cu_version < 2 || cu_version > 4))
+      if (kind == INDEX(DEBUG_TYPES) && (cu_version < 2 || cu_version > 4))
 	{
 	  error (0, 0, "%s: DWARF version %d in .debug_types unhandled",
 		 dso->filename, cu_version);
@@ -6349,9 +6378,9 @@ try_debug_info (DSO *dso)
       else
 	{
 	  value = read_32 (ptr);
-	  if (value >= debug_sections[DEBUG_ABBREV].size)
+	  if (value >= debug_sections[INDEX(DEBUG_ABBREV)].size)
 	    {
-	      if (debug_sections[DEBUG_ABBREV].data == NULL)
+	      if (debug_sections[INDEX(DEBUG_ABBREV)].data == NULL)
 		error (0, 0, "%s: .debug_abbrev not present", dso->filename);
 	      else
 		error (0, 0, "%s: DWARF CU abbrev offset too large",
@@ -6387,9 +6416,9 @@ try_debug_info (DSO *dso)
 	      goto fail;
 	    }
 	  value = read_32 (ptr);
-	  if (value >= debug_sections[DEBUG_ABBREV].size)
+	  if (value >= debug_sections[INDEX(DEBUG_ABBREV)].size)
 	    {
-	      if (debug_sections[DEBUG_ABBREV].data == NULL)
+	      if (debug_sections[INDEX(DEBUG_ABBREV)].data == NULL)
 		error (0, 0, "%s: .debug_abbrev not present", dso->filename);
 	      else
 		error (0, 0, "%s: DWARF CU abbrev offset too large",
@@ -6403,7 +6432,8 @@ try_debug_info (DSO *dso)
 	  if (abbrev)
 	    htab_delete (abbrev);
 	  abbrev
-	    = read_abbrev (dso, debug_sections[DEBUG_ABBREV].data + value);
+	    = read_abbrev (dso,
+                           debug_sections[INDEX(DEBUG_ABBREV)].data + value);
 	  if (abbrev == NULL)
 	    {
 	      error (0, 0, "%s: Couldn't read abbrev at offset 0x%x",
@@ -6499,12 +6529,12 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
   struct abbrev_tag tag, *t;
   unsigned int cu_chunk = 0;
   dw_cu_ref cu_tail = NULL, cu_collapse = NULL;
-  unsigned int cu_kind = rd_multifile ? CU_ALT
-			 : kind == DEBUG_TYPES ? CU_TYPES : CU_NORMAL;
+  unsigned int cu_kind =
+      rd_multifile ? CU_ALT : kind == INDEX(DEBUG_TYPES) ? CU_TYPES : CU_NORMAL;
   void *to_free = NULL;
   int ret = 1;
   unsigned int ndies;
-  bool low_mem_phase1 = low_mem && kind == DEBUG_INFO;
+  bool low_mem_phase1 = low_mem && kind == INDEX(DEBUG_INFO);
   struct dw_cu cu_buf;
   struct dw_die die_buf;
   bool lang_p = odr || uni_lang_p;
@@ -6514,7 +6544,7 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
     odr_phase = 1;
 
   unsigned int estimated_nr_dies = estimate_nr_dies ();
-  if (kind == DEBUG_INFO
+  if ((kind == INDEX(DEBUG_INFO))
       && multifile_mode == 0
       && die_count_method == estimate)
     {
@@ -6536,11 +6566,11 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
     {
       report_progress ();
       fprintf (stderr, "read_debug_info %s%s\n",
-	       kind == DEBUG_INFO ? ".debug_info" : ".debug_types",
-	       low_mem && kind == DEBUG_INFO ? " (low-mem)" : "");
+	       kind == INDEX(DEBUG_INFO) ? ".debug_info" : ".debug_types",
+	       low_mem && kind == INDEX(DEBUG_INFO) ? " (low-mem)" : "");
     }
 
-  if (likely (!fi_multifile && kind != DEBUG_TYPES))
+  if (likely (!fi_multifile && kind != INDEX(DEBUG_TYPES)))
     {
       dup_htab = htab_try_create (100000, die_hash, die_eq, NULL);
       if (dup_htab == NULL)
@@ -6573,7 +6603,7 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       unsigned int type_offset = 0;
 
       /* Note header is one bigger with DWARF version 5.  */
-      if (ptr + (kind == DEBUG_TYPES ? 23 : 11) > endsec)
+      if (ptr + (kind == INDEX(DEBUG_TYPES) ? 23 : 11) > endsec)
 	{
 	  error (0, 0, "%s: %s CU header too small", dso->filename,
 		 debug_sections[kind].name);
@@ -6597,7 +6627,7 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	}
 
       cu_version = read_16 (ptr);
-      if (kind == DEBUG_TYPES && (cu_version < 2 || cu_version > 4))
+      if (kind == INDEX(DEBUG_TYPES) && (cu_version < 2 || cu_version > 4))
 	{
 	  error (0, 0, "%s: DWARF version %d in .debug_types unhandled",
 		 dso->filename, cu_version);
@@ -6623,9 +6653,9 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       else
 	{
 	  value = read_32 (ptr);
-	  if (value >= debug_sections[DEBUG_ABBREV].size)
+	  if (value >= debug_sections[INDEX(DEBUG_ABBREV)].size)
 	    {
-	      if (debug_sections[DEBUG_ABBREV].data == NULL)
+	      if (debug_sections[INDEX(DEBUG_ABBREV)].data == NULL)
 		error (0, 0, "%s: .debug_abbrev not present", dso->filename);
 	      else
 		error (0, 0, "%s: DWARF CU abbrev offset too large",
@@ -6661,9 +6691,9 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	      goto fail;
 	    }
 	  value = read_32 (ptr);
-	  if (value >= debug_sections[DEBUG_ABBREV].size)
+	  if (value >= debug_sections[INDEX(DEBUG_ABBREV)].size)
 	    {
-	      if (debug_sections[DEBUG_ABBREV].data == NULL)
+	      if (debug_sections[INDEX(DEBUG_ABBREV)].data == NULL)
 		error (0, 0, "%s: .debug_abbrev not present", dso->filename);
 	      else
 		error (0, 0, "%s: DWARF CU abbrev offset too large",
@@ -6734,7 +6764,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	    {
 	      *slot = (void *) &meta_abbrev_fallback;
 	      abbrev
-		= read_abbrev (dso, debug_sections[DEBUG_ABBREV].data + value);
+		= read_abbrev (dso,
+			       debug_sections[INDEX(DEBUG_ABBREV)].data + value);
 	      if (abbrev == NULL)
 		goto fail;
 	      mp = (struct meta_abbrev_entry *)
@@ -6749,7 +6780,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	  if (abbrev)
 	    htab_delete (abbrev);
 	  abbrev
-	    = read_abbrev (dso, debug_sections[DEBUG_ABBREV].data + value);
+	    = read_abbrev (dso,
+			   debug_sections[INDEX(DEBUG_ABBREV)].data + value);
 	  if (abbrev == NULL)
 	    {
 	      error (0, 0, "%s: Couldn't read abbrev at offset 0x%x",
@@ -6760,7 +6792,7 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	}
       last_abbrev_offset = value;
 
-      if (unlikely (kind == DEBUG_TYPES))
+      if (unlikely (kind == INDEX(DEBUG_TYPES)))
 	{
 	  ptr += 8;
 	  type_offset = read_32 (ptr);
@@ -6826,7 +6858,7 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	      goto fail;
 	    }
 	  if (likely (!op_multifile && !rd_multifile && !fi_multifile)
-	      && likely (kind == DEBUG_INFO))
+	      && likely (kind == INDEX(DEBUG_INFO)))
 	    {
 	      if (ndies == max_die_limit)
 		{
@@ -7112,7 +7144,7 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	    {
 	      if (low_mem_phase1)
 		continue;
-	      if (off_htab != NULL && kind == DEBUG_INFO)
+	      if (off_htab != NULL && kind == INDEX(DEBUG_INFO))
 		{
 		  void **slot
 		    = htab_find_slot_with_hash (off_htab, die, off_hash (die),
@@ -7159,6 +7191,32 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	  cu->cu_die->die_remove = 1;
 	  continue;
 	}
+      char *dwo_name = get_AT_string (cu->cu_die, DW_AT_GNU_dwo_name);
+      if (!dwo_name)
+        dwo_name = get_AT_string (cu->cu_die, DW_AT_dwo_name);
+      if (dwo_name)
+	{
+	  int len1 = strlen(dwo_name);
+	  int len2 = strlen(dso->filename);
+          if (len2 > 4 && strncmp(dso->filename + len2 - 4, ".dwo", 4))
+	    {
+              int len = 0;
+              char *ptr;
+	      int len3 = (cu->cu_comp_dir != NULL && *dwo_name != '/')
+                         ? (strlen(cu->cu_comp_dir) + 1) : 0;
+              len = len1 + 1 + len3;
+              dwofile = malloc (len);
+              ptr = dwofile;
+              if (len3 != 0)
+                {
+                  memcpy(dwofile, cu->cu_comp_dir, strlen(cu->cu_comp_dir));
+                  dwofile[len3-1] = '/';
+                  ptr += len3;
+                }
+              memcpy(ptr, dwo_name, len1 + 1);
+	    }
+        }
+
       enum dwarf_form form;
       debug_line_off
 	= get_AT_int (cu->cu_die, DW_AT_stmt_list, &present, &form);
@@ -7187,7 +7245,7 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	}
 
       if (likely (!op_multifile && !rd_multifile && !fi_multifile)
-	  && likely (kind == DEBUG_INFO))
+	  && likely (kind == INDEX(DEBUG_INFO)))
 	{
 	  if (checksum_die (dso, cu, NULL, cu->cu_die))
 	    goto fail;
@@ -7213,7 +7271,7 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	  if (find_dups (cu->cu_die))
 	    goto fail;
 	}
-      if (unlikely (kind == DEBUG_TYPES))
+      if (unlikely (kind == INDEX(DEBUG_TYPES)))
 	{
 	  dw_die_ref ref = off_htab_lookup (cu, cu->cu_offset + type_offset);
 	  if (ref == NULL)
@@ -7262,7 +7320,7 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
   else if (abbrev)
     htab_delete (abbrev);
 
-  if (unlikely (kind == DEBUG_TYPES))
+  if (unlikely (kind == INDEX(DEBUG_TYPES)))
     return 0;
 
   if (unlikely (rd_multifile || fi_multifile))
@@ -7327,7 +7385,7 @@ fail:
     }
   else if (abbrev)
     htab_delete (abbrev);
-  if (dup_htab && kind == DEBUG_INFO)
+  if (dup_htab && kind == INDEX(DEBUG_INFO))
     {
       htab_delete (dup_htab);
       dup_htab = NULL;
@@ -7517,9 +7575,9 @@ mark_singletons (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die,
     goto handle_children;
 
   if (unlikely (cu->cu_kind == CU_TYPES))
-    ptr = debug_sections[DEBUG_TYPES].data;
+    ptr = debug_sections[INDEX(DEBUG_TYPES)].data;
   else
-    ptr = debug_sections[DEBUG_INFO].data;
+    ptr = debug_sections[INDEX(DEBUG_INFO)].data;
   ptr += die->die_offset;
   skip_leb128 (ptr);
   for (i = 0; i < t->nattr; ++i)
@@ -9956,8 +10014,8 @@ macro_eq (const void *p, const void *q)
 	  strp2 = read_32 (p2);
 	  if (op_multifile)
 	    {
-	      if (strcmp ((char *) debug_sections[DEBUG_STR].data + strp1,
-			  (char *) debug_sections[DEBUG_STR].data + strp2)
+	      if (strcmp ((char *) debug_sections[INDEX(DEBUG_STR)].data + strp1,
+			  (char *) debug_sections[INDEX(DEBUG_STR)].data + strp2)
 		  != 0)
 		return 0;
 	    }
@@ -9978,7 +10036,7 @@ macro_hash2 (const void *p)
 {
   struct macro_entry *m = (struct macro_entry *)p;
 
-  return m->ptr - debug_sections[DEBUG_MACRO].data;
+  return m->ptr - debug_sections[INDEX(DEBUG_MACRO)].data;
 }
 
 /* Equality function in macro_htab.  */
@@ -9993,7 +10051,7 @@ macro_eq2 (const void *p, const void *q)
 /* Parse .debug_macro section, either during write_multifile
    or during fi_multifile phase.  During write_multifile it
    selects potentially shareable .debug_macro sequences and
-   writes them into debug_sections[DEBUG_MACRO].new_data
+   writes them into debug_sections[INDEX(DEBUG_MACRO)].new_data
    block it allocates.  During fi_multifile it populates
    macro_htab.  In both cases it calls note_strp_offset
    on DW_FORM_strp offsets.  */
@@ -10004,9 +10062,9 @@ read_macro (DSO *dso)
   unsigned int version, flags, op, strp;
   struct macro_entry me, *m;
 
-  ptr = debug_sections[DEBUG_MACRO].data;
-  endsec = ptr + debug_sections[DEBUG_MACRO].size;
-  debug_sections[DEBUG_MACRO].new_size = 0;
+  ptr = debug_sections[INDEX(DEBUG_MACRO)].data;
+  endsec = ptr + debug_sections[INDEX(DEBUG_MACRO)].size;
+  debug_sections[INDEX(DEBUG_MACRO)].new_size = 0;
   if (!wr_multifile)
     {
       macro_htab = htab_try_create (50, macro_hash2, macro_eq2, NULL);
@@ -10084,7 +10142,7 @@ read_macro (DSO *dso)
 		hash = iterative_hash (s, ptr - 4 - s, hash);
 	      if (can_share)
 		{
-		  unsigned char *p = debug_sections[DEBUG_STR].data + strp;
+		  unsigned char *p = debug_sections[INDEX(DEBUG_STR)].data + strp;
 		  unsigned int len = strlen ((char *) p);
 		  hash = iterative_hash (p, len, hash);
 		  s = ptr;
@@ -10109,7 +10167,7 @@ read_macro (DSO *dso)
       if (wr_multifile)
 	{
 	  if (can_share)
-	    debug_sections[DEBUG_MACRO].new_size += ptr - start;
+	    debug_sections[INDEX(DEBUG_MACRO)].new_size += ptr - start;
 	  continue;
 	}
 
@@ -10124,17 +10182,17 @@ read_macro (DSO *dso)
 	  if (m == NULL)
 	    can_share = false;
 	  else
-	    me.hash = m->ptr - alt_data[DEBUG_MACRO];
+	    me.hash = m->ptr - alt_data[INDEX(DEBUG_MACRO)];
 	}
       if (!can_share)
 	{
 	  me.len = 0;
-	  me.hash = debug_sections[DEBUG_MACRO].new_size;
-	  debug_sections[DEBUG_MACRO].new_size += ptr - start;
+	  me.hash = debug_sections[INDEX(DEBUG_MACRO)].new_size;
+	  debug_sections[INDEX(DEBUG_MACRO)].new_size += ptr - start;
 	}
       slot
 	= htab_find_slot_with_hash (macro_htab, &me,
-				    me.ptr - debug_sections[DEBUG_MACRO].data,
+				    me.ptr - debug_sections[INDEX(DEBUG_MACRO)].data,
 				    INSERT);
       if (slot == NULL)
 	dwz_oom ();
@@ -10150,12 +10208,12 @@ read_macro (DSO *dso)
   if (!wr_multifile)
     return 0;
 
-  debug_sections[DEBUG_MACRO].new_data
-    = (unsigned char *) malloc (debug_sections[DEBUG_MACRO].new_size);
-  if (debug_sections[DEBUG_MACRO].new_data == NULL)
+  debug_sections[INDEX(DEBUG_MACRO)].new_data
+    = (unsigned char *) malloc (debug_sections[INDEX(DEBUG_MACRO)].new_size);
+  if (debug_sections[INDEX(DEBUG_MACRO)].new_data == NULL)
     dwz_oom ();
-  dst = debug_sections[DEBUG_MACRO].new_data;
-  for (ptr = debug_sections[DEBUG_MACRO].data; ptr < endsec; )
+  dst = debug_sections[INDEX(DEBUG_MACRO)].new_data;
+  for (ptr = debug_sections[INDEX(DEBUG_MACRO)].data; ptr < endsec; )
     {
       unsigned char *start = ptr;
       bool can_share = true;
@@ -10236,8 +10294,8 @@ read_macro (DSO *dso)
 	  dst += ptr - start;
 	}
     }
-  assert (dst == debug_sections[DEBUG_MACRO].new_data
-		 + debug_sections[DEBUG_MACRO].new_size);
+  assert (dst == debug_sections[INDEX(DEBUG_MACRO)].new_data
+		 + debug_sections[INDEX(DEBUG_MACRO)].new_size);
 
   return 0;
 }
@@ -10293,7 +10351,7 @@ optimize_write_macro (void **slot, void *data)
    or during read_multifile.  It parses .debug_macro written
    by write_multifile, so it only contains shareable sequences.
    Find duplicate sequences, during optimize_multifile write them
-   into debug_sections[DEBUG_MACRO].new_data it allocates,
+   into debug_sections[INDEX(DEBUG_MACRO)].new_data it allocates,
    during read_multifile just populates macro_htab (soon to be
    alt_macro_htab).  */
 static void
@@ -10307,14 +10365,14 @@ handle_macro (void)
   if (macro_htab == NULL)
     dwz_oom ();
 
-  endsec = debug_sections[DEBUG_MACRO].data + debug_sections[DEBUG_MACRO].size;
+  endsec = debug_sections[INDEX(DEBUG_MACRO)].data + debug_sections[DEBUG_MACRO].size;
   if (op_multifile)
     {
-      debug_sections[DEBUG_MACRO].new_size = 0;
+      debug_sections[INDEX(DEBUG_MACRO)].new_size = 0;
       to_free = obstack_alloc (&ob, 1);
     }
 
-  for (ptr = debug_sections[DEBUG_MACRO].data; ptr < endsec; )
+  for (ptr = debug_sections[INDEX(DEBUG_MACRO)].data; ptr < endsec; )
     {
       unsigned char *start = ptr, *s = ptr, *p;
       hashval_t hash = 0;
@@ -10340,7 +10398,7 @@ handle_macro (void)
 	    case DW_MACRO_undef_strp:
 	      skip_leb128 (ptr);
 	      hash = iterative_hash (s, ptr - s, hash);
-	      p = debug_sections[DEBUG_STR].data + read_32 (ptr);
+	      p = debug_sections[INDEX(DEBUG_STR)].data + read_32 (ptr);
 	      len = strlen ((char *) p);
 	      hash = iterative_hash (p, len, hash);
 	      if (op_multifile
@@ -10370,7 +10428,7 @@ handle_macro (void)
 	  if (op_multifile && (m->hash & 1) == 0)
 	    {
 	      m->hash |= 1;
-	      debug_sections[DEBUG_MACRO].new_size += me.len;
+	      debug_sections[INDEX(DEBUG_MACRO)].new_size += me.len;
 	    }
 	}
       else if (op_multifile)
@@ -10389,15 +10447,15 @@ handle_macro (void)
 
   if (op_multifile)
     {
-      if (debug_sections[DEBUG_MACRO].new_size)
+      if (debug_sections[INDEX(DEBUG_MACRO)].new_size)
 	{
 	  unsigned char *p;
-	  debug_sections[DEBUG_MACRO].new_data
-	    = malloc (debug_sections[DEBUG_MACRO].new_size);
-	  p = debug_sections[DEBUG_MACRO].new_data;
+	  debug_sections[INDEX(DEBUG_MACRO)].new_data
+	    = malloc (debug_sections[INDEX(DEBUG_MACRO)].new_size);
+	  p = debug_sections[INDEX(DEBUG_MACRO)].new_data;
 	  htab_traverse (macro_htab, optimize_write_macro, &p);
-	  assert (p == debug_sections[DEBUG_MACRO].new_data
-		       + debug_sections[DEBUG_MACRO].new_size);
+	  assert (p == debug_sections[INDEX(DEBUG_MACRO)].new_data
+		       + debug_sections[INDEX(DEBUG_MACRO)].new_size);
 	  htab_delete (macro_htab);
 	  macro_htab = NULL;
 	}
@@ -10413,13 +10471,13 @@ write_macro (void)
   unsigned int op, strp;
   struct macro_entry me, *m;
 
-  endsec = debug_sections[DEBUG_MACRO].data + debug_sections[DEBUG_MACRO].size;
-  debug_sections[DEBUG_MACRO].new_data
-    = (unsigned char *) malloc (debug_sections[DEBUG_MACRO].new_size);
-  if (debug_sections[DEBUG_MACRO].new_data == NULL)
+  endsec = debug_sections[INDEX(DEBUG_MACRO)].data + debug_sections[DEBUG_MACRO].size;
+  debug_sections[INDEX(DEBUG_MACRO)].new_data
+    = (unsigned char *) malloc (debug_sections[INDEX(DEBUG_MACRO)].new_size);
+  if (debug_sections[INDEX(DEBUG_MACRO)].new_data == NULL)
     dwz_oom ();
-  dst = debug_sections[DEBUG_MACRO].new_data;
-  for (ptr = debug_sections[DEBUG_MACRO].data; ptr < endsec; )
+  dst = debug_sections[INDEX(DEBUG_MACRO)].new_data;
+  for (ptr = debug_sections[INDEX(DEBUG_MACRO)].data; ptr < endsec; )
     {
       unsigned char *s = ptr;
       unsigned char flags;
@@ -10427,7 +10485,7 @@ write_macro (void)
       me.ptr = ptr;
       m = (struct macro_entry *)
 	  htab_find_with_hash (macro_htab, &me,
-			       me.ptr - debug_sections[DEBUG_MACRO].data);
+			       me.ptr - debug_sections[INDEX(DEBUG_MACRO)].data);
       if (m->len)
 	{
 	  ptr += m->len;
@@ -10486,11 +10544,11 @@ write_macro (void)
 	    case DW_MACRO_import:
 	      memcpy (dst, s, ptr - 1 - s);
 	      dst += ptr - 1 - s;
-	      me.ptr = debug_sections[DEBUG_MACRO].data + read_32 (ptr);
+	      me.ptr = debug_sections[INDEX(DEBUG_MACRO)].data + read_32 (ptr);
 	      m = (struct macro_entry *)
 		  htab_find_with_hash (macro_htab, &me,
 				       me.ptr
-				       - debug_sections[DEBUG_MACRO].data);
+				       - debug_sections[INDEX(DEBUG_MACRO)].data);
 	      if (m->len)
 		*dst = DW_MACRO_import_sup;
 	      else
@@ -10506,8 +10564,8 @@ write_macro (void)
       memcpy (dst, s, ptr - s);
       dst += ptr - s;
     }
-  assert (dst == debug_sections[DEBUG_MACRO].new_data
-		 + debug_sections[DEBUG_MACRO].new_size);
+  assert (dst == debug_sections[INDEX(DEBUG_MACRO)].new_data
+		 + debug_sections[INDEX(DEBUG_MACRO)].new_size);
 }
 
 /* Compute new abbreviations for DIE (with reference DIE REF).
@@ -10583,8 +10641,8 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
     {
       unsigned char *base
 	= cu->cu_kind == CU_TYPES
-	  ? debug_sections[DEBUG_TYPES].data
-	  : debug_sections[DEBUG_INFO].data;
+	  ? debug_sections[INDEX(DEBUG_TYPES)].data
+	  : debug_sections[INDEX(DEBUG_INFO)].data;
       unsigned char *ptr = base + ref->die_offset;
       struct abbrev_tag *reft = ref->die_abbrev;
 
@@ -10720,7 +10778,7 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
 			     get_DW_AT_str (reft->attr[i].attr));
 		      return 1;
 		    }
-		  me.ptr = debug_sections[DEBUG_MACRO].data + value;
+		  me.ptr = debug_sections[INDEX(DEBUG_MACRO)].data + value;
 		  m = (struct macro_entry *)
 		    htab_find_with_hash (macro_htab, &me, value);
 		  if (m->len)
@@ -11837,9 +11895,9 @@ compute_abbrevs (DSO *dso)
 	    owner = owner->u1.cu_new_abbrev_owner;
 	  }
       }
-  debug_sections[DEBUG_INFO].new_size = total_size;
-  debug_sections[DEBUG_ABBREV].new_size = abbrev_size;
-  debug_sections[DEBUG_TYPES].new_size = types_size;
+  debug_sections[INDEX(DEBUG_INFO)].new_size = total_size;
+  debug_sections[INDEX(DEBUG_ABBREV)].new_size = abbrev_size;
+  debug_sections[INDEX(DEBUG_TYPES)].new_size = types_size;
   return 0;
 }
 
@@ -11864,7 +11922,7 @@ static void
 write_abbrev (void)
 {
   dw_cu_ref cu;
-  unsigned char *abbrev = malloc (debug_sections[DEBUG_ABBREV].new_size);
+  unsigned char *abbrev = malloc (debug_sections[INDEX(DEBUG_ABBREV)].new_size);
   unsigned char *ptr = abbrev;
 
   if (unlikely (progress_p))
@@ -11876,7 +11934,7 @@ write_abbrev (void)
   if (abbrev == NULL)
     dwz_oom ();
 
-  debug_sections[DEBUG_ABBREV].new_data = abbrev;
+  debug_sections[INDEX(DEBUG_ABBREV)].new_data = abbrev;
   for (cu = first_cu; cu; cu = cu->cu_next)
     {
       struct abbrev_tag **arr;
@@ -11916,7 +11974,7 @@ write_abbrev (void)
 	  cu->cu_new_abbrev = NULL;
 	}
     }
-  assert (abbrev + debug_sections[DEBUG_ABBREV].new_size == ptr);
+  assert (abbrev + debug_sections[INDEX(DEBUG_ABBREV)].new_size == ptr);
 }
 
 /* Adjust DWARF expression starting at PTR, LEN bytes long, referenced by
@@ -12245,8 +12303,8 @@ write_die (unsigned char *ptr, dw_cu_ref cu, dw_die_ref die,
     {
       unsigned char *base
 	= cu->cu_kind == CU_TYPES
-	  ? debug_sections[DEBUG_TYPES].data
-	  : debug_sections[DEBUG_INFO].data;
+	  ? debug_sections[INDEX(DEBUG_TYPES)].data
+	  : debug_sections[INDEX(DEBUG_INFO)].data;
       unsigned char *inptr = base + ref->die_offset;
       struct abbrev_tag *reft = ref->die_abbrev;
       unsigned int i, j;
@@ -12318,7 +12376,7 @@ write_die (unsigned char *ptr, dw_cu_ref cu, dw_die_ref die,
 	      memcpy (ptr, orig_ptr, inptr - orig_ptr);
 	      ptr += inptr - orig_ptr;
 	      value = read_32 (inptr);
-	      me.ptr = debug_sections[DEBUG_MACRO].data + value;
+	      me.ptr = debug_sections[INDEX(DEBUG_MACRO)].data + value;
 	      m = (struct macro_entry *)
 		  htab_find_with_hash (macro_htab, &me, value);
 	      write_32 (ptr, m->hash);
@@ -12799,7 +12857,7 @@ static void
 write_info (unsigned int *die_count)
 {
   dw_cu_ref cu, cu_next;
-  unsigned char *info = malloc (debug_sections[DEBUG_INFO].new_size);
+  unsigned char *info = malloc (debug_sections[INDEX(DEBUG_INFO)].new_size);
   unsigned char *ptr = info;
 
   if (unlikely (progress_p))
@@ -12812,7 +12870,7 @@ write_info (unsigned int *die_count)
     dwz_oom ();
   if (die_count)
     *die_count = 0;
-  debug_sections[DEBUG_INFO].new_data = info;
+  debug_sections[INDEX(DEBUG_INFO)].new_data = info;
   cu = first_cu;
   if (unlikely (fi_multifile))
     while (cu
@@ -12821,7 +12879,7 @@ write_info (unsigned int *die_count)
       cu = cu->cu_next;
   for (; cu; cu = cu_next)
     {
-      unsigned long next_off = debug_sections[DEBUG_INFO].new_size;
+      unsigned long next_off = debug_sections[INDEX(DEBUG_INFO)].new_size;
       /* Ignore .debug_types CUs.  */
       if (cu->cu_kind == CU_TYPES)
 	break;
@@ -12866,7 +12924,7 @@ write_info (unsigned int *die_count)
       write_32 (ptr, 0);
       write_8 (ptr, ptr_size);
     }
-  assert (info + debug_sections[DEBUG_INFO].new_size == ptr);
+  assert (info + debug_sections[INDEX(DEBUG_INFO)].new_size == ptr);
 }
 
 /* Adjust .debug_loc range determined by *SLOT, called through
@@ -12881,8 +12939,8 @@ adjust_loclist (void **slot, void *data)
 
   (void)data;
 
-  ptr = debug_sections[DEBUG_LOC].new_data + adj->start_offset;
-  endsec = ptr + debug_sections[DEBUG_LOC].size;
+  ptr = debug_sections[INDEX(DEBUG_LOC)].new_data + adj->start_offset;
+  endsec = ptr + debug_sections[INDEX(DEBUG_LOC)].size;
   while (ptr < endsec)
     {
       low = read_size (ptr, ptr_size);
@@ -12917,8 +12975,8 @@ adjust_loclists (void **slot, void *data)
 
   (void)data;
 
-  ptr = debug_sections[DEBUG_LOCLISTS].new_data + adj->start_offset;
-  endsec = ptr + debug_sections[DEBUG_LOCLISTS].size;
+  ptr = debug_sections[INDEX(DEBUG_LOCLISTS)].new_data + adj->start_offset;
+  endsec = ptr + debug_sections[INDEX(DEBUG_LOCLISTS)].size;
 
 again:
   while (ptr < endsec)
@@ -13002,11 +13060,11 @@ write_loc (void)
   unsigned char *loc;
   if (loc_htab == NULL)
     return;
-  loc = malloc (debug_sections[DEBUG_LOC].size);
+  loc = malloc (debug_sections[INDEX(DEBUG_LOC)].size);
   if (loc == NULL)
     dwz_oom ();
-  memcpy (loc, debug_sections[DEBUG_LOC].data, debug_sections[DEBUG_LOC].size);
-  debug_sections[DEBUG_LOC].new_data = loc;
+  memcpy (loc, debug_sections[INDEX(DEBUG_LOC)].data, debug_sections[DEBUG_LOC].size);
+  debug_sections[INDEX(DEBUG_LOC)].new_data = loc;
   htab_traverse (loc_htab, adjust_loclist, NULL);
 }
 
@@ -13018,12 +13076,12 @@ write_loclists (void)
   unsigned char *loc;
   if (loclists_htab == NULL)
     return;
-  loc = malloc (debug_sections[DEBUG_LOCLISTS].size);
+  loc = malloc (debug_sections[INDEX(DEBUG_LOCLISTS)].size);
   if (loc == NULL)
     dwz_oom ();
-  memcpy (loc, debug_sections[DEBUG_LOCLISTS].data,
-	  debug_sections[DEBUG_LOCLISTS].size);
-  debug_sections[DEBUG_LOCLISTS].new_data = loc;
+  memcpy (loc, debug_sections[INDEX(DEBUG_LOCLISTS)].data,
+	  debug_sections[INDEX(DEBUG_LOCLISTS)].size);
+  debug_sections[INDEX(DEBUG_LOCLISTS)].new_data = loc;
   htab_traverse (loclists_htab, adjust_loclists, NULL);
 }
 
@@ -13035,16 +13093,16 @@ write_types (void)
   unsigned char *types, *ptr, *inptr;
   dw_die_ref ref;
 
-  if (debug_sections[DEBUG_TYPES].data == NULL)
+  if (debug_sections[INDEX(DEBUG_TYPES)].data == NULL)
     return;
-  types = malloc (debug_sections[DEBUG_TYPES].new_size);
+  types = malloc (debug_sections[INDEX(DEBUG_TYPES)].new_size);
   if (types == NULL)
     dwz_oom ();
-  debug_sections[DEBUG_TYPES].new_data = types;
+  debug_sections[INDEX(DEBUG_TYPES)].new_data = types;
   ptr = types;
   for (cu = first_cu; cu; cu = cu->cu_next)
     {
-      unsigned long next_off = debug_sections[DEBUG_TYPES].new_size;
+      unsigned long next_off = debug_sections[INDEX(DEBUG_TYPES)].new_size;
       /* Ignore .debug_info CUs.  */
       if (cu->cu_kind != CU_TYPES)
 	continue;
@@ -13058,7 +13116,7 @@ write_types (void)
       write_16 (ptr, cu->cu_version);
       write_32 (ptr, cu->u2.cu_new_abbrev_offset);
       write_8 (ptr, ptr_size);
-      inptr = debug_sections[DEBUG_TYPES].data + cu->cu_offset + 19;
+      inptr = debug_sections[INDEX(DEBUG_TYPES)].data + cu->cu_offset + 19;
       memcpy (ptr, inptr - 8, 8);
       ptr += 8;
       ref = off_htab_lookup (cu, cu->cu_offset + read_32 (inptr));
@@ -13069,28 +13127,28 @@ write_types (void)
       if (unlikely (low_mem))
 	collapse_children (cu, cu->cu_die);
     }
-  assert (types + debug_sections[DEBUG_TYPES].new_size == ptr);
+  assert (types + debug_sections[INDEX(DEBUG_TYPES)].new_size == ptr);
 }
 
 /* Construct new .debug_aranges section in malloced memory,
-   store it to debug_sections[DEBUG_ARANGES].new_data.  */
+   store it to debug_sections[INDEX(DEBUG_ARANGES)].new_data.  */
 static int
 write_aranges (DSO *dso)
 {
   dw_cu_ref cu, cufirst = NULL, cucur;
   unsigned char *aranges, *ptr, *end;
 
-  if (debug_sections[DEBUG_ARANGES].data == NULL)
+  if (debug_sections[INDEX(DEBUG_ARANGES)].data == NULL)
     return 0;
 
-  aranges = malloc (debug_sections[DEBUG_ARANGES].size);
+  aranges = malloc (debug_sections[INDEX(DEBUG_ARANGES)].size);
   if (aranges == NULL)
     dwz_oom ();
-  memcpy (aranges, debug_sections[DEBUG_ARANGES].data,
-	  debug_sections[DEBUG_ARANGES].size);
-  debug_sections[DEBUG_ARANGES].new_data = aranges;
+  memcpy (aranges, debug_sections[INDEX(DEBUG_ARANGES)].data,
+	  debug_sections[INDEX(DEBUG_ARANGES)].size);
+  debug_sections[INDEX(DEBUG_ARANGES)].new_data = aranges;
   ptr = aranges;
-  end = aranges + debug_sections[DEBUG_ARANGES].size;
+  end = aranges + debug_sections[INDEX(DEBUG_ARANGES)].size;
   for (cu = first_cu; cu; cu = cu->cu_next)
     if (cu->cu_kind != CU_PU)
       break;
@@ -13196,12 +13254,12 @@ write_gdb_index (void)
   unsigned int *tuindices = NULL, tuidx = 0, *cumap = NULL, i, j, k;
   bool fail = false;
 
-  debug_sections[GDB_INDEX].new_size = 0;
+  debug_sections[INDEX(GDB_INDEX)].new_size = 0;
   if (likely (!op_multifile)
-      && (debug_sections[GDB_INDEX].data == NULL
-	  || debug_sections[GDB_INDEX].size < 0x18))
+      && (debug_sections[INDEX(GDB_INDEX)].data == NULL
+	  || debug_sections[INDEX(GDB_INDEX)].size < 0x18))
     return;
-  inptr = (unsigned char *) debug_sections[GDB_INDEX].data;
+  inptr = (unsigned char *) debug_sections[INDEX(GDB_INDEX)].data;
   if (unlikely (op_multifile))
     ver = multi_gdb_index_ver;
   else
@@ -13229,12 +13287,12 @@ write_gdb_index (void)
   if (unlikely (op_multifile))
     {
       assert (ncus == 0 && ntus == 0);
-      debug_sections[GDB_INDEX].new_size
+      debug_sections[INDEX(GDB_INDEX)].new_size
 	= 0x18 + npus * 16 + 16;
-      gdb_index = malloc (debug_sections[GDB_INDEX].new_size);
+      gdb_index = malloc (debug_sections[INDEX(GDB_INDEX)].new_size);
       if (gdb_index == NULL)
 	dwz_oom ();
-      debug_sections[GDB_INDEX].new_data = gdb_index;
+      debug_sections[INDEX(GDB_INDEX)].new_data = gdb_index;
       /* Write new header.  */
       buf_write_le32 (gdb_index + 0x00, ver);
       buf_write_le32 (gdb_index + 0x04, 0x18);
@@ -13246,7 +13304,7 @@ write_gdb_index (void)
       /* Write new CU list.  */
       for (cu = first_cu; cu; cu = cu->cu_next)
 	{
-	  unsigned long next_off = debug_sections[DEBUG_INFO].new_size;
+	  unsigned long next_off = debug_sections[INDEX(DEBUG_INFO)].new_size;
 	  if (cu->cu_next)
 	    next_off = cu->cu_next->cu_new_offset;
 	  buf_write_le64 (ptr, cu->cu_new_offset);
@@ -13271,7 +13329,7 @@ write_gdb_index (void)
       || constoff < symboloff
       || ((constoff - symboloff) & (constoff - symboloff - 1)) != 0
       || ((constoff - symboloff) & 7) != 0
-      || debug_sections[GDB_INDEX].size < constoff)
+      || debug_sections[INDEX(GDB_INDEX)].size < constoff)
     return;
   inptr += 0x18;
   if (ndelcus)
@@ -13328,12 +13386,12 @@ write_gdb_index (void)
       && multi_gdb_index_ver < ver)
     multi_gdb_index_ver = ver;
 
-  debug_sections[GDB_INDEX].new_size
-    = debug_sections[GDB_INDEX].size + npus * 16 - ndelcus * 16;
-  gdb_index = malloc (debug_sections[GDB_INDEX].new_size);
+  debug_sections[INDEX(GDB_INDEX)].new_size
+    = debug_sections[INDEX(GDB_INDEX)].size + npus * 16 - ndelcus * 16;
+  gdb_index = malloc (debug_sections[INDEX(GDB_INDEX)].new_size);
   if (gdb_index == NULL)
     dwz_oom ();
-  debug_sections[GDB_INDEX].new_data = gdb_index;
+  debug_sections[INDEX(GDB_INDEX)].new_data = gdb_index;
   /* Write new header.  */
   buf_write_le32 (gdb_index + 0x00, ver);
   buf_write_le32 (gdb_index + 0x04, culistoff);
@@ -13345,7 +13403,7 @@ write_gdb_index (void)
   /* Write new CU list.  */
   for (cu = first_cu; cu; cu = cu_next)
     {
-      unsigned long next_off = debug_sections[DEBUG_INFO].new_size;
+      unsigned long next_off = debug_sections[INDEX(DEBUG_INFO)].new_size;
       if (cu->cu_kind == CU_TYPES)
 	break;
       cu_next = cu->cu_next;
@@ -13372,7 +13430,7 @@ write_gdb_index (void)
       dw_die_ref ref;
       assert (cu->cu_kind == CU_TYPES);
       buf_write_le64 (ptr + tuoff, cu->cu_new_offset);
-      p = debug_sections[DEBUG_TYPES].data + cu->cu_offset + 19;
+      p = debug_sections[INDEX(DEBUG_TYPES)].data + cu->cu_offset + 19;
       ref = off_htab_lookup (cu, cu->cu_offset + read_32 (p));
       assert (ref && ref->die_dup == NULL);
       buf_write_le64 (ptr + tuoff + 8, ref->u.p2.die_new_offset);
@@ -13402,7 +13460,7 @@ write_gdb_index (void)
   memcpy (ptr, inptr, constoff - symboloff);
   /* Clear the const pool initially.  */
   memset (ptr + (constoff - symboloff), '\0',
-	  debug_sections[GDB_INDEX].size - constoff);
+	  debug_sections[INDEX(GDB_INDEX)].size - constoff);
   ptr = ptr + (constoff - symboloff);
   end = inptr + (constoff - symboloff);
   /* Finally copy over const objects into the const pool, strings as is,
@@ -13415,12 +13473,12 @@ write_gdb_index (void)
       inptr += 8;
       if (name == 0 && cuvec == 0)
 	continue;
-      if (name > debug_sections[GDB_INDEX].size - constoff - 1
-	  || cuvec > debug_sections[GDB_INDEX].size - constoff - 4)
+      if (name > debug_sections[INDEX(GDB_INDEX)].size - constoff - 1
+	  || cuvec > debug_sections[INDEX(GDB_INDEX)].size - constoff - 4)
 	{
 	fail:
 	  free (gdb_index);
-	  debug_sections[GDB_INDEX].new_size = 0;
+	  debug_sections[INDEX(GDB_INDEX)].new_size = 0;
 	  return;
 	}
       if (ptr[name] == '\0')
@@ -13429,7 +13487,7 @@ write_gdb_index (void)
 	  while (*strend != '\0')
 	    {
 	      if (strend + 1
-		  == end + (debug_sections[GDB_INDEX].size - constoff))
+		  == end + (debug_sections[INDEX(GDB_INDEX)].size - constoff))
 		goto fail;
 	      strend++;
 	    }
@@ -13439,7 +13497,7 @@ write_gdb_index (void)
 	{
 	  unsigned int count = buf_read_ule32 (end + cuvec);
 	  if (count * 4
-	      > debug_sections[GDB_INDEX].size - constoff - cuvec - 4)
+	      > debug_sections[INDEX(GDB_INDEX)].size - constoff - cuvec - 4)
 	    goto fail;
 	  buf_write_le32 (ptr + cuvec, count);
 	  for (i = 0; i < count; i++)
@@ -13471,9 +13529,9 @@ write_gdb_index (void)
     obstack_free (&ob2, (void *) tuindices);
   if (fail)
     {
-      free (debug_sections[GDB_INDEX].new_data);
-      debug_sections[GDB_INDEX].new_data = NULL;
-      debug_sections[GDB_INDEX].new_size = 0;
+      free (debug_sections[INDEX(GDB_INDEX)].new_data);
+      debug_sections[INDEX(GDB_INDEX)].new_data = NULL;
+      debug_sections[INDEX(GDB_INDEX)].new_size = 0;
     }
 }
 
@@ -13601,7 +13659,7 @@ read_dwarf (DSO *dso, bool quieter, unsigned int *die_count)
       return 1;
     }
 
-  if (debug_sections[DEBUG_INFO].data == NULL
+  if (debug_sections[INDEX(DEBUG_INFO)].data == NULL
       && !rd_multifile)
     {
       if (!quieter)
@@ -13610,14 +13668,14 @@ read_dwarf (DSO *dso, bool quieter, unsigned int *die_count)
       return 3;
     }
 
-  if (debug_sections[DEBUG_SUP].data != NULL && !(dwarf_5 && rd_multifile))
+  if (debug_sections[INDEX(DEBUG_SUP)].data != NULL && !(dwarf_5 && rd_multifile))
     {
       error (0, 0, "%s: .debug_sup section already present",
 	     dso->filename);
       return 1;
     }
 
-  if (debug_sections[GNU_DEBUGALTLINK].data != NULL)
+  if (debug_sections[INDEX(GNU_DEBUGALTLINK)].data != NULL)
     {
       error (0, 0, "%s: .gnu_debugaltlink section already present",
 	     dso->filename);
@@ -13625,7 +13683,7 @@ read_dwarf (DSO *dso, bool quieter, unsigned int *die_count)
     }
 
   int res;
-  res = read_debug_info (dso, DEBUG_INFO, die_count);
+  res = read_debug_info (dso, INDEX(DEBUG_INFO), die_count);
   if (res == 0 && stats_p)
     print_parse_stats ();
   return res;
@@ -13661,7 +13719,7 @@ fdopen_dso (int fd, const char *name)
     }
 
   if (ehdr.e_type != ET_DYN && ehdr.e_type != ET_EXEC
-      && (!rd_multifile || ehdr.e_type != ET_REL))
+      && !is_dwo_file && (!rd_multifile || ehdr.e_type != ET_REL))
     {
       error (0, 0, "\"%s\" is not a shared library", name);
       goto error_out;
@@ -14166,7 +14224,7 @@ write_dso (DSO *dso, const char *file, struct stat *st, bool save_to_temp)
 	 already has the correct ELF class.  */
       || memcpy (e_ident, dso->ehdr.e_ident, EI_NIDENT) == NULL
       || gelf_update_ehdr (elf, &ehdr) == 0
-      || gelf_newphdr (elf, ehdr.e_phnum) == 0)
+      || ((ehdr.e_phnum > 0) && (gelf_newphdr (elf, ehdr.e_phnum) == 0)))
     {
       error (0, 0, "Could not create new ELF headers");
       unlink (file);
@@ -14429,7 +14487,7 @@ propagate_multifile_refs_backward (dw_cu_ref cu, dw_die_ref top_die,
   if (die->die_offset == -1U)
     return;
 
-  ptr = debug_sections[DEBUG_INFO].data + die->die_offset;
+  ptr = debug_sections[INDEX(DEBUG_INFO)].data + die->die_offset;
   skip_leb128 (ptr);
   for (i = 0; i < t->nattr; ++i)
     {
@@ -14591,14 +14649,14 @@ write_multifile_strp (void)
   htab_traverse (strp_htab, list_strp_entries, (void *) &end);
   assert (arr + count == end);
   qsort (arr, count, sizeof (struct strp_entry *), strp_off_cmp);
-  buf_alloc = max_strp_off - debug_sections[DEBUG_STR].size;
+  buf_alloc = max_strp_off - debug_sections[INDEX(DEBUG_STR)].size;
   if (buf_alloc > 131072)
     buf_alloc = 131072;
   buf = (unsigned char *) obstack_alloc (&ob, buf_alloc);
   buf_size = 0;
   for (i = 0; i < count; i++)
     {
-      unsigned char *p = debug_sections[DEBUG_STR].data + arr[i]->off;
+      unsigned char *p = debug_sections[INDEX(DEBUG_STR)].data + arr[i]->off;
       unsigned int len = strlen ((char *) p) + 1;
       if (buf_alloc - buf_size < len)
 	{
@@ -14675,7 +14733,7 @@ line_id_cmp (const void *p, const void *q)
    into the temporary .debug_line file (if line_htab is non-NULL, fill
    its directory and file table from it, otherwise emit an entry
    with no directories or files), if op_multifile, store the entry
-   into debug_sections[DEBUG_LINE].new_data which it allocates.  */
+   into debug_sections[INDEX(DEBUG_LINE)].new_data which it allocates.  */
 static int
 write_multifile_line (void)
 {
@@ -14795,11 +14853,11 @@ write_multifile_line (void)
   len = header_len + filetbllen + dirtbllen;
   if (unlikely (op_multifile))
     {
-      debug_sections[DEBUG_LINE].new_size = len;
-      debug_sections[DEBUG_LINE].new_data = malloc (len);
-      if (debug_sections[DEBUG_LINE].new_data == NULL)
+      debug_sections[INDEX(DEBUG_LINE)].new_size = len;
+      debug_sections[INDEX(DEBUG_LINE)].new_data = malloc (len);
+      if (debug_sections[INDEX(DEBUG_LINE)].new_data == NULL)
 	dwz_oom ();
-      line = debug_sections[DEBUG_LINE].new_data;
+      line = debug_sections[INDEX(DEBUG_LINE)].new_data;
     }
   else
     {
@@ -15076,20 +15134,20 @@ write_multifile_1 (DSO *dso, struct file_result *res)
 	fprintf (stderr, "Write-multifile %s\n", dso->filename);
       if (compute_abbrevs (NULL))
 	ret = 1;
-      else if (debug_sections[DEBUG_MACRO].data && read_macro (dso))
+      else if (debug_sections[INDEX(DEBUG_MACRO)].data && read_macro (dso))
 	ret = 1;
       else if ((unsigned int) (multi_info_off
-			       + debug_sections[DEBUG_INFO].new_size)
+			       + debug_sections[INDEX(DEBUG_INFO)].new_size)
 	       < multi_info_off
 	       || (unsigned int) (multi_abbrev_off
-				  + debug_sections[DEBUG_ABBREV].new_size)
+				  + debug_sections[INDEX(DEBUG_ABBREV)].new_size)
 		  < multi_abbrev_off
 	       || (unsigned int) (multi_str_off
 				  + (max_strp_off ? max_strp_off
-				     : debug_sections[DEBUG_ABBREV].size))
+				     : debug_sections[INDEX(DEBUG_ABBREV)].size))
 		  < multi_str_off
 	       || (unsigned int) (multi_macro_off
-				  + debug_sections[DEBUG_MACRO].new_size)
+				  + debug_sections[INDEX(DEBUG_MACRO)].new_size)
 		  < multi_macro_off)
 	{
 	  error (0, 0, "Multifile temporary files too large");
@@ -15105,20 +15163,20 @@ write_multifile_1 (DSO *dso, struct file_result *res)
 	     files.  */
 	  mfile = multifile;
 	  multifile = NULL;
-	  if (write (multi_abbrev_fd, debug_sections[DEBUG_ABBREV].new_data,
-		     debug_sections[DEBUG_ABBREV].new_size)
-	      != (ssize_t) debug_sections[DEBUG_ABBREV].new_size
-	      || write (multi_info_fd, debug_sections[DEBUG_INFO].new_data,
-			debug_sections[DEBUG_INFO].new_size)
-		 != (ssize_t) debug_sections[DEBUG_INFO].new_size
-	      || write (multi_str_fd, debug_sections[DEBUG_STR].data,
-			debug_sections[DEBUG_STR].size)
-		 != (ssize_t) debug_sections[DEBUG_STR].size
-	      || (debug_sections[DEBUG_MACRO].new_data
+	  if (write (multi_abbrev_fd, debug_sections[INDEX(DEBUG_ABBREV)].new_data,
+		     debug_sections[INDEX(DEBUG_ABBREV)].new_size)
+	      != (ssize_t) debug_sections[INDEX(DEBUG_ABBREV)].new_size
+	      || write (multi_info_fd, debug_sections[INDEX(DEBUG_INFO)].new_data,
+			debug_sections[INDEX(DEBUG_INFO)].new_size)
+		 != (ssize_t) debug_sections[INDEX(DEBUG_INFO)].new_size
+	      || write (multi_str_fd, debug_sections[INDEX(DEBUG_STR)].data,
+			debug_sections[INDEX(DEBUG_STR)].size)
+		 != (ssize_t) debug_sections[INDEX(DEBUG_STR)].size
+	      || (debug_sections[INDEX(DEBUG_MACRO)].new_data
 		  && write (multi_macro_fd,
-			    debug_sections[DEBUG_MACRO].new_data,
-			    debug_sections[DEBUG_MACRO].new_size)
-		     != (ssize_t) debug_sections[DEBUG_MACRO].new_size)
+			    debug_sections[INDEX(DEBUG_MACRO)].new_data,
+			    debug_sections[INDEX(DEBUG_MACRO)].new_size)
+		     != (ssize_t) debug_sections[INDEX(DEBUG_MACRO)].new_size)
 	      || (strp_htab != NULL && write_multifile_strp ())
 	      || write_multifile_line ())
 	    {
@@ -15127,11 +15185,11 @@ write_multifile_1 (DSO *dso, struct file_result *res)
 	    }
 	  else
 	    {
-	      multi_info_off += debug_sections[DEBUG_INFO].new_size;
-	      multi_abbrev_off += debug_sections[DEBUG_ABBREV].new_size;
+	      multi_info_off += debug_sections[INDEX(DEBUG_INFO)].new_size;
+	      multi_abbrev_off += debug_sections[INDEX(DEBUG_ABBREV)].new_size;
 	      multi_str_off += max_strp_off ? max_strp_off
-			       : debug_sections[DEBUG_STR].size;
-	      multi_macro_off += debug_sections[DEBUG_MACRO].new_size;
+			       : debug_sections[INDEX(DEBUG_STR)].size;
+	      multi_macro_off += debug_sections[INDEX(DEBUG_MACRO)].new_size;
 	      multifile = mfile;
 	    }
 	}
@@ -15292,6 +15350,7 @@ dwz (const char *file, const char *outfile, struct file_result *res)
   unsigned int i;
   struct stat st;
 
+  dwofile = NULL;
   if (res->res == -1)
     return 1;
 
@@ -15351,7 +15410,7 @@ dwz (const char *file, const char *outfile, struct file_result *res)
 	       || (unlikely (fi_multifile)
 		   && (remove_empty_pus ()
 		       || read_macro (dso)))
-	       || read_debug_info (dso, DEBUG_TYPES, NULL)
+	       || read_debug_info (dso, INDEX(DEBUG_TYPES), NULL)
 #if DEVEL
 	       || clear_p2_field ()
 #endif
@@ -15362,30 +15421,30 @@ dwz (const char *file, const char *outfile, struct file_result *res)
 	  ret = 1;
 	}
       else if (!(ignore_size || force_p)
-	       && ((debug_sections[DEBUG_INFO].new_size
-		    + debug_sections[DEBUG_ABBREV].new_size
-		    + debug_sections[DEBUG_STR].new_size
-		    + debug_sections[DEBUG_MACRO].new_size
-		    + debug_sections[DEBUG_TYPES].new_size)
-		   >= (debug_sections[DEBUG_INFO].size
-		       + debug_sections[DEBUG_ABBREV].size
-		       + debug_sections[DEBUG_STR].size
-		       + debug_sections[DEBUG_MACRO].size
-		       + debug_sections[DEBUG_TYPES].size)))
+	       && ((debug_sections[INDEX(DEBUG_INFO)].new_size
+		    + debug_sections[INDEX(DEBUG_ABBREV)].new_size
+		    + debug_sections[INDEX(DEBUG_STR)].new_size
+		    + debug_sections[INDEX(DEBUG_MACRO)].new_size
+		    + debug_sections[INDEX(DEBUG_TYPES)].new_size)
+		   >= (debug_sections[INDEX(DEBUG_INFO)].size
+		       + debug_sections[INDEX(DEBUG_ABBREV)].size
+		       + debug_sections[INDEX(DEBUG_STR)].size
+		       + debug_sections[INDEX(DEBUG_MACRO)].size
+		       + debug_sections[INDEX(DEBUG_TYPES)].size)))
 	{
 	  if (!quiet || outfile != NULL)
 	    error (0, 0, "%s: DWARF compression not beneficial "
 			 "- old size %ld new size %ld", dso->filename,
-		   (unsigned long) (debug_sections[DEBUG_INFO].size
-				    + debug_sections[DEBUG_ABBREV].size
-				    + debug_sections[DEBUG_STR].size
-				    + debug_sections[DEBUG_MACRO].size
-				    + debug_sections[DEBUG_TYPES].size),
-		   (unsigned long) (debug_sections[DEBUG_INFO].new_size
-				    + debug_sections[DEBUG_ABBREV].new_size
-				    + debug_sections[DEBUG_STR].new_size
-				    + debug_sections[DEBUG_MACRO].new_size
-				    + debug_sections[DEBUG_TYPES].new_size));
+		   (unsigned long) (debug_sections[INDEX(DEBUG_INFO)].size
+				    + debug_sections[INDEX(DEBUG_ABBREV)].size
+				    + debug_sections[INDEX(DEBUG_STR)].size
+				    + debug_sections[INDEX(DEBUG_MACRO)].size
+				    + debug_sections[INDEX(DEBUG_TYPES)].size),
+		   (unsigned long) (debug_sections[INDEX(DEBUG_INFO)].new_size
+				    + debug_sections[INDEX(DEBUG_ABBREV)].new_size
+				    + debug_sections[INDEX(DEBUG_STR)].new_size
+				    + debug_sections[INDEX(DEBUG_MACRO)].new_size
+				    + debug_sections[INDEX(DEBUG_TYPES)].new_size));
 
 	  if (multifile && !fi_multifile && !low_mem)
 	    write_multifile (dso, res);
@@ -15467,7 +15526,7 @@ dwz (const char *file, const char *outfile, struct file_result *res)
 		    }
 		}
 	      len = strlen (name) + 1;
-	      sec_kind = dwarf_5 ? DEBUG_SUP : GNU_DEBUGALTLINK;
+	      sec_kind = dwarf_5 ? INDEX(DEBUG_SUP) : INDEX(GNU_DEBUGALTLINK);
 	      debug_sections[sec_kind].new_size
 		= len + 0x14 + (dwarf_5 ? 4 : 0);
 	      debug_sections[sec_kind].new_data
@@ -15517,14 +15576,14 @@ dwz (const char *file, const char *outfile, struct file_result *res)
 	  write_gdb_index ();
 	  /* These sections are optional and it is unclear
 	     how to adjust them.  Just remove them.  */
-	  debug_sections[DEBUG_PUBNAMES].new_data = NULL;
-	  debug_sections[DEBUG_PUBNAMES].new_size = 0;
-	  debug_sections[DEBUG_PUBTYPES].new_data = NULL;
-	  debug_sections[DEBUG_PUBTYPES].new_size = 0;
-	  debug_sections[DEBUG_GNU_PUBNAMES].new_data = NULL;
-	  debug_sections[DEBUG_GNU_PUBNAMES].new_size = 0;
-	  debug_sections[DEBUG_GNU_PUBTYPES].new_data = NULL;
-	  debug_sections[DEBUG_GNU_PUBTYPES].new_size = 0;
+	  debug_sections[INDEX(DEBUG_PUBNAMES)].new_data = NULL;
+	  debug_sections[INDEX(DEBUG_PUBNAMES)].new_size = 0;
+	  debug_sections[INDEX(DEBUG_PUBTYPES)].new_data = NULL;
+	  debug_sections[INDEX(DEBUG_PUBTYPES)].new_size = 0;
+	  debug_sections[INDEX(DEBUG_GNU_PUBNAMES)].new_data = NULL;
+	  debug_sections[INDEX(DEBUG_GNU_PUBNAMES)].new_size = 0;
+	  debug_sections[INDEX(DEBUG_GNU_PUBTYPES)].new_data = NULL;
+	  debug_sections[INDEX(DEBUG_GNU_PUBTYPES)].new_size = 0;
 
 	  if (multifile && !fi_multifile && !low_mem)
 	    write_multifile (dso, res);
@@ -15565,6 +15624,13 @@ dwz (const char *file, const char *outfile, struct file_result *res)
       ret = (outfile != NULL) ? 1 : 0;
       res->res = -1;
     }
+  if (dwofile) {
+    is_dwo_file = true;
+    ret = dwz (dwofile, NULL, res);
+    free(dwofile);
+    is_dwo_file = false;
+  }
+
   return ret;
 }
 
@@ -15633,35 +15699,35 @@ optimize_multifile (unsigned int *die_count)
       shstrtab = shstrtab_gnu;
       shstrtab_len = sizeof shstrtab_gnu;
     }
-  debug_sections[DEBUG_INFO].size = multi_info_off;
-  debug_sections[DEBUG_INFO].data
+  debug_sections[INDEX(DEBUG_INFO)].size = multi_info_off;
+  debug_sections[INDEX(DEBUG_INFO)].data
     = (multi_info_off
        ? mmap (NULL, multi_info_off, PROT_READ, MAP_PRIVATE, multi_info_fd, 0)
        : NULL);
-  debug_sections[DEBUG_ABBREV].size = multi_abbrev_off;
-  debug_sections[DEBUG_ABBREV].data
+  debug_sections[INDEX(DEBUG_ABBREV)].size = multi_abbrev_off;
+  debug_sections[INDEX(DEBUG_ABBREV)].data
     = (multi_abbrev_off
        ? mmap (NULL, multi_abbrev_off, PROT_READ, MAP_PRIVATE,
 	       multi_abbrev_fd, 0)
        : NULL);
-  debug_sections[DEBUG_LINE].size = multi_line_off;
-  debug_sections[DEBUG_LINE].data
+  debug_sections[INDEX(DEBUG_LINE)].size = multi_line_off;
+  debug_sections[INDEX(DEBUG_LINE)].data
     = mmap (NULL, multi_line_off, PROT_READ, MAP_PRIVATE, multi_line_fd, 0);
-  debug_sections[DEBUG_STR].size = multi_str_off;
-  debug_sections[DEBUG_STR].data
+  debug_sections[INDEX(DEBUG_STR)].size = multi_str_off;
+  debug_sections[INDEX(DEBUG_STR)].data
     = multi_str_off
       ? mmap (NULL, multi_str_off, PROT_READ, MAP_PRIVATE, multi_str_fd, 0)
       : NULL;
-  debug_sections[DEBUG_MACRO].size = multi_macro_off;
-  debug_sections[DEBUG_MACRO].data
+  debug_sections[INDEX(DEBUG_MACRO)].size = multi_macro_off;
+  debug_sections[INDEX(DEBUG_MACRO)].data
     = multi_macro_off
       ? mmap (NULL, multi_macro_off, PROT_READ, MAP_PRIVATE, multi_macro_fd, 0)
       : NULL;
-  if (debug_sections[DEBUG_INFO].data == MAP_FAILED
-      || debug_sections[DEBUG_ABBREV].data == MAP_FAILED
-      || debug_sections[DEBUG_LINE].data == MAP_FAILED
-      || debug_sections[DEBUG_STR].data == MAP_FAILED
-      || debug_sections[DEBUG_MACRO].data == MAP_FAILED)
+  if (debug_sections[INDEX(DEBUG_INFO)].data == MAP_FAILED
+      || debug_sections[INDEX(DEBUG_ABBREV)].data == MAP_FAILED
+      || debug_sections[INDEX(DEBUG_LINE)].data == MAP_FAILED
+      || debug_sections[INDEX(DEBUG_STR)].data == MAP_FAILED
+      || debug_sections[INDEX(DEBUG_MACRO)].data == MAP_FAILED)
     {
       error (0, 0, "Error mmapping multi-file temporary files");
     fail:
@@ -15673,23 +15739,23 @@ optimize_multifile (unsigned int *die_count)
 	  unlink (multifile);
 	  close (vfd);
 	}
-      if (debug_sections[DEBUG_INFO].data != MAP_FAILED)
-	munmap (debug_sections[DEBUG_INFO].data,
-		debug_sections[DEBUG_INFO].size);
-      if (debug_sections[DEBUG_ABBREV].data != MAP_FAILED)
-	munmap (debug_sections[DEBUG_ABBREV].data,
-		debug_sections[DEBUG_ABBREV].size);
-      if (debug_sections[DEBUG_LINE].data != MAP_FAILED)
-	munmap (debug_sections[DEBUG_LINE].data,
-		debug_sections[DEBUG_LINE].size);
-      if (debug_sections[DEBUG_STR].data != MAP_FAILED
-	  && debug_sections[DEBUG_STR].data != NULL)
-	munmap (debug_sections[DEBUG_STR].data,
-		debug_sections[DEBUG_STR].size);
-      if (debug_sections[DEBUG_MACRO].data != MAP_FAILED
-	  && debug_sections[DEBUG_MACRO].data != NULL)
-	munmap (debug_sections[DEBUG_MACRO].data,
-		debug_sections[DEBUG_MACRO].size);
+      if (debug_sections[INDEX(DEBUG_INFO)].data != MAP_FAILED)
+	munmap (debug_sections[INDEX(DEBUG_INFO)].data,
+		debug_sections[INDEX(DEBUG_INFO)].size);
+      if (debug_sections[INDEX(DEBUG_ABBREV)].data != MAP_FAILED)
+	munmap (debug_sections[INDEX(DEBUG_ABBREV)].data,
+		debug_sections[INDEX(DEBUG_ABBREV)].size);
+      if (debug_sections[INDEX(DEBUG_LINE)].data != MAP_FAILED)
+	munmap (debug_sections[INDEX(DEBUG_LINE)].data,
+		debug_sections[INDEX(DEBUG_LINE)].size);
+      if (debug_sections[INDEX(DEBUG_STR)].data != MAP_FAILED
+	  && debug_sections[INDEX(DEBUG_STR)].data != NULL)
+	munmap (debug_sections[INDEX(DEBUG_STR)].data,
+		debug_sections[INDEX(DEBUG_STR)].size);
+      if (debug_sections[INDEX(DEBUG_MACRO)].data != MAP_FAILED
+	  && debug_sections[INDEX(DEBUG_MACRO)].data != NULL)
+	munmap (debug_sections[INDEX(DEBUG_MACRO)].data,
+		debug_sections[INDEX(DEBUG_MACRO)].size);
       return -1;
     }
 
@@ -15725,7 +15791,7 @@ optimize_multifile (unsigned int *die_count)
       obstack_init (&ob);
       obstack_init (&ob2);
 
-      if (read_debug_info (dso, DEBUG_INFO, NULL)
+      if (read_debug_info (dso, INDEX(DEBUG_INFO), NULL)
 	  || partition_dups ())
 	goto fail;
 
@@ -15739,7 +15805,7 @@ optimize_multifile (unsigned int *die_count)
 
       *cup = NULL;
 
-      strp_count = debug_sections[DEBUG_STR].size / 64;
+      strp_count = debug_sections[INDEX(DEBUG_STR)].size / 64;
       if (strp_count < 64)
 	strp_count = 64;
       strp_htab = htab_try_create (strp_count,
@@ -15747,8 +15813,8 @@ optimize_multifile (unsigned int *die_count)
       if (strp_htab == NULL)
 	dwz_oom ();
 
-      for (p = debug_sections[DEBUG_STR].data;
-	   p < debug_sections[DEBUG_STR].data + debug_sections[DEBUG_STR].size;
+      for (p = debug_sections[INDEX(DEBUG_STR)].data;
+	   p < debug_sections[INDEX(DEBUG_STR)].data + debug_sections[DEBUG_STR].size;
 	   p = q + 1)
 	{
 	  void **slot;
@@ -15757,7 +15823,7 @@ optimize_multifile (unsigned int *die_count)
 
 	  q = (unsigned char *) strchr ((char *) p, '\0');
 	  hash = iterative_hash (p, q - p, 0);
-	  se.off = p - debug_sections[DEBUG_STR].data;
+	  se.off = p - debug_sections[INDEX(DEBUG_STR)].data;
 	  se.new_off = hash & ~1U;
 	  slot = htab_find_slot_with_hash (strp_htab, &se, se.new_off, INSERT);
 	  if (slot == NULL)
@@ -15788,7 +15854,7 @@ optimize_multifile (unsigned int *die_count)
       else
 	strp_tail_off_list = finalize_strp (true);
 
-      if (debug_sections[DEBUG_MACRO].data)
+      if (debug_sections[INDEX(DEBUG_MACRO)].data)
 	handle_macro ();
     }
 
@@ -15800,12 +15866,12 @@ optimize_multifile (unsigned int *die_count)
   supp = NULL;
   if (dwarf_5)
     {
-      debug_sections[DEBUG_SUP].new_size = 0x14 + 5;
-      debug_sections[DEBUG_SUP].new_data
-	= malloc (debug_sections[DEBUG_SUP].new_size);
-      if (debug_sections[DEBUG_SUP].new_data == NULL)
+      debug_sections[INDEX(DEBUG_SUP)].new_size = 0x14 + 5;
+      debug_sections[INDEX(DEBUG_SUP)].new_data
+	= malloc (debug_sections[INDEX(DEBUG_SUP)].new_size);
+      if (debug_sections[INDEX(DEBUG_SUP)].new_data == NULL)
 	dwz_oom ();
-      supp = debug_sections[DEBUG_SUP].new_data;
+      supp = debug_sections[INDEX(DEBUG_SUP)].new_data;
       write_16 (supp, 5);
       write_8 (supp, 1);
       write_8 (supp, 0);
@@ -15930,7 +15996,7 @@ optimize_multifile (unsigned int *die_count)
 	    break;
 	  }
       shdr.sh_size = debug_sections[i].new_size;
-      if (i == DEBUG_STR)
+      if ((int)i == INDEX(DEBUG_STR))
 	{
 	  shdr.sh_flags = SHF_MERGE | SHF_STRINGS;
 	  shdr.sh_entsize = 1;
@@ -15984,18 +16050,21 @@ optimize_multifile (unsigned int *die_count)
 
   if (dwarf_5)
     {
-      free (debug_sections[DEBUG_SUP].new_data);
-      debug_sections[DEBUG_SUP].new_data = NULL;
-    }
-  munmap (debug_sections[DEBUG_INFO].data, debug_sections[DEBUG_INFO].size);
-  munmap (debug_sections[DEBUG_ABBREV].data,
-	  debug_sections[DEBUG_ABBREV].size);
-  munmap (debug_sections[DEBUG_LINE].data, debug_sections[DEBUG_LINE].size);
-  if (debug_sections[DEBUG_STR].data)
-    munmap (debug_sections[DEBUG_STR].data, debug_sections[DEBUG_STR].size);
-  if (debug_sections[DEBUG_MACRO].data)
-    munmap (debug_sections[DEBUG_MACRO].data,
-	    debug_sections[DEBUG_MACRO].size);
+      free (debug_sections[INDEX(DEBUG_SUP)].new_data);
+      debug_sections[INDEX(DEBUG_SUP)].new_data = NULL;
+    }
+  munmap (debug_sections[INDEX(DEBUG_INFO)].data,
+	  debug_sections[INDEX(DEBUG_INFO)].size);
+  munmap (debug_sections[INDEX(DEBUG_ABBREV)].data,
+	  debug_sections[INDEX(DEBUG_ABBREV)].size);
+  munmap (debug_sections[INDEX(DEBUG_LINE)].data,
+	  debug_sections[DEBUG_LINE].size);
+  if (debug_sections[INDEX(DEBUG_STR)].data)
+    munmap (debug_sections[INDEX(DEBUG_STR)].data,
+	    debug_sections[DEBUG_STR].size);
+  if (debug_sections[INDEX(DEBUG_MACRO)].data)
+    munmap (debug_sections[INDEX(DEBUG_MACRO)].data,
+	    debug_sections[INDEX(DEBUG_MACRO)].size);
 
   for (i = 0; debug_sections[i].name; ++i)
     {
@@ -16058,10 +16127,10 @@ read_multifile (int fd, unsigned int die_count)
       if (read_dwarf (dso, false, &die_count))
 	goto fail;
 
-      if (debug_sections[DEBUG_STR].size)
+      if (debug_sections[INDEX(DEBUG_STR)].size)
 	{
 	  unsigned char *p, *q;
-	  unsigned int strp_count = debug_sections[DEBUG_STR].size / 64;
+	  unsigned int strp_count = debug_sections[INDEX(DEBUG_STR)].size / 64;
 	  void **slot;
 	  unsigned int *pi;
 
@@ -16070,9 +16139,9 @@ read_multifile (int fd, unsigned int die_count)
 	  strp_htab = htab_try_create (strp_count, strp_hash3, strp_eq3, NULL);
 	  if (strp_htab == NULL)
 	    dwz_oom ();
-	  for (p = debug_sections[DEBUG_STR].data;
-	       p < debug_sections[DEBUG_STR].data
-		   + debug_sections[DEBUG_STR].size; p = q)
+	  for (p = debug_sections[INDEX(DEBUG_STR)].data;
+	       p < debug_sections[INDEX(DEBUG_STR)].data
+		   + debug_sections[INDEX(DEBUG_STR)].size; p = q)
 	    {
 	      q = (unsigned char *) strchr ((char *) p, '\0') + 1;
 	      slot = htab_find_slot_with_hash (strp_htab, p,
@@ -16087,7 +16156,7 @@ read_multifile (int fd, unsigned int die_count)
 	    {
 	      for (pi = strp_tail_off_list; *pi; pi++)
 		{
-		  p = debug_sections[DEBUG_STR].data + *pi;
+		  p = debug_sections[INDEX(DEBUG_STR)].data + *pi;
 		  q = (unsigned char *) strchr ((char *) p, '\0');
 		  slot = htab_find_slot_with_hash (strp_htab, p,
 						   iterative_hash (p, q - p,
@@ -16103,7 +16172,7 @@ read_multifile (int fd, unsigned int die_count)
 	    }
 	}
 
-      if (debug_sections[DEBUG_MACRO].data)
+      if (debug_sections[INDEX(DEBUG_MACRO)].data)
 	handle_macro ();
 
       alt_strp_htab = strp_htab;
-- 
2.17.1


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

* RE: [PATCH] Split DWARF support for DWZ
  2021-08-23  5:35 [PATCH] Split DWARF support for DWZ Sharma, Alok Kumar
@ 2021-10-03 12:37 ` Sharma, Alok Kumar
  0 siblings, 0 replies; 2+ messages in thread
From: Sharma, Alok Kumar @ 2021-10-03 12:37 UTC (permalink / raw)
  To: dwz; +Cc: George, Jini Susan, Achra, Nitika, E, Nagajyothi, Joseph, Ancel

PING !

Regards,
Alok

-----Original Message-----
From: Sharma, Alok Kumar 
Sent: Monday, August 23, 2021 11:06 AM
To: dwz@sourceware.org
Cc: George, Jini Susan <JiniSusan.George@amd.com>; Achra, Nitika <Nitika.Achra@amd.com>; E, Nagajyothi <Nagajyothi.E@amd.com>; Joseph, Ancel <Ancel.Joseph@amd.com>
Subject: [PATCH] Split DWARF support for DWZ

Hi all,

I request you to please review the source modification done to support split DWARF.

    Existing DWZ when deals with executable having split DWARF information
    in separate file (DW_AT_GNU_dwo_name/DW_AT_dwo_name), it ignores the
    separate file and only attempts to optimize main executable which has
    very less information as almost all the debug information is present
    in sepaterate file.

    Now DWZ is modified to extract the separate file name from
    atributes DW_AT_GNU_dwo_name/DW_AT_dwo_name in main executable and
    calls function DWZ on separate file as well.

    While processing DWO file, information is read from corresponding ".dwo"
    sections in place of original one. This is assisted by macros
    DEFINE_DEBUG (defining section enum) and DEFINE_SECTION (defining section
    names along with other fields) in a way that very next section to the
    original one is the ".dwo" variant of it. When we process DWO file we
    access section using macro "INDEX(DEBUG_SECTION)", which is defined as
    "(DEBUG_SECTION + is_dwo_file)". This way we avoid any duplicacy and
    use existing code.

Regards,
Alok

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

end of thread, other threads:[~2021-10-03 12:37 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-23  5:35 [PATCH] Split DWARF support for DWZ Sharma, Alok Kumar
2021-10-03 12:37 ` Sharma, Alok Kumar

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