Mark Wielaard c6952c
diff --git a/tools/debugedit.c b/tools/debugedit.c
Mark Wielaard c6952c
index 4798c63..47e5bbf 100644
Mark Wielaard c6952c
--- a/tools/debugedit.c
Mark Wielaard c6952c
+++ b/tools/debugedit.c
Mark Wielaard c6952c
@@ -2581,40 +2581,25 @@ main (int argc, char *argv[])
Mark Wielaard c6952c
 	  break;
Mark Wielaard c6952c
 	case SHT_NOTE:
Mark Wielaard c6952c
 	  if (do_build_id
Mark Wielaard c6952c
-	      && build_id == NULL && (dso->shdr[i].sh_flags & SHF_ALLOC))
Mark Wielaard c6952c
+	      && build_id == 0 && (dso->shdr[i].sh_flags & SHF_ALLOC))
Mark Wielaard c6952c
 	    {
Mark Wielaard c6952c
 	      /* Look for a build-ID note here.  */
Mark Wielaard c6952c
+	      size_t off = 0;
Mark Wielaard c6952c
+	      GElf_Nhdr nhdr;
Mark Wielaard c6952c
+	      size_t name_off;
Mark Wielaard c6952c
+	      size_t desc_off;
Mark Wielaard c6952c
 	      Elf_Data *data = elf_getdata (elf_getscn (dso->elf, i), NULL);
Mark Wielaard c6952c
-	      Elf32_Nhdr nh;
Mark Wielaard c6952c
-	      Elf_Data dst =
Mark Wielaard c6952c
-		{
Mark Wielaard c6952c
-		  .d_version = EV_CURRENT, .d_type = ELF_T_NHDR,
Mark Wielaard c6952c
-		  .d_buf = &nh, .d_size = sizeof nh
Mark Wielaard c6952c
-		};
Mark Wielaard c6952c
-	      Elf_Data src = dst;
Mark Wielaard c6952c
-	      src.d_buf = data->d_buf;
Mark Wielaard c6952c
-	      assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
Mark Wielaard c6952c
-	      while ((char *) data->d_buf + data->d_size -
Mark Wielaard c6952c
-		     (char *) src.d_buf > (int) sizeof nh
Mark Wielaard c6952c
-		     && elf32_xlatetom (&dst, &src, dso->ehdr.e_ident[EI_DATA]))
Mark Wielaard c6952c
-		{
Mark Wielaard c6952c
-		  Elf32_Word len = sizeof nh + nh.n_namesz;
Mark Wielaard c6952c
-		  len = (len + 3) & ~3;
Mark Wielaard c6952c
-
Mark Wielaard c6952c
-		  if (nh.n_namesz == sizeof "GNU" && nh.n_type == 3
Mark Wielaard c6952c
-		      && !memcmp ((char *) src.d_buf + sizeof nh, "GNU", sizeof "GNU"))
Mark Wielaard c6952c
-		    {
Mark Wielaard c6952c
-		      build_id = data;
Mark Wielaard c6952c
-		      build_id_offset = (char *) src.d_buf + len -
Mark Wielaard c6952c
-					(char *) data->d_buf;
Mark Wielaard c6952c
-		      build_id_size = nh.n_descsz;
Mark Wielaard c6952c
-		      break;
Mark Wielaard c6952c
-		    }
Mark Wielaard c6952c
-
Mark Wielaard c6952c
-		  len += nh.n_descsz;
Mark Wielaard c6952c
-		  len = (len + 3) & ~3;
Mark Wielaard c6952c
-		  src.d_buf = (char *) src.d_buf + len;
Mark Wielaard c6952c
-		}
Mark Wielaard c6952c
+	      while ((off = gelf_getnote (data, off,
Mark Wielaard c6952c
+					  &nhdr, &name_off, &desc_off)) > 0)
Mark Wielaard c6952c
+		if (nhdr.n_type == NT_GNU_BUILD_ID
Mark Wielaard c6952c
+		    && nhdr.n_namesz == sizeof "GNU"
Mark Wielaard c6952c
+		    && (memcmp ((char *)data->d_buf + name_off, "GNU",
Mark Wielaard c6952c
+				sizeof "GNU") == 0))
Mark Wielaard c6952c
+		  {
Mark Wielaard c6952c
+		    build_id = data;
Mark Wielaard c6952c
+		    build_id_offset = desc_off;
Mark Wielaard c6952c
+		    build_id_size = nhdr.n_descsz;
Mark Wielaard c6952c
+		  }
Mark Wielaard c6952c
 	    }
Mark Wielaard c6952c
 	  break;
Mark Wielaard c6952c
 	default:
Mark Wielaard c6952c
@@ -2622,6 +2607,20 @@ main (int argc, char *argv[])
Mark Wielaard c6952c
 	}
Mark Wielaard c6952c
     }
Mark Wielaard c6952c
 
Mark Wielaard c6952c
+  /* Normally we only need to explicitly update the section headers
Mark Wielaard c6952c
+     and data when any section data changed size. But because of a bug
Mark Wielaard c6952c
+     in elfutils before 0.169 we will have to update and write out all
Mark Wielaard c6952c
+     section data if any data has changed (when ELF_F_LAYOUT was
Mark Wielaard c6952c
+     set). https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */
Mark Wielaard c6952c
+  bool need_update = need_strp_update || need_stmt_update;
Mark Wielaard c6952c
+
Mark Wielaard c6952c
+#if !_ELFUTILS_PREREQ (0, 169)
Mark Wielaard c6952c
+  /* string replacements or build_id updates don't change section size. */
Mark Wielaard c6952c
+  need_update = (need_update
Mark Wielaard c6952c
+		 || need_string_replacement
Mark Wielaard c6952c
+		 || (do_build_id && build_id != NULL));
Mark Wielaard c6952c
+#endif
Mark Wielaard c6952c
+
Mark Wielaard c6952c
   /* We might have changed the size of some debug sections. If so make
Mark Wielaard c6952c
      sure the section headers are updated and the data offsets are
Mark Wielaard c6952c
      correct. We set ELF_F_LAYOUT above because we don't want libelf
Mark Wielaard c6952c
@@ -2631,7 +2630,7 @@ main (int argc, char *argv[])
Mark Wielaard c6952c
      anything for the phdrs allocated sections. Keep the offset of
Mark Wielaard c6952c
      allocated sections so they are at the same place in the file. Add
Mark Wielaard c6952c
      unallocated ones after the allocated ones. */
Mark Wielaard c6952c
-  if (dso->phnum != 0 && (need_strp_update || need_stmt_update))
Mark Wielaard c6952c
+  if (dso->phnum != 0 && need_update)
Mark Wielaard c6952c
     {
Mark Wielaard c6952c
       Elf *elf = dso->elf;
Mark Wielaard c6952c
       GElf_Off last_offset;