diff --git a/tests/debugedit.at b/tests/debugedit.at
index 49721a342..bcd86ac67 100644
--- a/tests/debugedit.at
+++ b/tests/debugedit.at
@@ -253,9 +253,8 @@ AT_CLEANUP
 # ===
 # Make sure -fdebug-types-section has updated strings in objects.
 # ===
-AT_SETUP([debugedit .debug_types objects])
-AT_KEYWORDS([debugtypes] [debugedit])
-RPM_DEBUGEDIT_SETUP([-fdebug-types-section])
+m4_define([RPM_DEBUGEDIT_DEBUG_TYPES_OBJECTS],[
+RPM_DEBUGEDIT_SETUP($1)
 
 AT_DATA([expout],
 [st1
@@ -283,15 +282,13 @@ for i in ./foo.o ./subdir_bar/bar.o ./baz.o;do \
           | sort;
 done
 ]],[0],[expout])
-
-AT_CLEANUP
+])
 
 # ===
 # Make sure -fdebug-types-section has updated strings in partial linked object.
 # ===
-AT_SETUP([debugedit .debug_types partial])
-AT_KEYWORDS([debugtypes] [debugedit])
-RPM_DEBUGEDIT_SETUP([-fdebug-types-section])
+m4_define([RPM_DEBUGEDIT_DEBUG_TYPES_PARTIAL],[
+RPM_DEBUGEDIT_SETUP($1)
 
 AT_DATA([expout],
 [st1
@@ -311,15 +308,13 @@ readelf --debug-dump=info ./foobarbaz.part.o \
         | sed -n 's/^.*> *DW_AT_name *:.* \(stringp[^ ]*\|st.\)$/\1/p' \
         | sort
 ]],[0],[expout])
-
-AT_CLEANUP
+])
 
 # ===
 # Make sure -fdebug-types-section has updated strings in executable.
 # ===
-AT_SETUP([debugedit .debug_types exe])
-AT_KEYWORDS([debugtypes] [debugedit])
-RPM_DEBUGEDIT_SETUP([-fdebug-types-section])
+m4_define([RPM_DEBUGEDIT_DEBUG_TYPES_EXE],[
+RPM_DEBUGEDIT_SETUP($1)
 
 AT_DATA([expout],
 [st1
@@ -339,7 +334,36 @@ readelf --debug-dump=info ./foobarbaz.exe \
         | sed -n 's/^.*> *DW_AT_name *:.* \(stringp[^ ]*\|st.\)$/\1/p' \
         | sort
 ]],[0],[expout])
+])
+
+AT_SETUP([debugedit DWARF-4 .debug_types objects])
+AT_KEYWORDS([debugtypes] [debugedit])
+RPM_DEBUGEDIT_DEBUG_TYPES_OBJECTS([-gdwarf-4 -fdebug-types-section])
+AT_CLEANUP
 
+AT_SETUP([debugedit DWARF-4 .debug_types partial])
+AT_KEYWORDS([debugtypes] [debugedit])
+RPM_DEBUGEDIT_DEBUG_TYPES_PARTIAL([-gdwarf-4 -fdebug-types-section])
+AT_CLEANUP
+
+AT_SETUP([debugedit DWARF-4 .debug_types exe])
+AT_KEYWORDS([debugtypes] [debugedit])
+RPM_DEBUGEDIT_DEBUG_TYPES_EXE([-gdwarf-4 -fdebug-types-section])
+AT_CLEANUP
+
+AT_SETUP([debugedit DWARF-5 .debug_types objects])
+AT_KEYWORDS([debugtypes] [debugedit])
+RPM_DEBUGEDIT_DEBUG_TYPES_OBJECTS([-gdwarf-5 -fdebug-types-section])
+AT_CLEANUP
+
+AT_SETUP([debugedit DWARF-5 .debug_types partial])
+AT_KEYWORDS([debugtypes] [debugedit])
+RPM_DEBUGEDIT_DEBUG_TYPES_PARTIAL([-gdwarf-5 -fdebug-types-section])
+AT_CLEANUP
+
+AT_SETUP([debugedit DWARF-5 .debug_types exe])
+AT_KEYWORDS([debugtypes] [debugedit])
+RPM_DEBUGEDIT_DEBUG_TYPES_EXE([-gdwarf-5 -fdebug-types-section])
 AT_CLEANUP
 
 # foo.o and bar.o are build with relative paths and so will use the
diff --git a/tools/debugedit.c b/tools/debugedit.c
index 9f1dc2d3f..19f69e263 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -433,7 +433,8 @@ typedef struct debug_section
     int sec, relsec;
     REL *relbuf;
     REL *relend;
