Mark Wielaard 652537
From 8b5dcb4c2175ac706a4e1c34ce83301213800689 Mon Sep 17 00:00:00 2001
Mark Wielaard 652537
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Mark Wielaard 652537
Date: Mon, 18 Jan 2021 22:56:53 +0100
Mark Wielaard 652537
Subject: [PATCH 5/6] debugedit: Implement DWARF-5 unit header and new forms
Mark Wielaard 652537
 parsing.
Mark Wielaard 652537
Mark Wielaard 652537
Recognize the various new DWARF5 .debug sections.
Mark Wielaard 652537
Parse and skip new DWARF5 forms in read_abbrev and skip_form.
Mark Wielaard 652537
Read DWARF5 unit headers for compile and partial units in edit_info.
Mark Wielaard 652537
Mark Wielaard 652537
This is enough to be able to process gcc -gdwarf-5 produced binaries
Mark Wielaard 652537
without the new DWARF5 .debug_line format (which isn't produced with
Mark Wielaard 652537
binutils < 2.36).
Mark Wielaard 652537
Mark Wielaard 652537
Patches slightly edited/merged by Mark Wielaard <mark@klomp.org>
Mark Wielaard 652537
---
Mark Wielaard 652537
 tools/debugedit.c | 88 +++++++++++++++++++++++++++++++++++++++++++----
Mark Wielaard 652537
 1 file changed, 81 insertions(+), 7 deletions(-)
Mark Wielaard 652537
Mark Wielaard 652537
diff --git a/tools/debugedit.c b/tools/debugedit.c
Mark Wielaard 652537
index 7464883c5..be5fee85b 100644
Mark Wielaard 652537
--- a/tools/debugedit.c
Mark Wielaard 652537
+++ b/tools/debugedit.c
Mark Wielaard 652537
@@ -453,6 +453,11 @@ static debug_section debug_sections[] =
Mark Wielaard 652537
 #define DEBUG_TYPES	11
Mark Wielaard 652537
 #define DEBUG_MACRO	12
Mark Wielaard 652537
 #define DEBUG_GDB_SCRIPT	13
Mark Wielaard 652537
+#define DEBUG_RNGLISTS	14
Mark Wielaard 652537
+#define DEBUG_LINE_STR	15
Mark Wielaard 652537
+#define DEBUG_ADDR	16
Mark Wielaard 652537
+#define DEBUG_STR_OFFSETS	17
Mark Wielaard 652537
+#define DEBUG_LOCLISTS	18
Mark Wielaard 652537
     { ".debug_info", NULL, NULL, 0, 0, 0 },
Mark Wielaard 652537
     { ".debug_abbrev", NULL, NULL, 0, 0, 0 },
Mark Wielaard 652537
     { ".debug_line", NULL, NULL, 0, 0, 0 },
Mark Wielaard 652537
@@ -467,6 +472,11 @@ static debug_section debug_sections[] =
Mark Wielaard 652537
     { ".debug_types", NULL, NULL, 0, 0, 0 },
Mark Wielaard 652537
     { ".debug_macro", NULL, NULL, 0, 0, 0 },
Mark Wielaard 652537
     { ".debug_gdb_scripts", NULL, NULL, 0, 0, 0 },
Mark Wielaard 652537
+    { ".debug_rnglists", NULL, NULL, 0, 0, 0 },
Mark Wielaard 652537
+    { ".debug_line_str", NULL, NULL, 0, 0, 0 },
Mark Wielaard 652537
+    { ".debug_addr", NULL, NULL, 0, 0, 0 },
Mark Wielaard 652537
+    { ".debug_str_offsets", NULL, NULL, 0, 0, 0 },
Mark Wielaard 652537
+    { ".debug_loclists", NULL, NULL, 0, 0, 0 },
Mark Wielaard 652537
     { NULL, NULL, NULL, 0, 0, 0 }
Mark Wielaard 652537
   };
Mark Wielaard 652537
 
Mark Wielaard 652537
@@ -755,12 +765,28 @@ no_memory:
Mark Wielaard 652537
 	    }
Mark Wielaard 652537
 	  form = read_uleb128 (ptr);
Mark Wielaard 652537
 	  if (form == 2
Mark Wielaard 652537
-	      || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8))
Mark Wielaard 652537
+	      || (form > DW_FORM_flag_present
Mark Wielaard 652537
+		  && !(form == DW_FORM_ref_sig8
Mark Wielaard 652537
+		       || form == DW_FORM_data16
Mark Wielaard 652537
+		       || form == DW_FORM_implicit_const
Mark Wielaard 652537
+		       || form == DW_FORM_addrx
Mark Wielaard 652537
+		       || form == DW_FORM_loclistx
Mark Wielaard 652537
+		       || form == DW_FORM_rnglistx
Mark Wielaard 652537
+		       || form == DW_FORM_addrx1
Mark Wielaard 652537
+		       || form == DW_FORM_addrx2
Mark Wielaard 652537
+		       || form == DW_FORM_addrx3
Mark Wielaard 652537
+		       || form == DW_FORM_addrx4)))
Mark Wielaard 652537
 	    {
Mark Wielaard 652537
-	      error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form);
Mark Wielaard 652537
+	      error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename,
Mark Wielaard 652537
+		     form);
Mark Wielaard 652537
 	      htab_delete (h);