-    /* Only happens for COMDAT .debug_macro and .debug_types.  */
+    /* Only happens for COMDAT .debug_macro, .debug_types and DWARF-5
+       .debug_info.  */
     struct debug_section *next;
   } debug_section;
 
@@ -755,12 +756,19 @@ no_memory:
            }
          form = read_uleb128 (ptr);
          if (form == 2
-             || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8))
+             || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8
+                 && form != DW_FORM_implicit_const))
            {
-             error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form);
+             error (0, 0, "%s: Unknown DWARF abbrev DW_FORM_0x%x",
+                    dso->filename, form);
              htab_delete (h);
              return NULL;
            }
+         if (form == DW_FORM_implicit_const)
+           {
+             /* It is SLEB128 but the value is dropped anyway.  */
+             read_uleb128 (ptr);
+           }
 
          t->attr[t->nattr].attr = attr;
          t->attr[t->nattr++].form = form;
@@ -1505,6 +1513,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char 
**ptrp)
        *ptrp += 4;
       break;
     case DW_FORM_flag_present:
+    case DW_FORM_implicit_const:
       break;
     case DW_FORM_addr:
       *ptrp += ptr_size;
@@ -2018,7 +2027,7 @@ line_rel_cmp (const void *a, const void *b)
 }
 
 static int
-edit_info (DSO *dso, int phase, struct debug_section *sec)
+edit_info (DSO *dso, int phase, struct debug_section *sec, bool is_types)
 {
   unsigned char *ptr, *endcu, *endsec;
   uint32_t value;
@@ -2033,7 +2042,9 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
   endsec = ptr + sec->size;
   while (ptr < endsec)
     {
-      if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec)
+      unsigned char *sec_start = ptr;
+
+      if (ptr + 4 + 2 + 1 + 1 > endsec)
        {
          error (0, 0, "%s: %s CU header too small",
                 dso->filename, sec->name);
@@ -2055,13 +2066,48 @@ edit_info (DSO *dso, int phase, struct debug_section 
*sec)
        }
 
       cu_version = read_16 (ptr);
-      if (cu_version != 2 && cu_version != 3 && cu_version != 4)
+      if (cu_version != 2 && cu_version != 3 && cu_version != 4
+         && cu_version != 5)
        {
          error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
                 cu_version);
          return 1;
        }
 
+      int cu_ptr_size;
+      bool cu_is_types;
+
+      if (cu_version >= 5)
+       {
+         if (is_types)
+           {
+             error (0, 0, "%s: .debug_types are invalid for DWARF 5+",
+                    dso->filename);
+             return 1;
+           }
+
+         uint8_t unit_type = read_8 (ptr);
+         if (unit_type != DW_UT_compile && unit_type != DW_UT_type)
+           {
+             error (0, 0, "%s: Unit type %u unhandled", dso->filename,
+                    unit_type);
+             return 1;
+           }
+         cu_is_types = unit_type == DW_UT_type;
+
+         cu_ptr_size = read_8 (ptr);
+       }
+      else
+       cu_is_types = is_types;
+
+      unsigned char *header_end = (sec_start + (!cu_is_types ? 11 : 23)
+                                  + (cu_version < 5 ? 0 : 1));
+      if (header_end > endsec)
+       {
+         error (0, 0, "%s: %s CU header too small", dso->filename, sec->name);
+         return 1;
+       }
+
       value = read_32_relocated (ptr);
       if (value >= debug_sections[DEBUG_ABBREV].size)
        {
@@ -2073,9 +2119,12 @@ edit_info (DSO *dso, int phase, struct debug_section 
*sec)
          return 1;
        }
 