Mark Wielaard 652537
 	      return NULL;
Mark Wielaard 652537
 	    }
Mark Wielaard 652537
+	  if (form == DW_FORM_implicit_const)
Mark Wielaard 652537
+	    {
Mark Wielaard 652537
+	      /* It is SLEB128 but the value is dropped anyway.  */
Mark Wielaard 652537
+	      read_uleb128 (ptr);
Mark Wielaard 652537
+	    }
Mark Wielaard 652537
 
Mark Wielaard 652537
 	  t->attr[t->nattr].attr = attr;
Mark Wielaard 652537
 	  t->attr[t->nattr++].form = form;
Mark Wielaard 652537
@@ -1505,6 +1531,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
Mark Wielaard 652537
 	*ptrp += 4;
Mark Wielaard 652537
       break;
Mark Wielaard 652537
     case DW_FORM_flag_present:
Mark Wielaard 652537
+    case DW_FORM_implicit_const:
Mark Wielaard 652537
       break;
Mark Wielaard 652537
     case DW_FORM_addr:
Mark Wielaard 652537
       *ptrp += ptr_size;
Mark Wielaard 652537
@@ -1512,14 +1539,24 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
Mark Wielaard 652537
     case DW_FORM_ref1:
Mark Wielaard 652537
     case DW_FORM_flag:
Mark Wielaard 652537
     case DW_FORM_data1:
Mark Wielaard 652537
+    case DW_FORM_strx1:
Mark Wielaard 652537
+    case DW_FORM_addrx1:
Mark Wielaard 652537
       ++*ptrp;
Mark Wielaard 652537
       break;
Mark Wielaard 652537
     case DW_FORM_ref2:
Mark Wielaard 652537
     case DW_FORM_data2:
Mark Wielaard 652537
+    case DW_FORM_strx2:
Mark Wielaard 652537
+    case DW_FORM_addrx2:
Mark Wielaard 652537
       *ptrp += 2;
Mark Wielaard 652537
       break;
Mark Wielaard 652537
+    case DW_FORM_strx3:
Mark Wielaard 652537
+    case DW_FORM_addrx3:
Mark Wielaard 652537
+      *ptrp += 3;
Mark Wielaard 652537
+      break;
Mark Wielaard 652537
     case DW_FORM_ref4:
Mark Wielaard 652537
     case DW_FORM_data4:
Mark Wielaard 652537
+    case DW_FORM_strx4:
Mark Wielaard 652537
+    case DW_FORM_addrx4:
Mark Wielaard 652537
     case DW_FORM_sec_offset:
Mark Wielaard 652537
       *ptrp += 4;
Mark Wielaard 652537
       break;
Mark Wielaard 652537
@@ -1528,12 +1565,20 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
Mark Wielaard 652537
     case DW_FORM_ref_sig8:
Mark Wielaard 652537
       *ptrp += 8;
Mark Wielaard 652537
       break;
Mark Wielaard 652537
+    case DW_FORM_data16:
Mark Wielaard 652537
+      *ptrp += 16;
Mark Wielaard 652537
+      break;
Mark Wielaard 652537
     case DW_FORM_sdata:
Mark Wielaard 652537
     case DW_FORM_ref_udata:
Mark Wielaard 652537
     case DW_FORM_udata:
Mark Wielaard 652537
+    case DW_FORM_strx:
Mark Wielaard 652537
+    case DW_FORM_loclistx:
Mark Wielaard 652537
+    case DW_FORM_rnglistx:
Mark Wielaard 652537
+    case DW_FORM_addrx:
Mark Wielaard 652537
       read_uleb128 (*ptrp);
Mark Wielaard 652537
       break;
Mark Wielaard 652537
     case DW_FORM_strp:
Mark Wielaard 652537
+    case DW_FORM_line_strp:
Mark Wielaard 652537
       *ptrp += 4;
Mark Wielaard 652537
       break;
Mark Wielaard 652537
     case DW_FORM_string:
Mark Wielaard 652537
@@ -1560,7 +1605,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
Mark Wielaard 652537
       assert (len < UINT_MAX);
Mark Wielaard 652537
       break;
Mark Wielaard 652537
     default:
Mark Wielaard 652537
-      error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, *formp);
Mark Wielaard 652537
+      error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename, *formp);
Mark Wielaard 652537
       return FORM_ERROR;
Mark Wielaard 652537
     }
Mark Wielaard 652537
 
Mark Wielaard 652537
@@ -2030,7 +2075,10 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
Mark Wielaard 652537
   endsec = ptr + sec->size;
Mark Wielaard 652537
   while (ptr < endsec)
Mark Wielaard 652537
     {
Mark Wielaard 652537
-      if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec)
Mark Wielaard 652537
+      unsigned char *cu_start = ptr;
Mark Wielaard 652537
+
Mark Wielaard 652537
+      /* header size, version, unit_type, ptr_size.  */
Mark Wielaard 652537
+      if (ptr + 4 + 2 + 1 + 1 > endsec)
Mark Wielaard 652537
 	{
Mark Wielaard 652537
 	  error (0, 0, "%s: %s CU header too small",
Mark Wielaard 652537
 		 dso->filename, sec->name);
Mark Wielaard 652537
@@ -2052,13 +2100,36 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
Mark Wielaard 652537
 	}
Mark Wielaard 652537
 
Mark Wielaard 652537
       cu_version = read_16 (ptr);
Mark Wielaard 652537
-      if (cu_version != 2 && cu_version != 3 && cu_version != 4)
Mark Wielaard 652537
+      if (cu_version != 2 && cu_version != 3 && cu_version != 4
Mark Wielaard 652537
+	  && cu_version != 5)
Mark Wielaard 652537
 	{
Mark Wielaard 652537
 	  error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
Mark Wielaard 652537
 		 cu_version);
Mark Wielaard 652537
 	  return 1;
Mark Wielaard 652537
 	}
Mark Wielaard 652537
 
Mark Wielaard 652537
+      int cu_ptr_size = 0;
Mark Wielaard 652537
+
Mark Wielaard 652537
+      if (cu_version >= 5)
Mark Wielaard 652537
+	{
Mark Wielaard 652537
+	  uint8_t unit_type = read_8 (ptr);
Mark Wielaard 652537
+	  if (unit_type != DW_UT_compile && unit_type != DW_UT_partial)
Mark Wielaard 652537
+	    {
Mark Wielaard 652537
+	      error (0, 0, "%s: Unit type %u unhandled", dso->filename,
Mark Wielaard 652537
+		     unit_type);
Mark Wielaard 652537
+	      return 1;
Mark Wielaard 652537
+	    }
Mark Wielaard 652537
+
Mark Wielaard 652537
+	  cu_ptr_size = read_8 (ptr);
Mark Wielaard 652537
+	}
Mark Wielaard 652537
+
Mark Wielaard 652537
+      unsigned char *header_end = (cu_start + 23 + (cu_version < 5 ? 0 : 1));
Mark Wielaard 652537
+      if (header_end > endsec)
Mark Wielaard 652537
+	{
Mark Wielaard 652537
+	  error (0, 0, "%s: %s CU header too small", dso->filename, sec->name);
Mark Wielaard 652537
+	  return 1;
Mark Wielaard 652537
+	}
Mark Wielaard 652537
+
Mark Wielaard 652537
       value = read_32_relocated (ptr);
Mark Wielaard 652537
       if (value >= debug_sections[DEBUG_ABBREV].size)
Mark Wielaard 652537
 	{
Mark Wielaard 652537
@@ -2070,9 +2141,12 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
Mark Wielaard 652537
 	  return 1;
Mark Wielaard 652537
 	}
Mark Wielaard 652537
 
Mark Wielaard 652537
+      if (cu_version < 5)
Mark Wielaard 652537
+	cu_ptr_size = read_8 (ptr);
Mark Wielaard 652537
+
Mark Wielaard 652537
       if (ptr_size == 0)
Mark Wielaard 652537
 	{
Mark Wielaard 652537
-	  ptr_size = read_8 (ptr);
Mark Wielaard 652537
+	  ptr_size = cu_ptr_size;
Mark Wielaard 652537
 	  if (ptr_size != 4 && ptr_size != 8)
Mark Wielaard 652537
 	    {
Mark Wielaard 652537
 	      error (0, 0, "%s: Invalid DWARF pointer size %d",
Mark Wielaard 652537
@@ -2080,7 +2154,7 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
Mark Wielaard 652537
 	      return 1;
Mark Wielaard 652537
 	    }
Mark Wielaard 652537
 	}
Mark Wielaard 652537
-      else if (read_8 (ptr) != ptr_size)
Mark Wielaard 652537
+      else if (cu_ptr_size != ptr_size)
Mark Wielaard 652537
 	{
Mark Wielaard 652537
 	  error (0, 0, "%s: DWARF pointer size differs between CUs",
Mark Wielaard 652537
 		 dso->filename);
Mark Wielaard 652537
-- 
Mark Wielaard 652537
2.18.4
Mark Wielaard 652537