+      if (cu_version < 5)
+       cu_ptr_size = read_8 (ptr);
+
       if (ptr_size == 0)
        {
-         ptr_size = read_8 (ptr);
+         ptr_size = cu_ptr_size;
          if (ptr_size != 4 && ptr_size != 8)
            {
              error (0, 0, "%s: Invalid DWARF pointer size %d",
@@ -2083,14 +2132,14 @@ edit_info (DSO *dso, int phase, struct debug_section 
*sec)
              return 1;
            }
        }
-      else if (read_8 (ptr) != ptr_size)
+      else if (cu_ptr_size != ptr_size)
        {
          error (0, 0, "%s: DWARF pointer size differs between CUs",
                 dso->filename);
          return 1;
        }
 
-      if (sec != &debug_sections[DEBUG_INFO])
+      if (cu_is_types)
        ptr += 12; /* Skip type_signature and type_offset.  */
 
       abbrev = read_abbrev (dso,
@@ -2179,7 +2228,8 @@ edit_dwarf2 (DSO *dso)
                  struct debug_section *debug_sec = &debug_sections[j];
                  if (debug_sections[j].data)
                    {
-                     if (j != DEBUG_MACRO && j != DEBUG_TYPES)
+                     if (j != DEBUG_MACRO && j != DEBUG_TYPES
+                         && j != DEBUG_INFO)
                        {
                          error (0, 0, "%s: Found two copies of %s section",
                                 dso->filename, name);
@@ -2187,8 +2237,9 @@ edit_dwarf2 (DSO *dso)
                        }
                      else
                        {
-                         /* In relocatable files .debug_macro and .debug_types
-                            might appear multiple times as COMDAT section.  */
+                         /* In relocatable files .debug_macro, .debug_types
+                            and DWARF-5 .debug_info might appear multiple
+                            times as COMDAT section.  */
                          struct debug_section *sec;
                          sec = calloc (sizeof (struct debug_section), 1);
                          if (sec == NULL)
@@ -2238,7 +2289,7 @@ edit_dwarf2 (DSO *dso)
                          + (dso->shdr[i].sh_type == SHT_RELA),
                          debug_sections[j].name) == 0)
                {
-                 if (j == DEBUG_MACRO || j == DEBUG_TYPES)
+                 if (j == DEBUG_MACRO || j == DEBUG_TYPES || j == DEBUG_INFO)
                    {
                      /* Pick the correct one.  */
                      int rel_target = dso->shdr[i].sh_info;
@@ -2302,8 +2353,13 @@ edit_dwarf2 (DSO *dso)
        break;
 
       rel_updated = false;
-      if (edit_info (dso, phase, &debug_sections[DEBUG_INFO]))
-       return 1;
+      struct debug_section *info_sec = &debug_sections[DEBUG_INFO];
+      while (info_sec != NULL)
+       {
+         if (edit_info (dso, phase, info_sec, false /* is_types */))
+           return 1;
+         info_sec = info_sec->next;
+       }
 
       /* Remember whether any .debug_info relocations might need
         to be updated. */
@@ -2313,7 +2369,7 @@ edit_dwarf2 (DSO *dso)
       struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
       while (types_sec != NULL)
        {
-         if (edit_info (dso, phase, types_sec))
+         if (edit_info (dso, phase, types_sec, true /* is_types */))
            return 1;
          types_sec = types_sec->next;
        }
@@ -2564,7 +2620,14 @@ edit_dwarf2 (DSO *dso)
 
   /* Update any relocations addends we might have touched. */
   if (info_rel_updated)
-    update_rela_data (dso, &debug_sections[DEBUG_INFO]);
+    {
+      struct debug_section *info_sec = &debug_sections[DEBUG_INFO];
+      while (info_sec != NULL)
+       {
+         update_rela_data (dso, info_sec);
+         info_sec = info_sec->next;
+       }
+    }
   if (types_rel_updated)
     {
       struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
@@ -2914,6 +2977,7 @@ main (int argc, char *argv[])
   if (dso == NULL)
     exit (1);
 
+  bool have_info = false;
   for (i = 1; i < dso->ehdr.e_shnum; i++)
     {
       const char *name;
@@ -2929,7 +2993,7 @@ main (int argc, char *argv[])
              break;
            }
          if (strcmp (name, ".debug_info") == 0)
-           edit_dwarf2 (dso);
+           have_info = true;
 
          break;
        case SHT_NOTE:
@@ -2960,6 +3024,9 @@ main (int argc, char *argv[])
        }
     }
 
+  if (have_info)
+    edit_dwarf2 (dso);
+
   /* Normally we only need to explicitly update the section headers
      and data when any section data changed size. But because of a bug
      in elfutils before 0.169 we will have to update and write out all
@@ -3136,6 +3203,17 @@ main (int argc, char *argv[])
       types_sec = next;
     }
 
+  /* In case there were multiple (COMDAT) DWARF-5 .debug_info sections,
+     free them.  */
+  struct debug_section *info_sec = &debug_sections[DEBUG_INFO];
+  info_sec = info_sec->next;
+  while (info_sec != NULL)
+    {
+      struct debug_section *next = info_sec->next;
+      free (info_sec);
+      info_sec = next;
+    }
+
   poptFreeContext (optCon);
 
   return 0;

_______________________________________________
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint

Reply via email to