diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d13e7f5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/rpm-4.16.1.3.tar.bz2
diff --git a/.rpm.metadata b/.rpm.metadata
new file mode 100644
index 0000000..ec701c1
--- /dev/null
+++ b/.rpm.metadata
@@ -0,0 +1 @@
+4c70c0dc08aec5ba29f3ee72eda774bd32230f77 SOURCES/rpm-4.16.1.3.tar.bz2
diff --git a/SOURCES/0001-Issue-deprecation-warning-when-creating-BDB-database.patch b/SOURCES/0001-Issue-deprecation-warning-when-creating-BDB-database.patch
new file mode 100644
index 0000000..94484d6
--- /dev/null
+++ b/SOURCES/0001-Issue-deprecation-warning-when-creating-BDB-database.patch
@@ -0,0 +1,28 @@
+From 5a80033676f331de2b0979fe7be9557279b6bff3 Mon Sep 17 00:00:00 2001
+Message-Id: <5a80033676f331de2b0979fe7be9557279b6bff3.1603865959.git.pmatilai@redhat.com>
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Wed, 28 Oct 2020 08:14:55 +0200
+Subject: [PATCH] Issue deprecation warning when creating BDB databases
+
+---
+ lib/backend/db3.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/lib/backend/db3.c b/lib/backend/db3.c
+index 68cfa6fb2..cb31676e7 100644
+--- a/lib/backend/db3.c
++++ b/lib/backend/db3.c
+@@ -874,6 +874,10 @@ static int db3_dbiOpen(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flag
+ 		oflags &= ~DB_RDONLY;
+ 		dbtype = (rpmtag == RPMDBI_PACKAGES) ?  DB_HASH : DB_BTREE;
+ 		retry_open--;
++		if (rpmtag == RPMDBI_PACKAGES) {
++		    rpmlog(RPMLOG_WARNING,
++			    "using deprecated bdb database backend");
++		}
+ 	    } else {
+ 		retry_open = 0;
+ 	    }
+-- 
+2.28.0
+
diff --git a/SOURCES/0001-NFC-debugedit-Protect-macro-arguments-by-parentheses.patch b/SOURCES/0001-NFC-debugedit-Protect-macro-arguments-by-parentheses.patch
new file mode 100644
index 0000000..6607373
--- /dev/null
+++ b/SOURCES/0001-NFC-debugedit-Protect-macro-arguments-by-parentheses.patch
@@ -0,0 +1,61 @@
+From a93b0f5c9f0abef6efb5413df9e98b047a2a9a46 Mon Sep 17 00:00:00 2001
+From: Jan Kratochvil <jan.kratochvil@redhat.com>
+Date: Mon, 17 Aug 2020 16:56:56 +0200
+Subject: [PATCH 1/6] [NFC] debugedit: Protect macro arguments by parentheses
+
+---
+ tools/debugedit.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/tools/debugedit.c b/tools/debugedit.c
+index 6bea88551..a351adec8 100644
+--- a/tools/debugedit.c
++++ b/tools/debugedit.c
+@@ -233,7 +233,7 @@ typedef struct
+   int shift = 0;			\
+   do					\
+     {					\
+-      c = *ptr++;			\
++      c = *(ptr)++;			\
+       ret |= (c & 0x7f) << shift;	\
+       shift += 7;			\
+     } while (c & 0x80);			\
+@@ -251,7 +251,7 @@ typedef struct
+       valv >>= 7;			\
+       if (valv)				\
+ 	c |= 0x80;			\
+-      *ptr++ = c;			\
++      *(ptr)++ = c;			\
+     }					\
+   while (valv);				\
+ })
+@@ -311,7 +311,7 @@ strptr (DSO *dso, int sec, off_t offset)
+ }
+ 
+ 
+-#define read_8(ptr) *ptr++
++#define read_8(ptr) *(ptr)++
+ 
+ #define read_16(ptr) ({					\
+   uint16_t ret = do_read_16 (ptr);			\
+@@ -328,13 +328,13 @@ strptr (DSO *dso, int sec, off_t offset)
+ REL *relptr, *relend;
+ int reltype;
+ 
+-#define do_read_32_relocated(ptr) ({			\
+-  uint32_t dret = do_read_32 (ptr);			\
++#define do_read_32_relocated(xptr) ({			\
++  uint32_t dret = do_read_32 (xptr);			\
+   if (relptr)						\
+     {							\
+-      while (relptr < relend && relptr->ptr < ptr)	\
++      while (relptr < relend && relptr->ptr < (xptr))	\
+ 	++relptr;					\
+-      if (relptr < relend && relptr->ptr == ptr)	\
++      if (relptr < relend && relptr->ptr == (xptr))	\
+ 	{						\
+ 	  if (reltype == SHT_REL)			\
+ 	    dret += relptr->addend;			\
+-- 
+2.18.4
+
diff --git a/SOURCES/0001-find-debuginfo.sh-decompress-DWARF-compressed-ELF-se.patch b/SOURCES/0001-find-debuginfo.sh-decompress-DWARF-compressed-ELF-se.patch
new file mode 100644
index 0000000..ee4b7cf
--- /dev/null
+++ b/SOURCES/0001-find-debuginfo.sh-decompress-DWARF-compressed-ELF-se.patch
@@ -0,0 +1,30 @@
+From f2bc669cd0a080792522dd1bb7f50ef7025f16f0 Mon Sep 17 00:00:00 2001
+From: Mark Wielaard <mark@klomp.org>
+Date: Sat, 21 Jul 2018 10:13:04 +0200
+Subject: [PATCH] find-debuginfo.sh: decompress DWARF compressed ELF sections
+
+debugedit and dwz do not support DWARF compressed ELF sections, let's
+just decompress those before extracting debuginfo.
+
+Tested-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
+---
+ scripts/find-debuginfo.sh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh
+index 90a44942d..7b01bc036 100755
+--- a/scripts/find-debuginfo.sh
++++ b/scripts/find-debuginfo.sh
+@@ -357,6 +357,9 @@ do_file()
+   get_debugfn "$f"
+   [ -f "${debugfn}" ] && return
+ 
++  echo "explicitly decompress any DWARF compressed ELF sections in $f"
++  eu-elfcompress -q -p -t none "$f"
++
+   echo "extracting debug info from $f"
+   # See also cpio SOURCEFILE copy. Directories must match up.
+   debug_base_name="$RPM_BUILD_DIR"
+-- 
+2.18.0
+
diff --git a/SOURCES/0002-NFC-debugedit-Move-code-from-edit_dwarf2-to-edit_inf.patch b/SOURCES/0002-NFC-debugedit-Move-code-from-edit_dwarf2-to-edit_inf.patch
new file mode 100644
index 0000000..74c37f7
--- /dev/null
+++ b/SOURCES/0002-NFC-debugedit-Move-code-from-edit_dwarf2-to-edit_inf.patch
@@ -0,0 +1,753 @@
+From de119ea9797f3ccfa3842e3926b6ea8198607207 Mon Sep 17 00:00:00 2001
+From: Jan Kratochvil <jan.kratochvil@redhat.com>
+Date: Sat, 1 Aug 2020 10:43:12 +0200
+Subject: [PATCH 2/6] [NFC] debugedit: Move code from edit_dwarf2() to
+ edit_info().
+
+---
+ tools/debugedit.c | 672 +++++++++++++++++++++++-----------------------
+ 1 file changed, 343 insertions(+), 329 deletions(-)
+
+diff --git a/tools/debugedit.c b/tools/debugedit.c
+index a351adec8..cad0cc349 100644
+--- a/tools/debugedit.c
++++ b/tools/debugedit.c
+@@ -1964,6 +1964,106 @@ line_rel_cmp (const void *a, const void *b)
+   return 0;
+ }
+ 
++static int
++edit_info (DSO *dso, int phase)
++{
++  unsigned char *ptr, *endcu, *endsec;
++  uint32_t value;
++  htab_t abbrev;
++  struct abbrev_tag tag, *t;
++
++  ptr = debug_sections[DEBUG_INFO].data;
++  setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
++  endsec = ptr + debug_sections[DEBUG_INFO].size;
++  while (ptr < endsec)
++    {
++      if (ptr + 11 > endsec)
++	{
++	  error (0, 0, "%s: .debug_info CU header too small",
++		 dso->filename);
++	  return 1;
++	}
++
++      endcu = ptr + 4;
++      endcu += read_32 (ptr);
++      if (endcu == ptr + 0xffffffff)
++	{
++	  error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
++	  return 1;
++	}
++
++      if (endcu > endsec)
++	{
++	  error (0, 0, "%s: .debug_info too small", dso->filename);
++	  return 1;
++	}
++
++      cu_version = read_16 (ptr);
++      if (cu_version != 2 && cu_version != 3 && cu_version != 4)
++	{
++	  error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
++		 cu_version);
++	  return 1;
++	}
++
++      value = read_32_relocated (ptr);
++      if (value >= debug_sections[DEBUG_ABBREV].size)
++	{
++	  if (debug_sections[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",
++		   dso->filename);
++	  return 1;
++	}
++
++      if (ptr_size == 0)
++	{
++	  ptr_size = read_8 (ptr);
++	  if (ptr_size != 4 && ptr_size != 8)
++	    {
++	      error (0, 0, "%s: Invalid DWARF pointer size %d",
++		     dso->filename, ptr_size);
++	      return 1;
++	    }
++	}
++      else if (read_8 (ptr) != ptr_size)
++	{
++	  error (0, 0, "%s: DWARF pointer size differs between CUs",
++		 dso->filename);
++	  return 1;
++	}
++
++      abbrev = read_abbrev (dso,
++			    debug_sections[DEBUG_ABBREV].data + value);
++      if (abbrev == NULL)
++	return 1;
++
++      while (ptr < endcu)
++	{
++	  tag.entry = read_uleb128 (ptr);
++	  if (tag.entry == 0)
++	    continue;
++	  t = htab_find_with_hash (abbrev, &tag, tag.entry);
++	  if (t == NULL)
++	    {
++	      error (0, 0, "%s: Could not find DWARF abbreviation %d",
++		     dso->filename, tag.entry);
++	      htab_delete (abbrev);
++	      return 1;
++	    }
++
++	  ptr = edit_attributes (dso, ptr, t, phase);
++	  if (ptr == NULL)
++	    break;
++	}
++
++      htab_delete (abbrev);
++    }
++
++  return 0;
++}
++
+ static int
+ edit_dwarf2 (DSO *dso)
+ {
+@@ -2100,385 +2200,299 @@ edit_dwarf2 (DSO *dso)
+       return 1;
+     }
+ 
+-  if (debug_sections[DEBUG_INFO].data != NULL)
++  if (debug_sections[DEBUG_INFO].data == NULL)
++    return 0;
++
++  unsigned char *ptr, *endcu, *endsec;
++  uint32_t value;
++  htab_t abbrev;
++  struct abbrev_tag tag, *t;
++  int phase;
++  bool info_rel_updated = false;
++  bool macro_rel_updated = false;
++
++  for (phase = 0; phase < 2; phase++)
+     {
+-      unsigned char *ptr, *endcu, *endsec;
+-      uint32_t value;
+-      htab_t abbrev;
+-      struct abbrev_tag tag, *t;
+-      int phase;
+-      bool info_rel_updated = false;
+-      bool macro_rel_updated = false;
++      /* If we don't need to update anyhing, skip phase 1. */
++      if (phase == 1
++	  && !need_strp_update
++	  && !need_string_replacement
++	  && !need_stmt_update)
++	break;
+ 
+-      for (phase = 0; phase < 2; phase++)
++      rel_updated = false;
++      if (edit_info (dso, phase))
++       return 1;
++
++      /* Remember whether any .debug_info relocations might need
++	 to be updated. */
++      info_rel_updated = rel_updated;
++
++      /* We might have to recalculate/rewrite the debug_line
++	 section.  We need to do that before going into phase one
++	 so we have all new offsets.  We do this separately from
++	 scanning the dirs/file names because the DW_AT_stmt_lists
++	 might not be in order or skip some padding we might have
++	 to (re)move. */
++      if (phase == 0 && need_stmt_update)
+ 	{
+-	  /* If we don't need to update anyhing, skip phase 1. */
+-	  if (phase == 1
+-	      && !need_strp_update
+-	      && !need_string_replacement
+-	      && !need_stmt_update)
+-	    break;
++	  edit_dwarf2_line (dso);
+ 
+-	  ptr = debug_sections[DEBUG_INFO].data;
+-	  setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
+-	  rel_updated = false;
+-	  endsec = ptr + debug_sections[DEBUG_INFO].size;
+-	  while (ptr < endsec)
++	  /* The line table programs will be moved
++	     forward/backwards a bit in the new data. Update the
++	     debug_line relocations to the new offsets. */
++	  int rndx = debug_sections[DEBUG_LINE].relsec;
++	  if (rndx != 0)
+ 	    {
+-	      if (ptr + 11 > endsec)
+-		{
+-		  error (0, 0, "%s: .debug_info CU header too small",
+-			 dso->filename);
+-		  return 1;
+-		}
+-
+-	      endcu = ptr + 4;
+-	      endcu += read_32 (ptr);
+-	      if (endcu == ptr + 0xffffffff)
+-		{
+-		  error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
+-		  return 1;
+-		}
+-
+-	      if (endcu > endsec)
+-		{
+-		  error (0, 0, "%s: .debug_info too small", dso->filename);
+-		  return 1;
+-		}
+-
+-	      cu_version = read_16 (ptr);
+-	      if (cu_version != 2 && cu_version != 3 && cu_version != 4)
+-		{
+-		  error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
+-			 cu_version);
+-		  return 1;
+-		}
+-
+-	      value = read_32_relocated (ptr);
+-	      if (value >= debug_sections[DEBUG_ABBREV].size)
++	      LINE_REL *rbuf;
++	      size_t rels;
++	      Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL);
++	      int rtype = dso->shdr[rndx].sh_type;
++	      rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize;
++	      rbuf = malloc (rels * sizeof (LINE_REL));
++	      if (rbuf == NULL)
++		error (1, errno, "%s: Could not allocate line relocations",
++		       dso->filename);
++
++	      /* Sort them by offset into section. */
++	      for (size_t i = 0; i < rels; i++)
+ 		{
+-		  if (debug_sections[DEBUG_ABBREV].data == NULL)
+-		    error (0, 0, "%s: .debug_abbrev not present", dso->filename);
++		  if (rtype == SHT_RELA)
++		    {
++		      GElf_Rela rela;
++		      if (gelf_getrela (rdata, i, &rela) == NULL)
++			error (1, 0, "Couldn't get relocation: %s",
++			       elf_errmsg (-1));
++		      rbuf[i].r_offset = rela.r_offset;
++		      rbuf[i].ndx = i;
++		    }
+ 		  else
+-		    error (0, 0, "%s: DWARF CU abbrev offset too large",
+-			   dso->filename);
+-		  return 1;
+-		}
+-
+-	      if (ptr_size == 0)
+-		{
+-		  ptr_size = read_8 (ptr);
+-		  if (ptr_size != 4 && ptr_size != 8)
+ 		    {
+-		      error (0, 0, "%s: Invalid DWARF pointer size %d",
+-			     dso->filename, ptr_size);
+-		      return 1;
++		      GElf_Rel rel;
++		      if (gelf_getrel (rdata, i, &rel) == NULL)
++			error (1, 0, "Couldn't get relocation: %s",
++			       elf_errmsg (-1));
++		      rbuf[i].r_offset = rel.r_offset;
++		      rbuf[i].ndx = i;
+ 		    }
+ 		}
+-	      else if (read_8 (ptr) != ptr_size)
+-		{
+-		  error (0, 0, "%s: DWARF pointer size differs between CUs",
+-			 dso->filename);
+-		  return 1;
+-		}
++	      qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp);
+ 
+-	      abbrev = read_abbrev (dso,
+-				    debug_sections[DEBUG_ABBREV].data + value);
+-	      if (abbrev == NULL)
+-		return 1;
+-
+-	      while (ptr < endcu)
++	      size_t lndx = 0;
++	      for (size_t i = 0; i < rels; i++)
+ 		{
+-		  tag.entry = read_uleb128 (ptr);
+-		  if (tag.entry == 0)
+-		    continue;
+-		  t = htab_find_with_hash (abbrev, &tag, tag.entry);
+-		  if (t == NULL)
++		  /* These relocations only happen in ET_REL files
++		     and are section offsets. */
++		  GElf_Addr r_offset;
++		  size_t ndx = rbuf[i].ndx;
++
++		  GElf_Rel rel;
++		  GElf_Rela rela;
++		  if (rtype == SHT_RELA)
+ 		    {
+-		      error (0, 0, "%s: Could not find DWARF abbreviation %d",
+-			     dso->filename, tag.entry);
+-		      htab_delete (abbrev);
+-		      return 1;
++		      if (gelf_getrela (rdata, ndx, &rela) == NULL)
++			error (1, 0, "Couldn't get relocation: %s",
++			       elf_errmsg (-1));
++		      r_offset = rela.r_offset;
++		    }
++		  else
++		    {
++		      if (gelf_getrel (rdata, ndx, &rel) == NULL)
++			error (1, 0, "Couldn't get relocation: %s",
++			       elf_errmsg (-1));
++		      r_offset = rel.r_offset;
+ 		    }
+ 
+-		  ptr = edit_attributes (dso, ptr, t, phase);
+-		  if (ptr == NULL)
+-		    break;
+-		}
++		  while (lndx < dso->lines.used
++			 && r_offset > (dso->lines.table[lndx].old_idx
++					+ 4
++					+ dso->lines.table[lndx].unit_length))
++		    lndx++;
+ 
+-	      htab_delete (abbrev);
+-	    }
++		  if (lndx >= dso->lines.used)
++		    error (1, 0,
++			   ".debug_line relocation offset out of range");
+ 
+-	  /* Remember whether any .debug_info relocations might need
+-	     to be updated. */
+-	  info_rel_updated = rel_updated;
+-
+-	  /* We might have to recalculate/rewrite the debug_line
+-	     section.  We need to do that before going into phase one
+-	     so we have all new offsets.  We do this separately from
+-	     scanning the dirs/file names because the DW_AT_stmt_lists
+-	     might not be in order or skip some padding we might have
+-	     to (re)move. */
+-	  if (phase == 0 && need_stmt_update)
+-	    {
+-	      edit_dwarf2_line (dso);
++		  /* Offset (pointing into the line program) moves
++		     from old to new index including the header
++		     size diff. */
++		  r_offset += (ssize_t)((dso->lines.table[lndx].new_idx
++					 - dso->lines.table[lndx].old_idx)
++					+ dso->lines.table[lndx].size_diff);
+ 
+-	      /* The line table programs will be moved
+-		 forward/backwards a bit in the new data. Update the
+-		 debug_line relocations to the new offsets. */
+-	      int rndx = debug_sections[DEBUG_LINE].relsec;
+-	      if (rndx != 0)
+-		{
+-		  LINE_REL *rbuf;
+-		  size_t rels;
+-		  Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL);
+-		  int rtype = dso->shdr[rndx].sh_type;
+-		  rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize;
+-		  rbuf = malloc (rels * sizeof (LINE_REL));
+-		  if (rbuf == NULL)
+-		    error (1, errno, "%s: Could not allocate line relocations",
+-			   dso->filename);
+-
+-		  /* Sort them by offset into section. */
+-		  for (size_t i = 0; i < rels; i++)
++		  if (rtype == SHT_RELA)
+ 		    {
+-		      if (rtype == SHT_RELA)
+-			{
+-			  GElf_Rela rela;
+-			  if (gelf_getrela (rdata, i, &rela) == NULL)
+-			    error (1, 0, "Couldn't get relocation: %s",
+-				   elf_errmsg (-1));
+-			  rbuf[i].r_offset = rela.r_offset;
+-			  rbuf[i].ndx = i;
+-			}
+-		      else
+-			{
+-			  GElf_Rel rel;
+-			  if (gelf_getrel (rdata, i, &rel) == NULL)
+-			    error (1, 0, "Couldn't get relocation: %s",
+-				   elf_errmsg (-1));
+-			  rbuf[i].r_offset = rel.r_offset;
+-			  rbuf[i].ndx = i;
+-			}
++		      rela.r_offset = r_offset;
++		      if (gelf_update_rela (rdata, ndx, &rela) == 0)
++			error (1, 0, "Couldn't update relocation: %s",
++			       elf_errmsg (-1));
+ 		    }
+-		  qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp);
+-
+-		  size_t lndx = 0;
+-		  for (size_t i = 0; i < rels; i++)
++		  else
+ 		    {
+-		      /* These relocations only happen in ET_REL files
+-			 and are section offsets. */
+-		      GElf_Addr r_offset;
+-		      size_t ndx = rbuf[i].ndx;
+-
+-		      GElf_Rel rel;
+-		      GElf_Rela rela;
+-		      if (rtype == SHT_RELA)
+-			{
+-			  if (gelf_getrela (rdata, ndx, &rela) == NULL)
+-			    error (1, 0, "Couldn't get relocation: %s",
+-				   elf_errmsg (-1));
+-			  r_offset = rela.r_offset;
+-			}
+-		      else
+-			{
+-			  if (gelf_getrel (rdata, ndx, &rel) == NULL)
+-			    error (1, 0, "Couldn't get relocation: %s",
+-				   elf_errmsg (-1));
+-			  r_offset = rel.r_offset;
+-			}
+-
+-		      while (lndx < dso->lines.used
+-			     && r_offset > (dso->lines.table[lndx].old_idx
+-					    + 4
+-					    + dso->lines.table[lndx].unit_length))
+-			lndx++;
+-
+-		      if (lndx >= dso->lines.used)
+-			error (1, 0,
+-			       ".debug_line relocation offset out of range");
+-
+-		      /* Offset (pointing into the line program) moves
+-			 from old to new index including the header
+-			 size diff. */
+-		      r_offset += (ssize_t)((dso->lines.table[lndx].new_idx
+-					     - dso->lines.table[lndx].old_idx)
+-					    + dso->lines.table[lndx].size_diff);
+-
+-		      if (rtype == SHT_RELA)
+-			{
+-			  rela.r_offset = r_offset;
+-			  if (gelf_update_rela (rdata, ndx, &rela) == 0)
+-			    error (1, 0, "Couldn't update relocation: %s",
+-				   elf_errmsg (-1));
+-			}
+-		      else
+-			{
+-			  rel.r_offset = r_offset;
+-			  if (gelf_update_rel (rdata, ndx, &rel) == 0)
+-			    error (1, 0, "Couldn't update relocation: %s",
+-				   elf_errmsg (-1));
+-			}
++		      rel.r_offset = r_offset;
++		      if (gelf_update_rel (rdata, ndx, &rel) == 0)
++			error (1, 0, "Couldn't update relocation: %s",
++			       elf_errmsg (-1));
+ 		    }
+-
+-		  elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY);
+-		  free (rbuf);
+ 		}
++
++	      elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY);
++	      free (rbuf);
+ 	    }
++	}
+ 
+-	  /* The .debug_macro section also contains offsets into the
+-	     .debug_str section and references to the .debug_line
+-	     tables, so we need to update those as well if we update
+-	     the strings or the stmts.  */
+-	  if ((need_strp_update || need_stmt_update)
+-	      && debug_sections[DEBUG_MACRO].data)
++      /* The .debug_macro section also contains offsets into the
++	 .debug_str section and references to the .debug_line
++	 tables, so we need to update those as well if we update
++	 the strings or the stmts.  */
++      if ((need_strp_update || need_stmt_update)
++	  && debug_sections[DEBUG_MACRO].data)
++	{
++	  /* There might be multiple (COMDAT) .debug_macro sections.  */
++	  struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
++	  while (macro_sec != NULL)
+ 	    {
+-	      /* There might be multiple (COMDAT) .debug_macro sections.  */
+-	      struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
+-	      while (macro_sec != NULL)
+-		{
+-		  setup_relbuf(dso, macro_sec, &reltype);
+-		  rel_updated = false;
++	      setup_relbuf(dso, macro_sec, &reltype);
++	      rel_updated = false;
+ 
+-		  ptr = macro_sec->data;
+-		  endsec = ptr + macro_sec->size;
+-		  int op = 0, macro_version, macro_flags;
+-		  int offset_len = 4, line_offset = 0;
++	      ptr = macro_sec->data;
++	      endsec = ptr + macro_sec->size;
++	      int op = 0, macro_version, macro_flags;
++	      int offset_len = 4, line_offset = 0;
+ 
+-		  while (ptr < endsec)
++	      while (ptr < endsec)
++		{
++		  if (!op)
+ 		    {
+-		      if (!op)
+-			{
+-			  macro_version = read_16 (ptr);
+-			  macro_flags = read_8 (ptr);
+-			  if (macro_version < 4 || macro_version > 5)
+-			    error (1, 0, "unhandled .debug_macro version: %d",
+-				   macro_version);
+-			  if ((macro_flags & ~2) != 0)
+-			    error (1, 0, "unhandled .debug_macro flags: 0x%x",
+-				   macro_flags);
+-
+-			  offset_len = (macro_flags & 0x01) ? 8 : 4;
+-			  line_offset = (macro_flags & 0x02) ? 1 : 0;
+-
+-			  if (offset_len != 4)
+-			    error (0, 1,
+-				   "Cannot handle 8 byte macro offsets: %s",
+-				   dso->filename);
+-
+-			  /* Update the line_offset if it is there.  */
+-			  if (line_offset)
+-			    {
+-			      if (phase == 0)
+-				ptr += offset_len;
+-			      else
+-				{
+-				  size_t idx, new_idx;
+-				  idx = do_read_32_relocated (ptr);
+-				  new_idx = find_new_list_offs (&dso->lines,
+-								idx);
+-				  write_32_relocated (ptr, new_idx);
+-				}
+-			    }
+-			}
++		      macro_version = read_16 (ptr);
++		      macro_flags = read_8 (ptr);
++		      if (macro_version < 4 || macro_version > 5)
++			error (1, 0, "unhandled .debug_macro version: %d",
++			       macro_version);
++		      if ((macro_flags & ~2) != 0)
++			error (1, 0, "unhandled .debug_macro flags: 0x%x",
++			       macro_flags);
++
++		      offset_len = (macro_flags & 0x01) ? 8 : 4;
++		      line_offset = (macro_flags & 0x02) ? 1 : 0;
++
++		      if (offset_len != 4)
++			error (0, 1,
++			       "Cannot handle 8 byte macro offsets: %s",
++			       dso->filename);
+ 
+-		      op = read_8 (ptr);
+-		      if (!op)
+-			continue;
+-		      switch(op)
++		      /* Update the line_offset if it is there.  */
++		      if (line_offset)
+ 			{
+-			case DW_MACRO_GNU_define:
+-			case DW_MACRO_GNU_undef:
+-			  read_uleb128 (ptr);
+-			  ptr = ((unsigned char *) strchr ((char *) ptr, '\0')
+-				 + 1);
+-			  break;
+-			case DW_MACRO_GNU_start_file:
+-			  read_uleb128 (ptr);
+-			  read_uleb128 (ptr);
+-			  break;
+-			case DW_MACRO_GNU_end_file:
+-			  break;
+-			case DW_MACRO_GNU_define_indirect:
+-			case DW_MACRO_GNU_undef_indirect:
+-			  read_uleb128 (ptr);
+ 			  if (phase == 0)
+-			    {
+-			      size_t idx = read_32_relocated (ptr);
+-			      record_existing_string_entry_idx (&dso->strings,
+-								idx);
+-			    }
++			    ptr += offset_len;
+ 			  else
+ 			    {
+-			      struct stridxentry *entry;
+ 			      size_t idx, new_idx;
+ 			      idx = do_read_32_relocated (ptr);
+-			      entry = string_find_entry (&dso->strings, idx);
+-			      new_idx = strent_offset (entry->entry);
++			      new_idx = find_new_list_offs (&dso->lines,
++							    idx);
+ 			      write_32_relocated (ptr, new_idx);
+ 			    }
+-			  break;
+-			case DW_MACRO_GNU_transparent_include:
+-			  ptr += offset_len;
+-			  break;
+-			default:
+-			  error (1, 0, "Unhandled DW_MACRO op 0x%x", op);
+-			  break;
+ 			}
+ 		    }
+ 
+-		  if (rel_updated)
+-		    macro_rel_updated = true;
+-		  macro_sec = macro_sec->next;
++		  op = read_8 (ptr);
++		  if (!op)
++		    continue;
++		  switch(op)
++		    {
++		    case DW_MACRO_GNU_define:
++		    case DW_MACRO_GNU_undef:
++		      read_uleb128 (ptr);
++		      ptr = ((unsigned char *) strchr ((char *) ptr, '\0')
++			     + 1);
++		      break;
++		    case DW_MACRO_GNU_start_file:
++		      read_uleb128 (ptr);
++		      read_uleb128 (ptr);
++		      break;
++		    case DW_MACRO_GNU_end_file:
++		      break;
++		    case DW_MACRO_GNU_define_indirect:
++		    case DW_MACRO_GNU_undef_indirect:
++		      read_uleb128 (ptr);
++		      if (phase == 0)
++			{
++			  size_t idx = read_32_relocated (ptr);
++			  record_existing_string_entry_idx (&dso->strings,
++							    idx);
++			}
++		      else
++			{
++			  struct stridxentry *entry;
++			  size_t idx, new_idx;
++			  idx = do_read_32_relocated (ptr);
++			  entry = string_find_entry (&dso->strings, idx);
++			  new_idx = strent_offset (entry->entry);
++			  write_32_relocated (ptr, new_idx);
++			}
++		      break;
++		    case DW_MACRO_GNU_transparent_include:
++		      ptr += offset_len;
++		      break;
++		    default:
++		      error (1, 0, "Unhandled DW_MACRO op 0x%x", op);
++		      break;
++		    }
+ 		}
+-	    }
+ 
+-	  /* Same for the debug_str section. Make sure everything is
+-	     in place for phase 1 updating of debug_info
+-	     references. */
+-	  if (phase == 0 && need_strp_update)
+-	    {
+-	      Strtab *strtab = dso->strings.str_tab;
+-	      Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
+-	      int strndx = debug_sections[DEBUG_STR].sec;
+-	      Elf_Scn *strscn = dso->scn[strndx];
+-
+-	      /* Out with the old. */
+-	      strdata->d_size = 0;
+-	      /* In with the new. */
+-	      strdata = elf_newdata (strscn);
+-
+-	      /* We really should check whether we had enough memory,
+-		 but the old ebl version will just abort on out of
+-		 memory... */
+-	      strtab_finalize (strtab, strdata);
+-	      debug_sections[DEBUG_STR].size = strdata->d_size;
+-	      dso->strings.str_buf = strdata->d_buf;
++	      if (rel_updated)
++		macro_rel_updated = true;
++	      macro_sec = macro_sec->next;
+ 	    }
++	}
+ 
++      /* Same for the debug_str section. Make sure everything is
++	 in place for phase 1 updating of debug_info
++	 references. */
++      if (phase == 0 && need_strp_update)
++	{
++	  Strtab *strtab = dso->strings.str_tab;
++	  Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
++	  int strndx = debug_sections[DEBUG_STR].sec;
++	  Elf_Scn *strscn = dso->scn[strndx];
++
++	  /* Out with the old. */
++	  strdata->d_size = 0;
++	  /* In with the new. */
++	  strdata = elf_newdata (strscn);
++
++	  /* We really should check whether we had enough memory,
++	     but the old ebl version will just abort on out of
++	     memory... */
++	  strtab_finalize (strtab, strdata);
++	  debug_sections[DEBUG_STR].size = strdata->d_size;
++	  dso->strings.str_buf = strdata->d_buf;
+ 	}
+ 
+-      /* After phase 1 we might have rewritten the debug_info with
+-	 new strp, strings and/or linep offsets.  */
+-      if (need_strp_update || need_string_replacement || need_stmt_update)
+-	dirty_section (DEBUG_INFO);
+-      if (need_strp_update || need_stmt_update)
+-	dirty_section (DEBUG_MACRO);
+-      if (need_stmt_update)
+-	dirty_section (DEBUG_LINE);
++    }
++
++  /* After phase 1 we might have rewritten the debug_info with
++     new strp, strings and/or linep offsets.  */
++  if (need_strp_update || need_string_replacement || need_stmt_update)
++    dirty_section (DEBUG_INFO);
++  if (need_strp_update || need_stmt_update)
++    dirty_section (DEBUG_MACRO);
++  if (need_stmt_update)
++    dirty_section (DEBUG_LINE);
+ 
+-      /* Update any relocations addends we might have touched. */
+-      if (info_rel_updated)
+-	update_rela_data (dso, &debug_sections[DEBUG_INFO]);
++  /* Update any relocations addends we might have touched. */
++  if (info_rel_updated)
++    update_rela_data (dso, &debug_sections[DEBUG_INFO]);
+ 
+-      if (macro_rel_updated)
++  if (macro_rel_updated)
++    {
++      struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
++      while (macro_sec != NULL)
+ 	{
+-	  struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
+-	  while (macro_sec != NULL)
+-	    {
+-	      update_rela_data (dso, macro_sec);
+-	      macro_sec = macro_sec->next;
+-	    }
++	  update_rela_data (dso, macro_sec);
++	  macro_sec = macro_sec->next;
+ 	}
+     }
+ 
+-- 
+2.18.4
+
diff --git a/SOURCES/0003-debugedit-Fix-missing-relocation-of-.debug_types-sec.patch b/SOURCES/0003-debugedit-Fix-missing-relocation-of-.debug_types-sec.patch
new file mode 100644
index 0000000..dd4abb1
--- /dev/null
+++ b/SOURCES/0003-debugedit-Fix-missing-relocation-of-.debug_types-sec.patch
@@ -0,0 +1,269 @@
+From 8cd4d5046d7cb1bc16f01e77a5ff50eca8d9da3d Mon Sep 17 00:00:00 2001
+From: Jan Kratochvil <jan.kratochvil@redhat.com>
+Date: Sat, 1 Aug 2020 10:45:47 +0200
+Subject: [PATCH 3/6] debugedit: Fix missing relocation of .debug_types
+ section.
+
+---
+ tools/debugedit.c | 123 ++++++++++++++++++++++++++++++----------------
+ 1 file changed, 80 insertions(+), 43 deletions(-)
+
+diff --git a/tools/debugedit.c b/tools/debugedit.c
+index cad0cc349..87c1cd622 100644
+--- a/tools/debugedit.c
++++ b/tools/debugedit.c
+@@ -433,7 +433,8 @@ typedef struct debug_section
+     int sec, relsec;
+     REL *relbuf;
+     REL *relend;
+-    struct debug_section *next; /* Only happens for COMDAT .debug_macro.  */
++    /* Only happens for COMDAT .debug_macro and .debug_types.  */
++    struct debug_section *next;
+   } debug_section;
+ 
+ static debug_section debug_sections[] =
+@@ -1269,7 +1270,9 @@ static int dirty_elf;
+ static void
+ dirty_section (unsigned int sec)
+ {
+-  elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY);
++  for (struct debug_section *secp = &debug_sections[sec]; secp != NULL;
++       secp = secp->next)
++    elf_flagdata (secp->elf_data, ELF_C_SET, ELF_F_DIRTY);
+   dirty_elf = 1;
+ }
+ 
+@@ -1469,12 +1472,7 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
+ 
+   if (get_line_table (dso, off, &table) == false
+       || table == NULL)
+-    {
+-      if (table != NULL)
+-	error (0, 0, ".debug_line offset 0x%x referenced multiple times",
+-	       off);
+-      return false;
+-    }
++    return false;
+ 
+   /* Skip to the directory table. The rest of the header has already
+      been read and checked by get_line_table. */
+@@ -1965,22 +1963,25 @@ line_rel_cmp (const void *a, const void *b)
+ }
+ 
+ static int
+-edit_info (DSO *dso, int phase)
++edit_info (DSO *dso, int phase, struct debug_section *sec)
+ {
+   unsigned char *ptr, *endcu, *endsec;
+   uint32_t value;
+   htab_t abbrev;
+   struct abbrev_tag tag, *t;
+ 
+-  ptr = debug_sections[DEBUG_INFO].data;
+-  setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
+-  endsec = ptr + debug_sections[DEBUG_INFO].size;
++  ptr = sec->data;
++  if (ptr == NULL)
++    return 0;
++
++  setup_relbuf(dso, sec, &reltype);
++  endsec = ptr + sec->size;
+   while (ptr < endsec)
+     {
+-      if (ptr + 11 > endsec)
++      if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec)
+ 	{
+-	  error (0, 0, "%s: .debug_info CU header too small",
+-		 dso->filename);
++	  error (0, 0, "%s: %s CU header too small",
++		 dso->filename, sec->name);
+ 	  return 1;
+ 	}
+ 
+@@ -1994,7 +1995,7 @@ edit_info (DSO *dso, int phase)
+ 
+       if (endcu > endsec)
+ 	{
+-	  error (0, 0, "%s: .debug_info too small", dso->filename);
++	  error (0, 0, "%s: %s too small", dso->filename, sec->name);
+ 	  return 1;
+ 	}
+ 
+@@ -2034,6 +2035,9 @@ edit_info (DSO *dso, int phase)
+ 	  return 1;
+ 	}
+ 
++      if (sec != &debug_sections[DEBUG_INFO])
++	ptr += 12; /* Skip type_signature and type_offset.  */
++
+       abbrev = read_abbrev (dso,
+ 			    debug_sections[DEBUG_ABBREV].data + value);
+       if (abbrev == NULL)
+@@ -2095,7 +2099,7 @@ edit_dwarf2 (DSO *dso)
+ 		  struct debug_section *debug_sec = &debug_sections[j];
+ 		  if (debug_sections[j].data)
+ 		    {
+-		      if (j != DEBUG_MACRO)
++		      if (j != DEBUG_MACRO && j != DEBUG_TYPES)
+ 			{
+ 			  error (0, 0, "%s: Found two copies of %s section",
+ 				 dso->filename, name);
+@@ -2103,22 +2107,21 @@ edit_dwarf2 (DSO *dso)
+ 			}
+ 		      else
+ 			{
+-			  /* In relocatable files .debug_macro might
+-			     appear multiple times as COMDAT
+-			     section.  */
++			  /* In relocatable files .debug_macro and .debug_types
++			     might appear multiple times as COMDAT section.  */
+ 			  struct debug_section *sec;
+ 			  sec = calloc (sizeof (struct debug_section), 1);
+ 			  if (sec == NULL)
+ 			    error (1, errno,
+-				   "%s: Could not allocate more macro sections",
+-				   dso->filename);
+-			  sec->name = ".debug_macro";
++				   "%s: Could not allocate more %s sections",
++				   dso->filename, name);
++			  sec->name = name;
+ 
+-			  struct debug_section *macro_sec = debug_sec;
+-			  while (macro_sec->next != NULL)
+-			    macro_sec = macro_sec->next;
++			  struct debug_section *multi_sec = debug_sec;
++			  while (multi_sec->next != NULL)
++			    multi_sec = multi_sec->next;
+ 
+-			  macro_sec->next = sec;
++			  multi_sec->next = sec;
+ 			  debug_sec = sec;
+ 			}
+ 		    }
+@@ -2155,23 +2158,23 @@ edit_dwarf2 (DSO *dso)
+ 			  + (dso->shdr[i].sh_type == SHT_RELA),
+ 			  debug_sections[j].name) == 0)
+ 	 	{
+-		  if (j == DEBUG_MACRO)
++		  if (j == DEBUG_MACRO || j == DEBUG_TYPES)
+ 		    {
+ 		      /* Pick the correct one.  */
+ 		      int rel_target = dso->shdr[i].sh_info;
+-		      struct debug_section *macro_sec = &debug_sections[j];
+-		      while (macro_sec != NULL)
++		      struct debug_section *multi_sec = &debug_sections[j];
++		      while (multi_sec != NULL)
+ 			{
+-			  if (macro_sec->sec == rel_target)
++			  if (multi_sec->sec == rel_target)
+ 			    {
+-			      macro_sec->relsec = i;
++			      multi_sec->relsec = i;
+ 			      break;
+ 			    }
+-			  macro_sec = macro_sec->next;
++			  multi_sec = multi_sec->next;
+ 			}
+-		      if (macro_sec == NULL)
+-			error (0, 1, "No .debug_macro reloc section: %s",
+-			       dso->filename);
++		      if (multi_sec == NULL)
++			error (0, 1, "No %s reloc section: %s",
++			       debug_sections[j].name, dso->filename);
+ 		    }
+ 		  else
+ 		    debug_sections[j].relsec = i;
+@@ -2203,12 +2206,10 @@ edit_dwarf2 (DSO *dso)
+   if (debug_sections[DEBUG_INFO].data == NULL)
+     return 0;
+ 
+-  unsigned char *ptr, *endcu, *endsec;
+-  uint32_t value;
+-  htab_t abbrev;
+-  struct abbrev_tag tag, *t;
++  unsigned char *ptr, *endsec;
+   int phase;
+   bool info_rel_updated = false;
++  bool types_rel_updated = false;
+   bool macro_rel_updated = false;
+ 
+   for (phase = 0; phase < 2; phase++)
+@@ -2221,13 +2222,26 @@ edit_dwarf2 (DSO *dso)
+ 	break;
+ 
+       rel_updated = false;
+-      if (edit_info (dso, phase))
+-       return 1;
++      if (edit_info (dso, phase, &debug_sections[DEBUG_INFO]))
++	return 1;
+ 
+       /* Remember whether any .debug_info relocations might need
+ 	 to be updated. */
+       info_rel_updated = rel_updated;
+ 
++      rel_updated = false;
++      struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
++      while (types_sec != NULL)
++	{
++	  if (edit_info (dso, phase, types_sec))
++	    return 1;
++	  types_sec = types_sec->next;
++	}
++
++      /* Remember whether any .debug_types relocations might need
++	 to be updated. */
++      types_rel_updated = rel_updated;
++
+       /* We might have to recalculate/rewrite the debug_line
+ 	 section.  We need to do that before going into phase one
+ 	 so we have all new offsets.  We do this separately from
+@@ -2475,8 +2489,11 @@ edit_dwarf2 (DSO *dso)
+ 
+   /* After phase 1 we might have rewritten the debug_info with
+      new strp, strings and/or linep offsets.  */
+-  if (need_strp_update || need_string_replacement || need_stmt_update)
++  if (need_strp_update || need_string_replacement || need_stmt_update) {
+     dirty_section (DEBUG_INFO);
++    if (debug_sections[DEBUG_TYPES].data != NULL)
++      dirty_section (DEBUG_TYPES);
++  }
+   if (need_strp_update || need_stmt_update)
+     dirty_section (DEBUG_MACRO);
+   if (need_stmt_update)
+@@ -2485,6 +2502,15 @@ edit_dwarf2 (DSO *dso)
+   /* Update any relocations addends we might have touched. */
+   if (info_rel_updated)
+     update_rela_data (dso, &debug_sections[DEBUG_INFO]);
++  if (types_rel_updated)
++    {
++      struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
++      while (types_sec != NULL)
++	{
++	  update_rela_data (dso, types_sec);
++	  types_sec = types_sec->next;
++	}
++    }
+ 
+   if (macro_rel_updated)
+     {
+@@ -3037,6 +3063,17 @@ main (int argc, char *argv[])
+       macro_sec = next;
+     }
+ 
++  /* In case there were multiple (COMDAT) .debug_types sections,
++     free them.  */
++  struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
++  types_sec = types_sec->next;
++  while (types_sec != NULL)
++    {
++      struct debug_section *next = types_sec->next;
++      free (types_sec);
++      types_sec = next;
++    }
++
+   poptFreeContext (optCon);
+ 
+   return 0;
+-- 
+2.18.4
+
diff --git a/SOURCES/0004-NFC-debugedit-Move-code-to-separate-functions.patch b/SOURCES/0004-NFC-debugedit-Move-code-to-separate-functions.patch
new file mode 100644
index 0000000..5f13953
--- /dev/null
+++ b/SOURCES/0004-NFC-debugedit-Move-code-to-separate-functions.patch
@@ -0,0 +1,455 @@
+From bab443ab4f756ef80f814af0353143f41e90e6a6 Mon Sep 17 00:00:00 2001
+From: Jan Kratochvil <jan.kratochvil@redhat.com>
+Date: Mon, 17 Aug 2020 21:58:19 +0200
+Subject: [PATCH 4/6] [NFC] debugedit: Move code to separate functions.
+
+New functions edit_strp, skip_form and edit_attributes_str_comp_dir
+called by edit_attributes.
+Split part of read_dwarf2_line into a read_dwarf4_line function.
+New function edit_dwarf2_any_str called by edit_dwarf2 at the end of
+phase 0 to rebuild .debug_str.
+---
+ tools/debugedit.c | 367 ++++++++++++++++++++++++++--------------------
+ 1 file changed, 212 insertions(+), 155 deletions(-)
+
+diff --git a/tools/debugedit.c b/tools/debugedit.c
+index 87c1cd622..7464883c5 100644
+--- a/tools/debugedit.c
++++ b/tools/debugedit.c
+@@ -1457,37 +1457,128 @@ edit_dwarf2_line (DSO *dso)
+     }
+ }
+ 
+-/* Called during phase zero for each debug_line table referenced from
+-   .debug_info.  Outputs all source files seen and records any
+-   adjustments needed in the debug_list data structures. Returns true
+-   if line_table needs to be rewrite either the dir or file paths. */
++/* Record or adjust (according to phase) DW_FORM_strp.  */
++static void
++edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp)
++{
++  unsigned char *ptr_orig = ptr;
++
++  /* In the first pass we collect all strings, in the
++     second we put the new references back (if there are
++     any changes).  */
++  if (phase == 0)
++    {
++      /* handled_strp is set for attributes referring to
++	 files. If it is set the string is already
++	 recorded. */
++      if (! handled_strp)
++	{
++	  size_t idx = do_read_32_relocated (ptr);
++	  record_existing_string_entry_idx (&dso->strings, idx);
++	}
++    }
++  else if (need_strp_update) /* && phase == 1 */
++    {
++      struct stridxentry *entry;
++      size_t idx, new_idx;
++      idx = do_read_32_relocated (ptr);
++      entry = string_find_entry (&dso->strings, idx);
++      new_idx = strent_offset (entry->entry);
++      do_write_32_relocated (ptr, new_idx);
++    }
++
++  assert (ptr == ptr_orig);
++}
++
++/* Adjust *PTRP after the current *FORMP, update *FORMP for FORM_INDIRECT.  */
++static enum { FORM_OK, FORM_ERROR, FORM_INDIRECT }
++skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
++{
++  size_t len = 0;
++
++  switch (*formp)
++    {
++    case DW_FORM_ref_addr:
++      if (cu_version == 2)
++	*ptrp += ptr_size;
++      else
++	*ptrp += 4;
++      break;
++    case DW_FORM_flag_present:
++      break;
++    case DW_FORM_addr:
++      *ptrp += ptr_size;
++      break;
++    case DW_FORM_ref1:
++    case DW_FORM_flag:
++    case DW_FORM_data1:
++      ++*ptrp;
++      break;
++    case DW_FORM_ref2:
++    case DW_FORM_data2:
++      *ptrp += 2;
++      break;
++    case DW_FORM_ref4:
++    case DW_FORM_data4:
++    case DW_FORM_sec_offset:
++      *ptrp += 4;
++      break;
++    case DW_FORM_ref8:
++    case DW_FORM_data8:
++    case DW_FORM_ref_sig8:
++      *ptrp += 8;
++      break;
++    case DW_FORM_sdata:
++    case DW_FORM_ref_udata:
++    case DW_FORM_udata:
++      read_uleb128 (*ptrp);
++      break;
++    case DW_FORM_strp:
++      *ptrp += 4;
++      break;
++    case DW_FORM_string:
++      *ptrp = (unsigned char *) strchr ((char *)*ptrp, '\0') + 1;
++      break;
++    case DW_FORM_indirect:
++      *formp = read_uleb128 (*ptrp);
++      return FORM_INDIRECT;
++    case DW_FORM_block1:
++      len = *(*ptrp)++;
++      break;
++    case DW_FORM_block2:
++      len = read_16 (*ptrp);
++      *formp = DW_FORM_block1;
++      break;
++    case DW_FORM_block4:
++      len = read_32 (*ptrp);
++      *formp = DW_FORM_block1;
++      break;
++    case DW_FORM_block:
++    case DW_FORM_exprloc:
++      len = read_uleb128 (*ptrp);
++      *formp = DW_FORM_block1;
++      assert (len < UINT_MAX);
++      break;
++    default:
++      error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, *formp);
++      return FORM_ERROR;
++    }
++
++  if (*formp == DW_FORM_block1)
++    *ptrp += len;
++
++  return FORM_OK;
++}
++
++/* Part of read_dwarf2_line processing DWARF-4.  */
+ static bool
+-read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
++read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
++		  struct line_table *table)
+ {
+-  unsigned char *ptr, *dir;
+   unsigned char **dirt;
+   uint32_t value, dirt_cnt;
+   size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir);
+-  struct line_table *table;
+-
+-  if (get_line_table (dso, off, &table) == false
+-      || table == NULL)
+-    return false;
+-
+-  /* Skip to the directory table. The rest of the header has already
+-     been read and checked by get_line_table. */
+-  ptr = debug_sections[DEBUG_LINE].data + off;
+-  ptr += (4 /* unit len */
+-	  + 2 /* version */
+-	  + 4 /* header len */
+-	  + 1 /* min instr len */
+-	  + (table->version >= 4) /* max op per instr, if version >= 4 */
+-	  + 1 /* default is stmt */
+-	  + 1 /* line base */
+-	  + 1 /* line range */
+-	  + 1 /* opcode base */
+-	  + table->opcode_base - 1); /* opcode len table */
+-  dir = ptr;
++  unsigned char *dir = ptr;
+ 
+   /* dir table: */
+   value = 1;
+@@ -1620,6 +1711,40 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
+       read_uleb128 (ptr);
+     }
+ 
++  return true;
++}
++
++/* Called during phase zero for each debug_line table referenced from
++   .debug_info.  Outputs all source files seen and records any
++   adjustments needed in the debug_list data structures. Returns true
++   if line_table needs to be rewrite either the dir or file paths. */
++static bool
++read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
++{
++  unsigned char *ptr;
++  struct line_table *table;
++
++  if (get_line_table (dso, off, &table) == false
++      || table == NULL)
++    return false;
++
++  /* Skip to the directory table. The rest of the header has already
++     been read and checked by get_line_table. */
++  ptr = debug_sections[DEBUG_LINE].data + off;
++  ptr += (4 /* unit len */
++	  + 2 /* version */
++	  + 4 /* header len */
++	  + 1 /* min instr len */
++	  + (table->version >= 4) /* max op per instr, if version >= 4 */
++	  + 1 /* default is stmt */
++	  + 1 /* line base */
++	  + 1 /* line range */
++	  + 1 /* opcode base */
++	  + table->opcode_base - 1); /* opcode len table */
++
++  if (! read_dwarf4_line (dso, ptr, comp_dir, table))
++   return false;
++
+   dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff;
+   return table->replace_dirs || table->replace_files;
+ }
+@@ -1637,6 +1762,33 @@ find_new_list_offs (struct debug_lines *lines, size_t idx)
+   return table->new_idx;
+ }
+ 
++/* Read DW_FORM_strp collecting compilation directory.  */
++static void
++edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase,
++			      char **comp_dirp, bool *handled_strpp)
++{
++  const char *dir;
++  size_t idx = do_read_32_relocated (*ptrp);
++  /* In phase zero we collect the comp_dir.  */
++  if (phase == 0)
++    {
++      if (idx >= debug_sections[DEBUG_STR].size)
++	error (1, 0, "%s: Bad string pointer index %zd for comp_dir",
++	       dso->filename, idx);
++      dir = (char *) debug_sections[DEBUG_STR].data + idx;
++
++      free (*comp_dirp);
++      *comp_dirp = strdup (dir);
++    }
++
++  if (dest_dir != NULL && phase == 0)
++    {
++      if (record_file_string_entry_idx (&dso->strings, idx))
++	need_strp_update = true;
++      *handled_strpp = true;
++    }
++}
++
+ /* This scans the attributes of one DIE described by the given abbrev_tag.
+    PTR points to the data in the debug_info. It will be advanced till all
+    abbrev data is consumed. In phase zero data is collected, in phase one
+@@ -1655,7 +1807,6 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
+   for (i = 0; i < t->nattr; ++i)
+     {
+       uint32_t form = t->attr[i].form;
+-      size_t len = 0;
+       while (1)
+ 	{
+ 	  /* Whether we already handled a string as file for this
+@@ -1743,29 +1894,8 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
+ 		}
+ 	      else if (form == DW_FORM_strp &&
+ 		       debug_sections[DEBUG_STR].data)
+-		{
+-		  const char *dir;
+-		  size_t idx = do_read_32_relocated (ptr);
+-		  /* In phase zero we collect the comp_dir.  */
+-		  if (phase == 0)
+-		    {
+-		      if (idx >= debug_sections[DEBUG_STR].size)
+-			error (1, 0,
+-			       "%s: Bad string pointer index %zd for comp_dir",
+-			       dso->filename, idx);
+-		      dir = (char *) debug_sections[DEBUG_STR].data + idx;
+-
+-		      free (comp_dir);
+-		      comp_dir = strdup (dir);
+-		    }
+-
+-		  if (dest_dir != NULL && phase == 0)
+-		    {
+-		      if (record_file_string_entry_idx (&dso->strings, idx))
+-			need_strp_update = true;
+-		      handled_strp = true;
+-		    }
+-		}
++		edit_attributes_str_comp_dir (dso, &ptr, phase, &comp_dir,
++					      &handled_strp);
+ 	    }
+ 	  else if ((t->tag == DW_TAG_compile_unit
+ 		    || t->tag == DW_TAG_partial_unit)
+@@ -1815,99 +1945,21 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
+ 
+ 	  switch (form)
+ 	    {
+-	    case DW_FORM_ref_addr:
+-	      if (cu_version == 2)
+-		ptr += ptr_size;
+-	      else
+-		ptr += 4;
+-	      break;
+-	    case DW_FORM_flag_present:
+-	      break;
+-	    case DW_FORM_addr:
+-	      ptr += ptr_size;
+-	      break;
+-	    case DW_FORM_ref1:
+-	    case DW_FORM_flag:
+-	    case DW_FORM_data1:
+-	      ++ptr;
+-	      break;
+-	    case DW_FORM_ref2:
+-	    case DW_FORM_data2:
+-	      ptr += 2;
+-	      break;
+-	    case DW_FORM_ref4:
+-	    case DW_FORM_data4:
+-	    case DW_FORM_sec_offset:
+-	      ptr += 4;
+-	      break;
+-	    case DW_FORM_ref8:
+-	    case DW_FORM_data8:
+-	    case DW_FORM_ref_sig8:
+-	      ptr += 8;
+-	      break;
+-	    case DW_FORM_sdata:
+-	    case DW_FORM_ref_udata:
+-	    case DW_FORM_udata:
+-	      read_uleb128 (ptr);
+-	      break;
+ 	    case DW_FORM_strp:
+-	      /* In the first pass we collect all strings, in the
+-		 second we put the new references back (if there are
+-		 any changes).  */
+-	      if (phase == 0)
+-		{
+-		  /* handled_strp is set for attributes referring to
+-		     files. If it is set the string is already
+-		     recorded. */
+-		  if (! handled_strp)
+-		    {
+-		      size_t idx = do_read_32_relocated (ptr);
+-		      record_existing_string_entry_idx (&dso->strings, idx);
+-		    }
+-		}
+-	      else if (need_strp_update) /* && phase == 1 */
+-		{
+-		  struct stridxentry *entry;
+-		  size_t idx, new_idx;
+-		  idx = do_read_32_relocated (ptr);
+-		  entry = string_find_entry (&dso->strings, idx);
+-		  new_idx = strent_offset (entry->entry);
+-		  do_write_32_relocated (ptr, new_idx);
+-		}
+-	      ptr += 4;
+-	      break;
+-	    case DW_FORM_string:
+-	      ptr = (unsigned char *) strchr ((char *)ptr, '\0') + 1;
+-	      break;
+-	    case DW_FORM_indirect:
+-	      form = read_uleb128 (ptr);
+-	      continue;
+-	    case DW_FORM_block1:
+-	      len = *ptr++;
+-	      break;
+-	    case DW_FORM_block2:
+-	      len = read_16 (ptr);
+-	      form = DW_FORM_block1;
++	      edit_strp (dso, ptr, phase, handled_strp);
+ 	      break;
+-	    case DW_FORM_block4:
+-	      len = read_32 (ptr);
+-	      form = DW_FORM_block1;
+-	      break;
+-	    case DW_FORM_block:
+-	    case DW_FORM_exprloc:
+-	      len = read_uleb128 (ptr);
+-	      form = DW_FORM_block1;
+-	      assert (len < UINT_MAX);
++	    }
++
++	  switch (skip_form (dso, &form, &ptr))
++	    {
++	    case FORM_OK:
+ 	      break;
+-	    default:
+-	      error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename,
+-		     form);
++	    case FORM_ERROR:
+ 	      return NULL;
++	    case FORM_INDIRECT:
++	      continue;
+ 	    }
+ 
+-	  if (form == DW_FORM_block1)
+-	    ptr += len;
+-
+ 	  break;
+ 	}
+     }
+@@ -2068,6 +2120,28 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
+   return 0;
+ }
+ 
++/* Rebuild .debug_str.  */
++static void
++edit_dwarf2_any_str (DSO *dso)
++{
++  Strtab *strtab = dso->strings.str_tab;
++  Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
++  int strndx = debug_sections[DEBUG_STR].sec;
++  Elf_Scn *strscn = dso->scn[strndx];
++
++  /* Out with the old. */
++  strdata->d_size = 0;
++  /* In with the new. */
++  strdata = elf_newdata (strscn);
++
++  /* We really should check whether we had enough memory,
++     but the old ebl version will just abort on out of
++     memory... */
++  strtab_finalize (strtab, strdata);
++  debug_sections[DEBUG_STR].size = strdata->d_size;
++  dso->strings.str_buf = strdata->d_buf;
++}
++
+ static int
+ edit_dwarf2 (DSO *dso)
+ {
+@@ -2466,24 +2540,7 @@ edit_dwarf2 (DSO *dso)
+ 	 in place for phase 1 updating of debug_info
+ 	 references. */
+       if (phase == 0 && need_strp_update)
+-	{
+-	  Strtab *strtab = dso->strings.str_tab;
+-	  Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
+-	  int strndx = debug_sections[DEBUG_STR].sec;
+-	  Elf_Scn *strscn = dso->scn[strndx];
+-
+-	  /* Out with the old. */
+-	  strdata->d_size = 0;
+-	  /* In with the new. */
+-	  strdata = elf_newdata (strscn);
+-
+-	  /* We really should check whether we had enough memory,
+-	     but the old ebl version will just abort on out of
+-	     memory... */
+-	  strtab_finalize (strtab, strdata);
+-	  debug_sections[DEBUG_STR].size = strdata->d_size;
+-	  dso->strings.str_buf = strdata->d_buf;
+-	}
++	edit_dwarf2_any_str (dso);
+ 
+     }
+ 
+-- 
+2.18.4
+
diff --git a/SOURCES/0005-debugedit-Implement-DWARF-5-unit-header-and-new-form.patch b/SOURCES/0005-debugedit-Implement-DWARF-5-unit-header-and-new-form.patch
new file mode 100644
index 0000000..4bef1ef
--- /dev/null
+++ b/SOURCES/0005-debugedit-Implement-DWARF-5-unit-header-and-new-form.patch
@@ -0,0 +1,217 @@
+From 8b5dcb4c2175ac706a4e1c34ce83301213800689 Mon Sep 17 00:00:00 2001
+From: Jan Kratochvil <jan.kratochvil@redhat.com>
+Date: Mon, 18 Jan 2021 22:56:53 +0100
+Subject: [PATCH 5/6] debugedit: Implement DWARF-5 unit header and new forms
+ parsing.
+
+Recognize the various new DWARF5 .debug sections.
+Parse and skip new DWARF5 forms in read_abbrev and skip_form.
+Read DWARF5 unit headers for compile and partial units in edit_info.
+
+This is enough to be able to process gcc -gdwarf-5 produced binaries
+without the new DWARF5 .debug_line format (which isn't produced with
+binutils < 2.36).
+
+Patches slightly edited/merged by Mark Wielaard <mark@klomp.org>
+---
+ tools/debugedit.c | 88 +++++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 81 insertions(+), 7 deletions(-)
+
+diff --git a/tools/debugedit.c b/tools/debugedit.c
+index 7464883c5..be5fee85b 100644
+--- a/tools/debugedit.c
++++ b/tools/debugedit.c
+@@ -453,6 +453,11 @@ static debug_section debug_sections[] =
+ #define DEBUG_TYPES	11
+ #define DEBUG_MACRO	12
+ #define DEBUG_GDB_SCRIPT	13
++#define DEBUG_RNGLISTS	14
++#define DEBUG_LINE_STR	15
++#define DEBUG_ADDR	16
++#define DEBUG_STR_OFFSETS	17
++#define DEBUG_LOCLISTS	18
+     { ".debug_info", NULL, NULL, 0, 0, 0 },
+     { ".debug_abbrev", NULL, NULL, 0, 0, 0 },
+     { ".debug_line", NULL, NULL, 0, 0, 0 },
+@@ -467,6 +472,11 @@ static debug_section debug_sections[] =
+     { ".debug_types", NULL, NULL, 0, 0, 0 },
+     { ".debug_macro", NULL, NULL, 0, 0, 0 },
+     { ".debug_gdb_scripts", NULL, NULL, 0, 0, 0 },
++    { ".debug_rnglists", NULL, NULL, 0, 0, 0 },
++    { ".debug_line_str", NULL, NULL, 0, 0, 0 },
++    { ".debug_addr", NULL, NULL, 0, 0, 0 },
++    { ".debug_str_offsets", NULL, NULL, 0, 0, 0 },
++    { ".debug_loclists", NULL, NULL, 0, 0, 0 },
+     { NULL, NULL, NULL, 0, 0, 0 }
+   };
+ 
+@@ -755,12 +765,28 @@ 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_data16
++		       || form == DW_FORM_implicit_const
++		       || form == DW_FORM_addrx
++		       || form == DW_FORM_loclistx
++		       || form == DW_FORM_rnglistx
++		       || form == DW_FORM_addrx1
++		       || form == DW_FORM_addrx2
++		       || form == DW_FORM_addrx3
++		       || form == DW_FORM_addrx4)))
+ 	    {
+-	      error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form);
++	      error (0, 0, "%s: Unknown DWARF 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 +1531,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;
+@@ -1512,14 +1539,24 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
+     case DW_FORM_ref1:
+     case DW_FORM_flag:
+     case DW_FORM_data1:
++    case DW_FORM_strx1:
++    case DW_FORM_addrx1:
+       ++*ptrp;
+       break;
+     case DW_FORM_ref2:
+     case DW_FORM_data2:
++    case DW_FORM_strx2:
++    case DW_FORM_addrx2:
+       *ptrp += 2;
+       break;
++    case DW_FORM_strx3:
++    case DW_FORM_addrx3:
++      *ptrp += 3;
++      break;
+     case DW_FORM_ref4:
+     case DW_FORM_data4:
++    case DW_FORM_strx4:
++    case DW_FORM_addrx4:
+     case DW_FORM_sec_offset:
+       *ptrp += 4;
+       break;
+@@ -1528,12 +1565,20 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
+     case DW_FORM_ref_sig8:
+       *ptrp += 8;
+       break;
++    case DW_FORM_data16:
++      *ptrp += 16;
++      break;
+     case DW_FORM_sdata:
+     case DW_FORM_ref_udata:
+     case DW_FORM_udata:
++    case DW_FORM_strx:
++    case DW_FORM_loclistx:
++    case DW_FORM_rnglistx:
++    case DW_FORM_addrx:
+       read_uleb128 (*ptrp);
+       break;
+     case DW_FORM_strp:
++    case DW_FORM_line_strp:
+       *ptrp += 4;
+       break;
+     case DW_FORM_string:
+@@ -1560,7 +1605,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
+       assert (len < UINT_MAX);
+       break;
+     default:
+-      error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, *formp);
++      error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename, *formp);
+       return FORM_ERROR;
+     }
+ 
+@@ -2030,7 +2075,10 @@ 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 *cu_start = ptr;
++
++      /* header size, version, unit_type, ptr_size.  */
++      if (ptr + 4 + 2 + 1 + 1 > endsec)
+ 	{
+ 	  error (0, 0, "%s: %s CU header too small",
+ 		 dso->filename, sec->name);
+@@ -2052,13 +2100,36 @@ 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 = 0;
++
++      if (cu_version >= 5)
++	{
++	  uint8_t unit_type = read_8 (ptr);
++	  if (unit_type != DW_UT_compile && unit_type != DW_UT_partial)
++	    {
++	      error (0, 0, "%s: Unit type %u unhandled", dso->filename,
++		     unit_type);
++	      return 1;
++	    }
++
++	  cu_ptr_size = read_8 (ptr);
++	}
++
++      unsigned char *header_end = (cu_start + 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)
+ 	{
+@@ -2070,9 +2141,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",
+@@ -2080,7 +2154,7 @@ 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);
+-- 
+2.18.4
+
diff --git a/SOURCES/0006-debugedit-Handle-DWARF-5-debug_line-and-debug_line_s.patch b/SOURCES/0006-debugedit-Handle-DWARF-5-debug_line-and-debug_line_s.patch
new file mode 100644
index 0000000..1f1a966
--- /dev/null
+++ b/SOURCES/0006-debugedit-Handle-DWARF-5-debug_line-and-debug_line_s.patch
@@ -0,0 +1,772 @@
+From d9947f2dc0c2cd812f8e64380d5f6f53705a5280 Mon Sep 17 00:00:00 2001
+From: Mark Wielaard <mark@klomp.org>
+Date: Tue, 19 Jan 2021 04:12:33 +0100
+Subject: [PATCH 6/6] debugedit: Handle DWARF-5 debug_line and debug_line_str.
+
+Handle the new DWARF5 .debug_line tables and the new DW_FORM_line_strp.
+DWARF5 tables are handled separately from the earlier tables. They
+will never change size, but they do need updates to the .debug_str
+or .debug_line_str references.
+
+Based on a patch from Jan Kratochvil <jan.kratochvil@redhat.com>
+---
+ tools/debugedit.c | 471 ++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 410 insertions(+), 61 deletions(-)
+
+diff --git a/tools/debugedit.c b/tools/debugedit.c
+index be5fee85b..d6a0058e9 100644
+--- a/tools/debugedit.c
++++ b/tools/debugedit.c
+@@ -103,6 +103,8 @@ static bool need_string_replacement = false;
+ /* Whether we need to do any updates of the string indexes (DW_FORM_strp)
+    in debug_info for string indexes. */
+ static bool need_strp_update = false;
++/* Likewise for DW_FORM_line_strp. */
++static bool need_line_strp_update = false;
+ /* If the debug_line changes size we will need to update the
+    DW_AT_stmt_list attributes indexes in the debug_info. */
+ static bool need_stmt_update = false;
+@@ -192,7 +194,7 @@ typedef struct
+   const char *filename;
+   int lastscn;
+   size_t phnum;
+-  struct strings strings;
++  struct strings debug_str, debug_line_str;
+   struct debug_lines lines;
+   GElf_Shdr shdr[0];
+ } DSO;
+@@ -553,10 +555,11 @@ setup_relbuf (DSO *dso, debug_section *sec, int *reltype)
+       /* Relocations against section symbols are uninteresting in REL.  */
+       if (dso->shdr[i].sh_type == SHT_REL && sym.st_value == 0)
+ 	continue;
+-      /* Only consider relocations against .debug_str, .debug_line
+-	 and .debug_abbrev.  */
++      /* Only consider relocations against .debug_str, .debug_line,
++	 .debug_line_str, and .debug_abbrev.  */
+       if (sym.st_shndx != debug_sections[DEBUG_STR].sec
+ 	  && sym.st_shndx != debug_sections[DEBUG_LINE].sec
++	  && sym.st_shndx != debug_sections[DEBUG_LINE_STR].sec
+ 	  && sym.st_shndx != debug_sections[DEBUG_ABBREV].sec)
+ 	continue;
+       rela.r_addend += sym.st_value;
+@@ -768,6 +771,7 @@ no_memory:
+ 	      || (form > DW_FORM_flag_present
+ 		  && !(form == DW_FORM_ref_sig8
+ 		       || form == DW_FORM_data16
++		       || form == DW_FORM_line_strp
+ 		       || form == DW_FORM_implicit_const
+ 		       || form == DW_FORM_addrx
+ 		       || form == DW_FORM_loclistx
+@@ -1049,17 +1053,20 @@ string_find_entry (struct strings *strings, size_t old_idx)
+    a replacement file string has been recorded for it, otherwise
+    returns false.  */
+ static bool
+-record_file_string_entry_idx (struct strings *strings, size_t old_idx)
++record_file_string_entry_idx (bool line_strp, DSO *dso, size_t old_idx)
+ {
++  struct strings *strings = line_strp ? &dso->debug_line_str : &dso->debug_str;
+   bool ret = false;
+   struct stridxentry *entry = string_find_new_entry (strings, old_idx);
+   if (entry != NULL)
+     {
+-      if (old_idx >= debug_sections[DEBUG_STR].size)
+-	error (1, 0, "Bad string pointer index %zd", old_idx);
++      debug_section *sec = &debug_sections[line_strp
++					   ? DEBUG_LINE_STR : DEBUG_STR];
++      if (old_idx >= sec->size)
++	error (1, 0, "Bad string pointer index %zd (%s)", old_idx, sec->name);
+ 
+       Strent *strent;
+-      const char *old_str = (char *)debug_sections[DEBUG_STR].data + old_idx;
++      const char *old_str = (char *)sec->data + old_idx;
+       const char *file = skip_dir_prefix (old_str, base_dir);
+       if (file == NULL)
+ 	{
+@@ -1103,15 +1110,18 @@ record_file_string_entry_idx (struct strings *strings, size_t old_idx)
+    base_dir with dest_dir, just records the existing string associated
+    with the index. */
+ static void
+-record_existing_string_entry_idx (struct strings *strings, size_t old_idx)
++record_existing_string_entry_idx (bool line_strp, DSO *dso, size_t old_idx)
+ {
++  struct strings *strings = line_strp ? &dso->debug_line_str : &dso->debug_str;
+   struct stridxentry *entry = string_find_new_entry (strings, old_idx);
+   if (entry != NULL)
+     {
+-      if (old_idx >= debug_sections[DEBUG_STR].size)
+-	error (1, 0, "Bad string pointer index %zd", old_idx);
++      debug_section *sec = &debug_sections[line_strp
++					   ? DEBUG_LINE_STR : DEBUG_STR];
++      if (old_idx >= sec->size)
++	error (1, 0, "Bad string pointer index %zd (%s)", old_idx, sec->name);
+ 
+-      const char *str = (char *)debug_sections[DEBUG_STR].data + old_idx;
++      const char *str = (char *)sec->data + old_idx;
+       Strent *strent = strtab_add_len (strings->str_tab,
+ 				       str, strlen (str) + 1);
+       if (strent == NULL)
+@@ -1244,13 +1254,28 @@ get_line_table (DSO *dso, size_t off, struct line_table **table)
+ 
+   /* version */
+   t->version = read_16 (ptr);
+-  if (t->version != 2 && t->version != 3 && t->version != 4)
++  if (t->version != 2 && t->version != 3 && t->version != 4 && t->version != 5)
+     {
+       error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
+ 	     t->version);
+       return false;
+     }
+ 
++  if (t->version >= 5)
++    {
++      /* address_size */
++      assert (ptr_size != 0);
++      if (ptr_size != read_8 (ptr))
++	{
++	  error (0, 0, "%s: .debug_line address size differs from .debug_info",
++		 dso->filename);
++	  return false;
++	}
++
++      /* segment_selector_size */
++      (void) read_8 (ptr);
++    }
++
+   /* header_length */
+   unsigned char *endprol = ptr + 4;
+   t->header_length = read_32 (ptr);
+@@ -1343,7 +1368,9 @@ edit_dwarf2_line (DSO *dso)
+ 
+   linedata->d_size = dso->lines.debug_lines_len;
+   linedata->d_buf = dso->lines.line_buf;
++  debug_sections[DEBUG_LINE].data = linedata->d_buf;
+   debug_sections[DEBUG_LINE].size = linedata->d_size;
++  debug_sections[DEBUG_LINE].elf_data = linedata;
+ 
+   /* Make sure the line tables are sorted on the old index. */
+   qsort (dso->lines.table, dso->lines.used, sizeof (struct line_table),
+@@ -1483,9 +1510,10 @@ edit_dwarf2_line (DSO *dso)
+     }
+ }
+ 
+-/* Record or adjust (according to phase) DW_FORM_strp.  */
++/* Record or adjust (according to phase) DW_FORM_strp or DW_FORM_line_strp.  */
+ static void
+-edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp)
++edit_strp (DSO *dso, bool line_strp, unsigned char *ptr, int phase,
++	   bool handled_strp)
+ {
+   unsigned char *ptr_orig = ptr;
+ 
+@@ -1500,15 +1528,18 @@ edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp)
+       if (! handled_strp)
+ 	{
+ 	  size_t idx = do_read_32_relocated (ptr);
+-	  record_existing_string_entry_idx (&dso->strings, idx);
++	  record_existing_string_entry_idx (line_strp, dso, idx);
+ 	}
+     }
+-  else if (need_strp_update) /* && phase == 1 */
++  else if (line_strp
++	   ? need_line_strp_update : need_strp_update) /* && phase == 1 */
+     {
+       struct stridxentry *entry;
+       size_t idx, new_idx;
++      struct strings *strings = (line_strp
++				 ? &dso->debug_line_str : &dso->debug_str);
+       idx = do_read_32_relocated (ptr);
+-      entry = string_find_entry (&dso->strings, idx);
++      entry = string_find_entry (strings, idx);
+       new_idx = strent_offset (entry->entry);
+       do_write_32_relocated (ptr, new_idx);
+     }
+@@ -1759,6 +1790,254 @@ read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
+   return true;
+ }
+ 
++/* Called by read_dwarf5_line first for directories and then file
++   names as they both have the same format.  */
++static bool
++read_dwarf5_line_entries (DSO *dso, unsigned char **ptrp,
++			  struct line_table *table, int phase,
++			  char ***dirs, int *ndir,
++			  const char *entry_name)
++{
++  /* directory_entry_format_count */
++  /* file_name_entry_format_count */
++  unsigned format_count = read_8 (*ptrp);
++
++  unsigned char *formats = *ptrp;
++
++  /* directory_entry_format */
++  /* file_name_entry_format */
++  for (unsigned formati = 0; formati < format_count; ++formati)
++    {
++      read_uleb128 (*ptrp);
++      read_uleb128 (*ptrp);
++    }
++
++  /* directories_count */
++  /* file_names_count */
++  unsigned entry_count = read_uleb128 (*ptrp);
++
++  bool collecting_dirs = dest_dir && phase == 0 && *dirs == NULL;
++  bool writing_files = dest_dir && phase == 0 && *dirs != NULL;
++  if (collecting_dirs)
++    {
++      *ndir = entry_count;
++      *dirs = malloc (entry_count * sizeof (char *));
++      if (*dirs == NULL)
++	error (1, errno, "%s: Could not allocate debug_line dirs",
++	       dso->filename);
++    }
++
++  /* directories */
++  /* file_names */
++  for (unsigned entryi = 0; entryi < entry_count; ++entryi)
++    {
++      char *dir = NULL;
++      char *file = NULL;;
++      unsigned char *format_ptr = formats;
++      for (unsigned formati = 0; formati < format_count; ++formati)
++	{
++	  unsigned lnct = read_uleb128 (format_ptr);
++	  unsigned form = read_uleb128 (format_ptr);
++	  bool handled_form = false;
++	  bool handled_strp = false;
++	  bool line_strp = form == DW_FORM_line_strp;
++	  if (lnct == DW_LNCT_path)
++	    {
++	      switch (form)
++		{
++		case DW_FORM_strp:
++		case DW_FORM_line_strp:
++		  if (dest_dir && phase == 0)
++		    {
++		      size_t idx = do_read_32_relocated (*ptrp);
++		      if (record_file_string_entry_idx (line_strp, dso, idx))
++			{
++			  if (line_strp)
++			    need_line_strp_update = true;
++			  else
++			    need_strp_update = true;
++			}
++		      handled_strp = true;
++		      if (collecting_dirs || writing_files)
++			{
++			  debug_section *sec = &debug_sections[line_strp
++                                           ? DEBUG_LINE_STR : DEBUG_STR];
++			  if (collecting_dirs)
++			    dir = (char *)sec->data + idx;
++			  if (writing_files)
++			    file = (char *)sec->data + idx;
++			}
++		    }
++		  break;
++		default:
++		  error (0, 0, "%s: Unsupported "
++			 ".debug_line %s %u path DW_FORM_0x%x",
++			 dso->filename, entry_name, entryi, form);
++		  return false;
++		}
++	    }
++	  if (writing_files && lnct == DW_LNCT_directory_index)
++	    {
++	      int dirndx;
++	      switch (form)
++		{
++		case DW_FORM_udata:
++		  handled_form = true;
++		  dirndx = read_uleb128 (*ptrp);
++		  break;
++		case DW_FORM_data1:
++		  dirndx = **ptrp;
++		  break;
++		case DW_FORM_data2:
++		  dirndx = do_read_16 (*ptrp);
++		  break;
++		case DW_FORM_data4:
++		  dirndx = do_read_32 (*ptrp);
++		  break;
++		default:
++		  error (0, 0, "%s: Unsupported "
++			 ".debug_line %s %u dirndx DW_FORM_0x%x",
++			 dso->filename, entry_name, entryi, form);
++		  return false;
++		}
++
++	      if (dirndx > *ndir)
++		{
++		  error (0, 0, "%s: Bad dir number %u in .debug_line %s",
++			 dso->filename, entryi, entry_name);
++		  return false;
++		}
++	      dir = (*dirs)[dirndx];
++	    }
++
++	  switch (form)
++	    {
++	    case DW_FORM_strp:
++	    case DW_FORM_line_strp:
++	      edit_strp (dso, line_strp, *ptrp, phase, handled_strp);
++	      break;
++	    }
++
++	  if (!handled_form)
++	    {
++	      switch (skip_form (dso, &form, ptrp))
++		{
++		case FORM_OK:
++		  break;
++		case FORM_ERROR:
++		  return false;
++		case FORM_INDIRECT:
++		  error (0, 0, "%s: Unsupported "
++			 ".debug_line %s %u DW_FORM_indirect",
++			 dso->filename, entry_name, entryi);
++		  return false;
++		}
++	    }
++	}
++
++      if (collecting_dirs)
++	(*dirs)[entryi] = dir;
++
++      if (writing_files)
++	{
++	  char *comp_dir = (*dirs)[0];
++	  size_t comp_dir_len = strlen(comp_dir);
++	  size_t file_len = strlen (file);
++	  size_t dir_len = strlen (dir);
++
++	  char *s = malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1);
++	  if (s == NULL)
++	    {
++	      error (0, ENOMEM, "%s: Reading file table", dso->filename);
++	      return false;
++	    }
++	  if (file[0] == '/')
++	    {
++	      memcpy (s, file, file_len + 1);
++	    }
++	  else if (dir[0] == '/')
++	    {
++	      memcpy (s, dir, dir_len);
++	      s[dir_len] = '/';
++	      memcpy (s + dir_len + 1, file, file_len + 1);
++	    }
++	  else
++	    {
++	      char *p = s;
++	      if (comp_dir_len != 0)
++		{
++		  memcpy (s, comp_dir, comp_dir_len);
++		  s[comp_dir_len] = '/';
++		  p += comp_dir_len + 1;
++		}
++	      memcpy (p, dir, dir_len);
++	      p[dir_len] = '/';
++	      memcpy (p + dir_len + 1, file, file_len + 1);
++	    }
++	  canonicalize_path (s, s);
++	  if (list_file_fd != -1)
++	    {
++	      const char *p = NULL;
++	      if (base_dir == NULL)
++		p = s;
++	      else
++		{
++		  p = skip_dir_prefix (s, base_dir);
++		  if (p == NULL && dest_dir != NULL)
++		    p = skip_dir_prefix (s, dest_dir);
++		}
++
++	      if (p)
++		{
++		  size_t size = strlen (p) + 1;
++		  while (size > 0)
++		    {
++		      ssize_t ret = write (list_file_fd, p, size);
++		      if (ret == -1)
++			break;
++		      size -= ret;
++		      p += ret;
++		    }
++		}
++	    }
++
++	  free (s);
++	}
++    }
++
++  return true;
++}
++
++/* Part of read_dwarf2_line processing DWARF-5.  */
++static bool
++read_dwarf5_line (DSO *dso, unsigned char *ptr, struct line_table *table,
++		  int phase)
++{
++  char **dirs = NULL;
++  int ndir;
++  /* Skip header.  */
++  ptr += (4 /* unit len */
++          + 2 /* version */
++          + (table->version < 5 ? 0 : 0
++             + 1 /* address_size */
++             + 1 /* segment_selector*/)
++          + 4 /* header len */
++          + 1 /* min instr len */
++          + (table->version >= 4) /* max op per instr, if version >= 4 */
++          + 1 /* default is stmt */
++          + 1 /* line base */
++          + 1 /* line range */
++          + 1 /* opcode base */
++          + table->opcode_base - 1); /* opcode len table */
++
++  bool retval = (read_dwarf5_line_entries (dso, &ptr, table, phase,
++					   &dirs, &ndir, "directory")
++		 && read_dwarf5_line_entries (dso, &ptr, table, phase,
++					      &dirs, &ndir, "file name"));
++  free (dirs);
++  return retval;
++}
++
+ /* Called during phase zero for each debug_line table referenced from
+    .debug_info.  Outputs all source files seen and records any
+    adjustments needed in the debug_list data structures. Returns true
+@@ -1778,6 +2057,9 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
+   ptr = debug_sections[DEBUG_LINE].data + off;
+   ptr += (4 /* unit len */
+ 	  + 2 /* version */
++	  + (table->version < 5 ? 0 : 0
++	     + 1 /* address_size */
++	     + 1 /* segment_selector*/)
+ 	  + 4 /* header len */
+ 	  + 1 /* min instr len */
+ 	  + (table->version >= 4) /* max op per instr, if version >= 4 */
+@@ -1787,8 +2069,13 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
+ 	  + 1 /* opcode base */
+ 	  + table->opcode_base - 1); /* opcode len table */
+ 
+-  if (! read_dwarf4_line (dso, ptr, comp_dir, table))
+-   return false;
++  /* DWARF version 5 line tables won't change size. But they might need
++     [line]strp recording/updates. Handle that part later.  */
++  if (table->version < 5)
++    {
++      if (! read_dwarf4_line (dso, ptr, comp_dir, table))
++	return false;
++    }
+ 
+   dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff;
+   return table->replace_dirs || table->replace_files;
+@@ -1807,20 +2094,22 @@ find_new_list_offs (struct debug_lines *lines, size_t idx)
+   return table->new_idx;
+ }
+ 
+-/* Read DW_FORM_strp collecting compilation directory.  */
++/* Read DW_FORM_strp or DW_FORM_line_strp collecting compilation directory.  */
+ static void
+-edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase,
+-			      char **comp_dirp, bool *handled_strpp)
++edit_attributes_str_comp_dir (bool line_strp, DSO *dso, unsigned char **ptrp,
++			      int phase, char **comp_dirp, bool *handled_strpp)
+ {
+   const char *dir;
+   size_t idx = do_read_32_relocated (*ptrp);
+   /* In phase zero we collect the comp_dir.  */
+   if (phase == 0)
+     {
+-      if (idx >= debug_sections[DEBUG_STR].size)
+-	error (1, 0, "%s: Bad string pointer index %zd for comp_dir",
+-	       dso->filename, idx);
+-      dir = (char *) debug_sections[DEBUG_STR].data + idx;
++      debug_section *sec = &debug_sections[line_strp
++					   ? DEBUG_LINE_STR : DEBUG_STR];
++      if (sec->data == NULL || idx >= sec->size)
++	error (1, 0, "%s: Bad string pointer index %zd for comp_dir (%s)",
++	       dso->filename, idx, sec->name);
++      dir = (char *) sec->data + idx;
+ 
+       free (*comp_dirp);
+       *comp_dirp = strdup (dir);
+@@ -1828,8 +2117,13 @@ edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase,
+ 
+   if (dest_dir != NULL && phase == 0)
+     {
+-      if (record_file_string_entry_idx (&dso->strings, idx))
+-	need_strp_update = true;
++      if (record_file_string_entry_idx (line_strp, dso, idx))
++	{
++	  if (line_strp)
++	    need_line_strp_update = true;
++	  else
++	    need_strp_update = true;
++	}
+       *handled_strpp = true;
+     }
+ }
+@@ -1937,17 +2231,24 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
+ 			}
+ 		    }
+ 		}
+-	      else if (form == DW_FORM_strp &&
+-		       debug_sections[DEBUG_STR].data)
+-		edit_attributes_str_comp_dir (dso, &ptr, phase, &comp_dir,
++	      else if (form == DW_FORM_strp)
++		edit_attributes_str_comp_dir (false /* line_strp */, dso,
++					      &ptr, phase, &comp_dir,
+ 					      &handled_strp);
++	      else if (form == DW_FORM_line_strp)
++		edit_attributes_str_comp_dir (true /* line_strp */, dso, &ptr,
++					      phase, &comp_dir, &handled_strp);
+ 	    }
+ 	  else if ((t->tag == DW_TAG_compile_unit
+ 		    || t->tag == DW_TAG_partial_unit)
+-		   && t->attr[i].attr == DW_AT_name
+-		   && form == DW_FORM_strp
+-		   && debug_sections[DEBUG_STR].data)
++		   && ((form == DW_FORM_strp
++			&& debug_sections[DEBUG_STR].data)
++		       || (form == DW_FORM_line_strp
++			   && debug_sections[DEBUG_LINE_STR].data))
++		   && t->attr[i].attr == DW_AT_name)
+ 	    {
++	      bool line_strp = form == DW_FORM_line_strp;
++
+ 	      /* DW_AT_name is the primary file for this compile
+ 		 unit. If starting with / it is a full path name.
+ 		 Note that we don't handle DW_FORM_string in this
+@@ -1957,11 +2258,14 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
+ 	      /* In phase zero we will look for a comp_dir to use.  */
+ 	      if (phase == 0)
+ 		{
+-		  if (idx >= debug_sections[DEBUG_STR].size)
++		  debug_section *sec = &debug_sections[line_strp
++						       ? DEBUG_LINE_STR
++						       : DEBUG_STR];
++		  if (idx >= sec->size)
+ 		    error (1, 0,
+-			   "%s: Bad string pointer index %zd for unit name",
+-			   dso->filename, idx);
+-		  char *name = (char *) debug_sections[DEBUG_STR].data + idx;
++			   "%s: Bad string pointer index %zd for unit name (%s)",
++			   dso->filename, idx, sec->name);
++		  char *name = (char *) sec->data + idx;
+ 		  if (*name == '/' && comp_dir == NULL)
+ 		    {
+ 		      char *enddir = strrchr (name, '/');
+@@ -1982,8 +2286,13 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
+ 		 pass (1) stores it (the new index). */
+ 	      if (dest_dir && phase == 0)
+ 		{
+-		  if (record_file_string_entry_idx (&dso->strings, idx))
+-		    need_strp_update = true;
++		  if (record_file_string_entry_idx (line_strp, dso, idx))
++		    {
++		      if (line_strp)
++			need_line_strp_update = true;
++		      else
++			need_strp_update = true;
++		    }
+ 		  handled_strp = true;
+ 		}
+ 	    }
+@@ -1991,7 +2300,10 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
+ 	  switch (form)
+ 	    {
+ 	    case DW_FORM_strp:
+-	      edit_strp (dso, ptr, phase, handled_strp);
++	      edit_strp (dso, false /* line_strp */, ptr, phase, handled_strp);
++	      break;
++	    case DW_FORM_line_strp:
++	      edit_strp (dso, true /* line_strp */, ptr, phase, handled_strp);
+ 	      break;
+ 	    }
+ 
+@@ -2196,11 +2508,11 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
+ 
+ /* Rebuild .debug_str.  */
+ static void
+-edit_dwarf2_any_str (DSO *dso)
++edit_dwarf2_any_str (DSO *dso, struct strings *strings, debug_section *secp)
+ {
+-  Strtab *strtab = dso->strings.str_tab;
+-  Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
+-  int strndx = debug_sections[DEBUG_STR].sec;
++  Strtab *strtab = strings->str_tab;
++  Elf_Data *strdata = secp->elf_data;
++  int strndx = secp->sec;
+   Elf_Scn *strscn = dso->scn[strndx];
+ 
+   /* Out with the old. */
+@@ -2212,8 +2524,8 @@ edit_dwarf2_any_str (DSO *dso)
+      but the old ebl version will just abort on out of
+      memory... */
+   strtab_finalize (strtab, strdata);
+-  debug_sections[DEBUG_STR].size = strdata->d_size;
+-  dso->strings.str_buf = strdata->d_buf;
++  secp->size = strdata->d_size;
++  strings->str_buf = strdata->d_buf;
+ }
+ 
+ static int
+@@ -2359,12 +2671,14 @@ edit_dwarf2 (DSO *dso)
+   bool info_rel_updated = false;
+   bool types_rel_updated = false;
+   bool macro_rel_updated = false;
++  bool line_rel_updated = false;
+ 
+   for (phase = 0; phase < 2; phase++)
+     {
+       /* If we don't need to update anyhing, skip phase 1. */
+       if (phase == 1
+ 	  && !need_strp_update
++	  && !need_line_strp_update
+ 	  && !need_string_replacement
+ 	  && !need_stmt_update)
+ 	break;
+@@ -2582,15 +2896,14 @@ edit_dwarf2 (DSO *dso)
+ 		      if (phase == 0)
+ 			{
+ 			  size_t idx = read_32_relocated (ptr);
+-			  record_existing_string_entry_idx (&dso->strings,
+-							    idx);
++			  record_existing_string_entry_idx (false, dso, idx);
+ 			}
+ 		      else
+ 			{
+ 			  struct stridxentry *entry;
+ 			  size_t idx, new_idx;
+ 			  idx = do_read_32_relocated (ptr);
+-			  entry = string_find_entry (&dso->strings, idx);
++			  entry = string_find_entry (&dso->debug_str, idx);
+ 			  new_idx = strent_offset (entry->entry);
+ 			  write_32_relocated (ptr, new_idx);
+ 			}
+@@ -2610,24 +2923,50 @@ edit_dwarf2 (DSO *dso)
+ 	    }
+ 	}
+ 
+-      /* Same for the debug_str section. Make sure everything is
+-	 in place for phase 1 updating of debug_info
++
++      /* Now handle all the DWARF5 line tables, they contain strp
++	 and/or line_strp entries that need to be registered/rewritten.  */
++      setup_relbuf(dso, &debug_sections[DEBUG_LINE], &reltype);
++      rel_updated = false;
++
++      /* edit_dwarf2_line will have set this up, unless there are no
++	 moved/resized (DWARF4) lines. In which case we can just use
++	 the original section data. new_idx will have been setup
++	 correctly, even if it is the same as old_idx.  */
++      unsigned char *line_buf = (unsigned char *)dso->lines.line_buf;
++      if (line_buf == NULL)
++	line_buf = debug_sections[DEBUG_LINE].data;
++      for (int ldx = 0; ldx < dso->lines.used; ldx++)
++	{
++	  struct line_table *t = &dso->lines.table[ldx];
++	  if (t->version >= 5)
++	    read_dwarf5_line (dso, line_buf + t->new_idx, t, phase);
++	}
++      if (rel_updated)
++	line_rel_updated = true;
++
++      /* Same for the debug_str and debug_line_str sections.
++	 Make sure everything is in place for phase 1 updating of debug_info
+ 	 references. */
+       if (phase == 0 && need_strp_update)
+-	edit_dwarf2_any_str (dso);
+-
++	edit_dwarf2_any_str (dso, &dso->debug_str,
++			     &debug_sections[DEBUG_STR]);
++      if (phase == 0 && need_line_strp_update)
++	edit_dwarf2_any_str (dso, &dso->debug_line_str,
++			     &debug_sections[DEBUG_LINE_STR]);
+     }
+ 
+   /* After phase 1 we might have rewritten the debug_info with
+      new strp, strings and/or linep offsets.  */
+-  if (need_strp_update || need_string_replacement || need_stmt_update) {
++  if (need_strp_update || need_line_strp_update
++      || need_string_replacement || need_stmt_update) {
+     dirty_section (DEBUG_INFO);
+     if (debug_sections[DEBUG_TYPES].data != NULL)
+       dirty_section (DEBUG_TYPES);
+   }
+   if (need_strp_update || need_stmt_update)
+     dirty_section (DEBUG_MACRO);
+-  if (need_stmt_update)
++  if (need_stmt_update || need_line_strp_update)
+     dirty_section (DEBUG_LINE);
+ 
+   /* Update any relocations addends we might have touched. */
+@@ -2653,6 +2992,9 @@ edit_dwarf2 (DSO *dso)
+ 	}
+     }
+ 
++  if (line_rel_updated)
++    update_rela_data (dso, &debug_sections[DEBUG_LINE]);
++
+   return 0;
+ }
+ 
+@@ -2745,7 +3087,8 @@ fdopen_dso (int fd, const char *name)
+     }
+ 
+   dso->filename = (const char *) strdup (name);
+-  setup_strings (&dso->strings);
++  setup_strings (&dso->debug_str);
++  setup_strings (&dso->debug_line_str);
+   setup_lines (&dso->lines);
+   return dso;
+ 
+@@ -2753,7 +3096,8 @@ error_out:
+   if (dso)
+     {
+       free ((char *) dso->filename);
+-      destroy_strings (&dso->strings);
++      destroy_strings (&dso->debug_str);
++      destroy_strings (&dso->debug_line_str);
+       destroy_lines (&dso->lines);
+       free (dso);
+     }
+@@ -3034,7 +3378,9 @@ main (int argc, char *argv[])
+      in elfutils before 0.169 we will have to update and write out all
+      section data if any data has changed (when ELF_F_LAYOUT was
+      set). https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */
+-  bool need_update = need_strp_update || need_stmt_update;
++  bool need_update = (need_strp_update
++		      || need_line_strp_update
++		      || need_stmt_update);
+ 
+ #if !_ELFUTILS_PREREQ (0, 169)
+   /* string replacements or build_id updates don't change section size. */
+@@ -3106,10 +3452,12 @@ main (int argc, char *argv[])
+ 	      GElf_Xword sec_size = shdr->sh_size;
+ 
+ 	      /* We might have changed the size (and content) of the
+-		 debug_str or debug_line section. */
++		 debug_str, debug_line_str or debug_line section. */
+ 	      size_t secnum = elf_ndxscn (scn);
+ 	      if (secnum == debug_sections[DEBUG_STR].sec)
+ 		sec_size = debug_sections[DEBUG_STR].size;
++	      if (secnum == debug_sections[DEBUG_LINE_STR].sec)
++		sec_size = debug_sections[DEBUG_LINE_STR].size;
+ 	      if (secnum == debug_sections[DEBUG_LINE].sec)
+ 		sec_size = debug_sections[DEBUG_LINE].size;
+ 
+@@ -3179,7 +3527,8 @@ main (int argc, char *argv[])
+   chmod (file, stat_buf.st_mode);
+ 
+   free ((char *) dso->filename);
+-  destroy_strings (&dso->strings);
++  destroy_strings (&dso->debug_str);
++  destroy_strings (&dso->debug_line_str);
+   destroy_lines (&dso->lines);
+   free (dso);
+ 
+-- 
+2.18.4
+
diff --git a/SOURCES/rpm-4.12.0-rpm2cpio-hack.patch b/SOURCES/rpm-4.12.0-rpm2cpio-hack.patch
new file mode 100644
index 0000000..38c7dbd
--- /dev/null
+++ b/SOURCES/rpm-4.12.0-rpm2cpio-hack.patch
@@ -0,0 +1,18 @@
+diff --git a/rpm2cpio.c b/rpm2cpio.c
+index 89ebdfa..ae999ff 100644
+--- a/rpm2cpio.c
++++ b/rpm2cpio.c
+@@ -84,7 +84,12 @@ int main(int argc, char *argv[])
+ 	exit(EXIT_FAILURE);
+     }
+ 
+-    rc = (ufdCopy(gzdi, fdo) == payload_size) ? EXIT_SUCCESS : EXIT_FAILURE;
++    /*
++     * XXX HACK for #1142949: should be equality test, but archive size
++     * short by cpio trailer size in packages built with rpm 4.12.0
++     * and its pre-releases.
++     */
++    rc = (ufdCopy(gzdi, fdo) >= payload_size) ? EXIT_SUCCESS : EXIT_FAILURE;
+ 
+     Fclose(fdo);
+ 
diff --git a/SOURCES/rpm-4.15.x-ldflags.patch b/SOURCES/rpm-4.15.x-ldflags.patch
new file mode 100644
index 0000000..c781ca8
--- /dev/null
+++ b/SOURCES/rpm-4.15.x-ldflags.patch
@@ -0,0 +1,15 @@
+diff -up rpm-4.9.1.1/macros.in.jx rpm-4.9.1.1/macros.in
+--- rpm-4.9.1.1/macros.in.jx	2011-08-03 16:19:05.000000000 -0400
++++ rpm-4.9.1.1/macros.in	2011-08-08 09:41:52.981064316 -0400
+@@ -674,9 +674,10 @@ print (t)\
+   RPM_BUILD_DIR=\"%{u2p:%{_builddir}}\"\
+   RPM_OPT_FLAGS=\"%{optflags}\"\
++  RPM_LD_FLAGS=\"%{?build_ldflags}\"\
+   RPM_ARCH=\"%{_arch}\"\
+   RPM_OS=\"%{_os}\"\
+   RPM_BUILD_NCPUS=\"%{_smp_build_ncpus}\"\
+-  export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS\
++  export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_LD_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS RPM_LD_FLAGS\
+   RPM_DOC_DIR=\"%{_docdir}\"\
+   export RPM_DOC_DIR\
+   RPM_PACKAGE_NAME=\"%{NAME}\"\
diff --git a/SOURCES/rpm-4.15.x-siteconfig.patch b/SOURCES/rpm-4.15.x-siteconfig.patch
new file mode 100644
index 0000000..5df41d4
--- /dev/null
+++ b/SOURCES/rpm-4.15.x-siteconfig.patch
@@ -0,0 +1,12 @@
+diff -up rpm-4.11.1-rc1/macros.in.siteconfig rpm-4.11.1-rc1/macros.in
+--- rpm-4.11.1-rc1/macros.in.siteconfig	2013-06-07 13:19:21.000000000 +0300
++++ rpm-4.11.1-rc1/macros.in	2013-06-11 15:06:59.525747503 +0300
+@@ -647,6 +647,8 @@ package or when debugging this package.\
+   export CLASSPATH}\
+   PKG_CONFIG_PATH=\"${PKG_CONFIG_PATH}:%{_libdir}/pkgconfig:%{_datadir}/pkgconfig\"\
+   export PKG_CONFIG_PATH\
++  CONFIG_SITE=${CONFIG_SITE:-NONE}\
++  export CONFIG_SITE\
+   \
+   %{verbose:set -x}\
+   umask 022\
diff --git a/SOURCES/rpm-4.16.1.3-add-fapolicyd-plugin.patch b/SOURCES/rpm-4.16.1.3-add-fapolicyd-plugin.patch
new file mode 100644
index 0000000..33aef5a
--- /dev/null
+++ b/SOURCES/rpm-4.16.1.3-add-fapolicyd-plugin.patch
@@ -0,0 +1,334 @@
+commit 39595ccee321497dc3b08c7cab8a10304345429c
+Author: Radovan Sroka <rsroka@redhat.com>
+Date:   Tue Oct 27 16:18:04 2020 +0100
+
+    Added fapolicyd rpm plugin
+    
+    Fapolicyd (File Access Policy Daemon) implements application whitelisting
+    to decide file access rights. Applications that are known via a reputation
+    source are allowed access while unknown applications are not.
+    
+    The rpm plugin allows us to use rpm database as a source of trust.
+    We used dnf plugin since the beggining but it only provides notification
+    when transaction ends. With "integrity checking" requirement we need
+    a continual addition of files which are installed during the system
+    update. With fapolicyd rpm plugin we can allow using of recently
+    added/updated files in scriptlets during rpm transaction.
+    
+    The fapolicyd plugin gathers metadata of currently installed files.
+    It sends the information about files and about ongoing rpm transaction
+    to the fapolicyd daemon. The information is written to Linux pipe which
+    is placed in /var/run/fapolicyd/fapolicyd.fifo.
+    
+    The data format is "%s %lu %64s\n". [path, size, sha256]
+    
+    The fapolicyd rpm plugin can be enabled with "--with-fapolicyd"
+    configure option.
+    
+    Related PRs:
+    https://github.com/linux-application-whitelisting/fapolicyd/pull/105
+    https://github.com/linux-application-whitelisting/fapolicyd/pull/106
+    
+    Signed-off-by: Radovan Sroka <rsroka@redhat.com>
+
+    Backported into 4.16.1.3, together with commit
+    6d61b7118adcc14631b7ee5163a481472af940b8 (covscan fix)
+
+diff -up rpm-4.16.1.3/configure.ac.orig rpm-4.16.1.3/configure.ac
+--- rpm-4.16.1.3/configure.ac.orig	2021-03-22 11:05:07.311635968 +0100
++++ rpm-4.16.1.3/configure.ac	2021-07-22 16:18:29.352006782 +0200
+@@ -891,6 +891,14 @@ AS_IF([test "$enable_plugins" != no],[
+ AM_CONDITIONAL(IMA, [test "x$ac_cv_func_lsetxattr" = xyes])
+ 
+ #=================
++# Check for fapolicyd support
++AC_ARG_WITH(fapolicyd,
++AS_HELP_STRING([--with-fapolicyd],[build with File Access Policy Daemon support]),
++with_fapolicyd=$withval,
++with_fapolicyd=auto)
++AM_CONDITIONAL(FAPOLICYD,[test "$with_fapolicyd" = yes])
++
++#=================
+ # Check for audit library.
+ AC_ARG_WITH(audit,
+ AS_HELP_STRING([--with-audit],[Linux audit plugin]),
+diff -up rpm-4.16.1.3/doc/Makefile.am.orig rpm-4.16.1.3/doc/Makefile.am
+--- rpm-4.16.1.3/doc/Makefile.am.orig	2020-06-23 14:13:01.895628382 +0200
++++ rpm-4.16.1.3/doc/Makefile.am	2021-07-22 16:18:29.352006782 +0200
+@@ -25,6 +25,9 @@ endif
+ if IMA
+ man_man8_DATA += rpm-plugin-ima.8
+ endif
++if FAPOLICYD
++man_man8_DATA += rpm-plugin-fapolicyd.8
++endif
+ if SELINUX
+ man_man8_DATA += rpm-plugin-selinux.8
+ endif
+@@ -37,6 +40,8 @@ endif
+ EXTRA_DIST += rpm-plugins.8 rpm-plugin-prioreset.8 rpm-plugin-syslog.8 
+ EXTRA_DIST += rpm-plugin-audit.8 rpm-plugin-systemd-inhibit.8 
+ EXTRA_DIST += rpm-plugin-ima.8 rpm-plugin-selinux.8 rpm2archive.8
++EXTRA_DIST += rpm-plugin-fapolicyd.8
++
+ 
+ man_fr_man8dir = $(mandir)/fr/man8
+ man_fr_man8_DATA = fr/rpm.8
+diff -up rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8.orig rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8
+--- rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8.orig	2021-07-22 16:18:29.353006800 +0200
++++ rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8	2021-07-22 16:18:29.353006800 +0200
+@@ -0,0 +1,21 @@
++'\" t
++.TH "RPM-FAPOLICYD" "8" "28 Jan 2021" "Red Hat, Inc."
++.SH NAME
++rpm-plugin-fapolicyd \- Fapolicyd plugin for the RPM Package Manager
++
++.SH Description
++
++The plugin gathers metadata of currently installed files. It sends the
++information about files and about ongoing rpm transaction to the fapolicyd daemon.
++The information is written to Linux pipe which is placed in
++/var/run/fapolicyd/fapolicyd.fifo.
++
++.SH Configuration
++
++There are currently no options for this plugin in particular. See
++.BR rpm-plugins (8)
++on how to control plugins in general.
++
++.SH SEE ALSO
++.IR fapolicyd (8)
++.IR rpm-plugins (8)
+diff -up rpm-4.16.1.3/macros.in.orig rpm-4.16.1.3/macros.in
+--- rpm-4.16.1.3/macros.in.orig	2021-07-22 16:18:20.525844141 +0200
++++ rpm-4.16.1.3/macros.in	2021-07-22 16:19:36.196238525 +0200
+@@ -1208,6 +1208,7 @@ package or when debugging this package.\
+ %__transaction_selinux		%{__plugindir}/selinux.so
+ %__transaction_syslog		%{__plugindir}/syslog.so
+ %__transaction_ima		%{__plugindir}/ima.so
++%__transaction_fapolicyd	%{__plugindir}/fapolicyd.so
+ %__transaction_prioreset	%{__plugindir}/prioreset.so
+ %__transaction_audit		%{__plugindir}/audit.so
+ 
+diff -up rpm-4.16.1.3/Makefile.am.orig rpm-4.16.1.3/Makefile.am
+--- rpm-4.16.1.3/Makefile.am.orig	2021-07-22 16:18:29.350006745 +0200
++++ rpm-4.16.1.3/Makefile.am	2021-07-22 16:19:18.223907346 +0200
+@@ -14,6 +14,7 @@ DISTCHECK_CONFIGURE_FLAGS = \
+ 	--with-audit \
+ 	--with-selinux \
+ 	--with-imaevm \
++	--with-fapolicyd \
+ 	--disable-dependency-tracking
+ 
+ include $(top_srcdir)/rpm.am
+diff -up rpm-4.16.1.3/plugins/fapolicyd.c.orig rpm-4.16.1.3/plugins/fapolicyd.c
+--- rpm-4.16.1.3/plugins/fapolicyd.c.orig	2021-07-22 16:18:29.356006855 +0200
++++ rpm-4.16.1.3/plugins/fapolicyd.c	2021-07-22 16:18:35.380117862 +0200
+@@ -0,0 +1,191 @@
++#include "system.h"
++
++#include <rpm/rpmts.h>
++#include <rpm/rpmlog.h>
++#include "lib/rpmplugin.h"
++
++#include <fcntl.h>
++#include <errno.h>
++#include <unistd.h>
++#include <sys/stat.h>
++
++struct fapolicyd_data {
++    int fd;
++    long changed_files;
++    const char * fifo_path;
++};
++
++static struct fapolicyd_data fapolicyd_state = {
++    .fd = -1,
++    .changed_files = 0,
++    .fifo_path = "/run/fapolicyd/fapolicyd.fifo",
++};
++
++static rpmRC open_fifo(struct fapolicyd_data* state)
++{
++    int fd = -1;
++    struct stat s;
++
++    fd = open(state->fifo_path, O_RDWR);
++    if (fd == -1) {
++        rpmlog(RPMLOG_DEBUG, "Open: %s -> %s\n", state->fifo_path, strerror(errno));
++        goto bad;
++    }
++
++    if (stat(state->fifo_path, &s) == -1) {
++        rpmlog(RPMLOG_DEBUG, "Stat: %s -> %s\n", state->fifo_path, strerror(errno));
++        goto bad;
++    }
++
++    if (!S_ISFIFO(s.st_mode)) {
++        rpmlog(RPMLOG_DEBUG, "File: %s exists but it is not a pipe!\n", state->fifo_path);
++        goto bad;
++    }
++
++    /* keep only file's permition bits */
++    mode_t mode = s.st_mode & ~S_IFMT;
++
++    /* we require pipe to have 0660 permission */
++    if (mode != 0660) {
++        rpmlog(RPMLOG_ERR, "File: %s has %o instead of 0660 \n",
++               state->fifo_path,
++               mode );
++        goto bad;
++    }
++
++    state->fd = fd;
++    /* considering success */
++    return RPMRC_OK;
++
++ bad:
++    if (fd >= 0)
++        close(fd);
++    return RPMRC_FAIL;
++}
++
++static rpmRC write_fifo(struct fapolicyd_data* state, const char * str)
++{
++    ssize_t len = strlen(str);
++    ssize_t written = 0;
++    ssize_t n = 0;
++
++    while (written < len) {
++        if ((n = write(state->fd, str + written, len - written)) < 0) {
++            if (errno == EINTR || errno == EAGAIN)
++                continue;
++            rpmlog(RPMLOG_DEBUG, "Write: %s -> %s\n", state->fifo_path, strerror(errno));
++            goto bad;
++        }
++        written += n;
++    }
++
++    return RPMRC_OK;
++
++ bad:
++    return RPMRC_FAIL;
++}
++
++static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts)
++{
++    if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
++        goto end;
++
++    if (!rstreq(rpmtsRootDir(ts), "/"))
++        goto end;
++
++    (void) open_fifo(&fapolicyd_state);
++
++ end:
++    return RPMRC_OK;
++}
++
++static void fapolicyd_cleanup(rpmPlugin plugin)
++{
++    if (fapolicyd_state.fd > 0)
++        (void) close(fapolicyd_state.fd);
++
++    fapolicyd_state.fd = -1;
++}
++
++static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res)
++{
++    if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
++        goto end;
++
++    /* we are ready */
++    if (fapolicyd_state.fd > 0) {
++        /* send a signal that transaction is over */
++        (void) write_fifo(&fapolicyd_state, "1\n");
++        /* flush cache */
++        (void) write_fifo(&fapolicyd_state, "2\n");
++    }
++
++ end:
++    return RPMRC_OK;
++}
++
++static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name,
++                                     int type)
++{
++    if (fapolicyd_state.fd == -1)
++        goto end;
++
++    if (fapolicyd_state.changed_files > 0) {
++        /* send signal to flush cache */
++        (void) write_fifo(&fapolicyd_state, "2\n");
++
++        /* optimize flushing */
++        /* flush only when there was an actual change */
++        fapolicyd_state.changed_files = 0;
++    }
++
++ end:
++    return RPMRC_OK;
++}
++
++static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
++                                        const char *path, const char *dest,
++                                        mode_t file_mode, rpmFsmOp op)
++{
++    /* not ready  */
++    if (fapolicyd_state.fd == -1)
++        goto end;
++
++    rpmFileAction action = XFO_ACTION(op);
++
++    /* Ignore skipped files and unowned directories */
++    if (XFA_SKIPPING(action) || (op & FAF_UNOWNED)) {
++        rpmlog(RPMLOG_DEBUG, "fapolicyd skipping early: path %s dest %s\n",
++               path, dest);
++        goto end;
++    }
++
++    if (!S_ISREG(rpmfiFMode(fi))) {
++        rpmlog(RPMLOG_DEBUG, "fapolicyd skipping non regular: path %s dest %s\n",
++               path, dest);
++        goto end;
++    }
++
++    fapolicyd_state.changed_files++;
++
++    char buffer[4096];
++
++    rpm_loff_t size = rpmfiFSize(fi);
++    char * sha = rpmfiFDigestHex(fi, NULL);
++
++    snprintf(buffer, 4096, "%s %lu %64s\n", dest, size, sha);
++    (void) write_fifo(&fapolicyd_state, buffer);
++
++    free(sha);
++
++ end:
++    return RPMRC_OK;
++}
++
++struct rpmPluginHooks_s fapolicyd_hooks = {
++    .init = fapolicyd_init,
++    .cleanup = fapolicyd_cleanup,
++    .scriptlet_pre = fapolicyd_scriptlet_pre,
++    .tsm_post = fapolicyd_tsm_post,
++    .fsm_file_prepare = fapolicyd_fsm_file_prepare,
++};
+diff -up rpm-4.16.1.3/plugins/Makefile.am.orig rpm-4.16.1.3/plugins/Makefile.am
+--- rpm-4.16.1.3/plugins/Makefile.am.orig	2021-07-22 16:18:23.022890155 +0200
++++ rpm-4.16.1.3/plugins/Makefile.am	2021-07-22 16:18:55.797494098 +0200
+@@ -43,6 +43,12 @@ ima_la_LIBADD = $(top_builddir)/lib/libr
+ plugins_LTLIBRARIES += ima.la
+ endif
+ 
++if FAPOLICYD
++fapolicyd_la_sources = fapolicyd.c
++fapolicyd_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
++plugins_LTLIBRARIES += fapolicyd.la
++endif
++
+ if AUDIT
+ audit_la_sources = audit.c
+ audit_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la @WITH_AUDIT_LIB@
diff --git a/SOURCES/rpm-4.16.1.3-hashtab-use-after-free-fix.patch b/SOURCES/rpm-4.16.1.3-hashtab-use-after-free-fix.patch
new file mode 100644
index 0000000..eee3cc3
--- /dev/null
+++ b/SOURCES/rpm-4.16.1.3-hashtab-use-after-free-fix.patch
@@ -0,0 +1,13 @@
+diff -up rpm-4.16.1.3/tools/hashtab.c.orig rpm-4.16.1.3/tools/hashtab.c
+--- rpm-4.16.1.3/tools/hashtab.c.orig	2021-07-01 14:51:24.576237269 +0200
++++ rpm-4.16.1.3/tools/hashtab.c	2021-07-01 15:02:42.005754968 +0200
+@@ -292,7 +292,8 @@ htab_expand (htab)
+     }
+   while (p < olimit);
+ 
+-  free (oentries);
++  if (oentries != htab->entries)
++    free(oentries);
+   return 1;
+ }
+ 
diff --git a/SOURCES/rpm-4.16.1.3-imp-covscan-fixes.patch b/SOURCES/rpm-4.16.1.3-imp-covscan-fixes.patch
new file mode 100644
index 0000000..02d77cc
--- /dev/null
+++ b/SOURCES/rpm-4.16.1.3-imp-covscan-fixes.patch
@@ -0,0 +1,286 @@
+commit c7d7c5acd0c14d0450016887cba1d86483086794
+Author: Michal Domonkos <mdomonko@redhat.com>
+Date:   Mon Jun 21 10:05:10 2021 +0200
+
+    Add quoting to literal curly brackets
+    
+    These curly brackets are already treated as literals by the shell, so
+    let's make that explicit for clarity, and silence a ShellCheck warning
+    at the same time.
+    
+    More info: https://github.com/koalaman/shellcheck/wiki/SC1083
+    
+    Found by ShellCheck.
+
+    Adjusted for 4.16.1.3
+
+diff -up rpm-4.16.1.3/scripts/check-rpaths-worker.orig rpm-4.16.1.3/scripts/check-rpaths-worker
+--- rpm-4.16.1.3/scripts/check-rpaths-worker.orig	2021-06-29 15:34:31.671003589 +0200
++++ rpm-4.16.1.3/scripts/check-rpaths-worker	2021-06-29 15:34:51.993414093 +0200
+@@ -120,13 +120,13 @@ for i; do
+ 	        (/lib64/*|/usr/lib64/*|/usr/X11R6/lib64/*|/usr/local/lib64/*)
+ 		    badness=0;;
+ 
+-		(\$ORIGIN|\${ORIGINX}|\$ORIGIN/*|\${ORIGINX}/*)
++		(\$ORIGIN|\$\{ORIGINX\}|\$ORIGIN/*|\$\{ORIGINX\}/*)
+ 		    test $allow_ORIGIN -eq 0 && badness=8 || {
+ 			badness=0
+ 			new_allow_ORIGIN=1
+ 		    }
+ 		    ;;
+-		(/*\$PLATFORM*|/*\${PLATFORM}*|/*\$LIB*|/*\${LIB}*)
++		(/*\$PLATFORM*|/*\$\{PLATFORM\}*|/*\$LIB*|/*\$\{LIB\}*)
+ 		    badness=0;;
+ 	    	
+ 	        (/lib|/usr/lib|/usr/X11R6/lib)
+From d8dc4fd37b1d90cd97de7fcf484d449ec132c9b3 Mon Sep 17 00:00:00 2001
+From: Michal Domonkos <mdomonko@redhat.com>
+Date: Wed, 9 Jun 2021 21:31:40 +0200
+Subject: [PATCH 1/7] Fix memory leak in sqlexec()
+
+Callers are supposed to free the error strings themselves:
+https://www.sqlite.org/capi3ref.html#sqlite3_exec
+
+Found by Coverity.
+---
+ lib/backend/sqlite.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/lib/backend/sqlite.c b/lib/backend/sqlite.c
+index 7c2de45aa..dbefeb163 100644
+--- a/lib/backend/sqlite.c
++++ b/lib/backend/sqlite.c
+@@ -233,6 +233,7 @@ static int sqlexec(sqlite3 *sdb, const char *fmt, ...)
+ 	rpmlog(RPMLOG_DEBUG, "%s: %d\n", cmd, rc);
+ 
+     sqlite3_free(cmd);
++    sqlite3_free(err);
+ 
+     return rc ? RPMRC_FAIL : RPMRC_OK;
+ }
+-- 
+2.31.1
+
+From 5baf73feb4951cc3b3f553a4b18d3b3599cbf87c Mon Sep 17 00:00:00 2001
+From: Michal Domonkos <mdomonko@redhat.com>
+Date: Fri, 25 Jun 2021 11:21:46 +0200
+Subject: [PATCH 2/7] Always free the arg list passed to rpmGlob()
+
+Even though the actual implementation of rpmGlob() does not allocate the
+passed arg list (av) if the return code (rc) is non-zero or arg count
+(ac) is 0, it's the responsibility of the caller (rpmInstall() here) to
+free that memory, so make sure we do that irrespectively of the above
+conditions.
+
+Found by Coverity.
+---
+ lib/rpminstall.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/lib/rpminstall.c b/lib/rpminstall.c
+index 724126e94..302ec0ba1 100644
+--- a/lib/rpminstall.c
++++ b/lib/rpminstall.c
+@@ -461,6 +461,7 @@ int rpmInstall(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_t fileArgv)
+ 		rpmlog(RPMLOG_ERR, _("File not found by glob: %s\n"), *eiu->fnp);
+ 	    }
+ 	    eiu->numFailed++;
++	    argvFree(av);
+ 	    continue;
+ 	}
+ 
+-- 
+2.31.1
+
+From 3c8b01b67ec907afaaffe71691fa41b878578527 Mon Sep 17 00:00:00 2001
+From: Michal Domonkos <mdomonko@redhat.com>
+Date: Mon, 14 Jun 2021 10:21:25 +0200
+Subject: [PATCH 3/7] Fix resource leak in Fts_children()
+
+This function is not used anywhere within our codebase (and neither is
+it part of the public API) so it's basically a no-op... Still, rather
+than yanking it completely, let's just silence the Coverity error here.
+
+Found by Coverity.
+---
+ misc/fts.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/misc/fts.c b/misc/fts.c
+index d3ebb2946..caf27495d 100644
+--- a/misc/fts.c
++++ b/misc/fts.c
+@@ -585,8 +585,10 @@ Fts_children(FTS * sp, int instr)
+ 	if ((fd = __open(".", O_RDONLY, 0)) < 0)
+ 		return (NULL);
+ 	sp->fts_child = fts_build(sp, instr);
+-	if (__fchdir(fd))
++	if (__fchdir(fd)) {
++		(void)__close(fd);
+ 		return (NULL);
++	}
+ 	(void)__close(fd);
+ 	return (sp->fts_child);
+ }
+-- 
+2.31.1
+
+From 39b7bf8579e0522cf16347b3a7e332d3b6d742c6 Mon Sep 17 00:00:00 2001
+From: Michal Domonkos <mdomonko@redhat.com>
+Date: Mon, 14 Jun 2021 12:34:23 +0200
+Subject: [PATCH 4/7] Fix memory leak in fts_build()
+
+Turns out this leak is already fixed in glibc's current version of fts.c
+(where our copy originates from), so let's just backport that.
+
+Original commit in glibc:
+https://sourceware.org/git/?p=glibc.git;\
+a=commit;h=db67c2c98b89a5723af44df54f38b779de8d4a65
+
+Found by Coverity.
+---
+ misc/fts.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/misc/fts.c b/misc/fts.c
+index caf27495d..f7fce0eaa 100644
+--- a/misc/fts.c
++++ b/misc/fts.c
+@@ -855,6 +855,7 @@ mem1:				saved_errno = errno;
+ 	     fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
+ 		cur->fts_info = FTS_ERR;
+ 		SET(FTS_STOP);
++		fts_lfree(head);
+ 		return (NULL);
+ 	}
+ 
+@@ -862,6 +863,7 @@ mem1:				saved_errno = errno;
+ 	if (!nitems) {
+ 		if (type == BREAD)
+ 			cur->fts_info = FTS_DP;
++		fts_lfree(head);
+ 		return (NULL);
+ 	}
+ 
+-- 
+2.31.1
+
+From 9c093c4f092dd6bd1e0c8d2b852a72b74db076c2 Mon Sep 17 00:00:00 2001
+From: Michal Domonkos <mdomonko@redhat.com>
+Date: Tue, 15 Jun 2021 13:34:21 +0200
+Subject: [PATCH 5/7] Fix memory leak in decodePkts()
+
+Found by Coverity.
+---
+ rpmio/rpmpgp.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index c59185dce..ee5c81e24 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -1371,9 +1371,13 @@ static pgpArmor decodePkts(uint8_t *b, uint8_t **pkt, size_t *pktlen)
+ 	    crc = pgpCRC(dec, declen);
+ 	    if (crcpkt != crc) {
+ 		ec = PGPARMOR_ERR_CRC_CHECK;
++		_free(dec);
+ 		goto exit;
+ 	    }
+-	    if (pkt) *pkt = dec;
++	    if (pkt)
++		*pkt = dec;
++	    else
++		_free(dec);
+ 	    if (pktlen) *pktlen = declen;
+ 	    ec = PGPARMOR_PUBKEY;	/* XXX ASCII Pubkeys only, please. */
+ 	    goto exit;
+-- 
+2.31.1
+
+From 590b2fc06252567eb7d57197dc361a8b459d62a3 Mon Sep 17 00:00:00 2001
+From: Michal Domonkos <mdomonko@redhat.com>
+Date: Mon, 21 Jun 2021 17:51:14 +0200
+Subject: [PATCH 6/7] Fix memory leak with multiple %lang-s in one line
+
+We permit two equivalent forms of specifying a list of languages per
+file:
+
+  %lang(xx,yy,zz) /path/to/file
+  %lang(xx) %lang(yy) %lang(zz) /path/to/file
+
+The leak was when parsing the second form.
+
+Found by Coverity.
+---
+ build/files.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/build/files.c b/build/files.c
+index f8153ad2b..0c8859f6c 100644
+--- a/build/files.c
++++ b/build/files.c
+@@ -777,6 +777,8 @@ static rpmRC parseForLang(char * buf, FileEntry cur)
+ 
+ 	if (*pe == ',') pe++;	/* skip , if present */
+     }
++
++    q = _free(q);
+   }
+ 
+     rc = RPMRC_OK;
+-- 
+2.31.1
+
+From b7a1e996326ee29a163d67ceb1e6127fdc251c14 Mon Sep 17 00:00:00 2001
+From: Michal Domonkos <mdomonko@redhat.com>
+Date: Fri, 25 Jun 2021 15:15:08 +0200
+Subject: [PATCH 7/7] Fix memory leaks in Lua rex extension
+
+This covers the following usage:
+
+expr = rex.newPOSIX(<regex>)
+expr:match(<string>)           # A leak occurred here
+expr:gmatch(<string>, <func>)  # A leak occurred here
+
+Found by Coverity.
+---
+ luaext/lrexlib.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/luaext/lrexlib.c b/luaext/lrexlib.c
+index 09c5a6454..0f29b6371 100644
+--- a/luaext/lrexlib.c
++++ b/luaext/lrexlib.c
+@@ -80,6 +80,7 @@ static void rex_push_matches(lua_State *L, const char *text, regmatch_t *match,
+ 
+ static int rex_match(lua_State *L)
+ {
++  int rc = 0;
+   int res;
+ #ifdef REG_BASIC
+   size_t len;
+@@ -109,9 +110,10 @@ static int rex_match(lua_State *L)
+     lua_pushstring(L, "n");
+     lua_pushnumber(L, ncapt);
+     lua_rawset(L, -3);
+-    return 3;
+-  } else
+-    return 0;
++    rc = 3;
++  }
++  free(match);
++  return rc;
+ }
+ 
+ static int rex_gmatch(lua_State *L)
+@@ -158,6 +160,7 @@ static int rex_gmatch(lua_State *L)
+       break;
+   }
+   lua_pushnumber(L, nmatch);
++  free(match);
+   return 1;
+ }
+ 
+-- 
+2.31.1
+
diff --git a/SOURCES/rpm-4.16.1.3-rpmsign-support-EdDSA-sig.patch b/SOURCES/rpm-4.16.1.3-rpmsign-support-EdDSA-sig.patch
new file mode 100644
index 0000000..12507fe
--- /dev/null
+++ b/SOURCES/rpm-4.16.1.3-rpmsign-support-EdDSA-sig.patch
@@ -0,0 +1,20 @@
+commit 23770e1a4f28c56a31fe600cae332c77333b60b6
+Author: Demi Marie Obenour <athena@invisiblethingslab.com>
+Date:   Sat Mar 6 03:23:41 2021 -0500
+
+    rpmsign: support EdDSA signatures
+    
+    They were previously rejected
+
+diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
+index 28cd91576..d8c84e937 100644
+--- a/sign/rpmgensig.c
++++ b/sign/rpmgensig.c
+@@ -155,6 +155,7 @@ static rpmtd makeSigTag(Header sigh, int ishdr, uint8_t *pkt, size_t pktlen)
+     pubkey_algo = pgpDigParamsAlgo(sigp, PGPVAL_PUBKEYALGO);
+     switch (pubkey_algo) {
+     case PGPPUBKEYALGO_DSA:
++    case PGPPUBKEYALGO_EDDSA:
+ 	sigtag = ishdr ? RPMSIGTAG_DSA : RPMSIGTAG_GPG;
+ 	break;
+     case PGPPUBKEYALGO_RSA:
diff --git a/SOURCES/rpm-4.16.1.3-unblock-signals-in-forked-scriptlets.patch b/SOURCES/rpm-4.16.1.3-unblock-signals-in-forked-scriptlets.patch
new file mode 100644
index 0000000..55713ed
--- /dev/null
+++ b/SOURCES/rpm-4.16.1.3-unblock-signals-in-forked-scriptlets.patch
@@ -0,0 +1,32 @@
+commit cb6aa82dbc10d554f8d234e934ae7c77e39a3ce2
+Author: Panu Matilainen <pmatilai@redhat.com>
+Date:   Tue Jan 12 13:35:23 2021 +0200
+
+    Unblock signals in forked scriptlets
+    
+    Since commit c5f82d3f6223ebd0c5cc0a07ea60393ae7284929 we've blocked
+    most signals during transactions, which makes sense to rpm itself but
+    the signal mask is inherited to childs and carried even across exec(),
+    so all scriptlets are executing with those signals blocked as well.
+    Which in turn does not make sense, the scriptlets could run stuff that
+    actually depends on signal delivery (such as SIGALARM in RhBug:1913765).
+    
+    Unblock all signals for forked scriptlet execution (Lua scriptlets are
+    totally different as they execute in-process for now)
+
+diff --git a/lib/rpmscript.c b/lib/rpmscript.c
+index 2ae3378f7..c69d29554 100644
+--- a/lib/rpmscript.c
++++ b/lib/rpmscript.c
+@@ -152,6 +152,11 @@ static void doScriptExec(ARGV_const_t argv, ARGV_const_t prefixes,
+ 			FD_t scriptFd, FD_t out)
+ {
+     int xx;
++    sigset_t set;
++
++    /* Unmask all signals, the scripts may need them */
++    sigfillset(&set);
++    sigprocmask(SIG_UNBLOCK, &set, NULL);
+ 
+     /* SIGPIPE is ignored in rpm, reset to default for the scriptlet */
+     (void) signal(SIGPIPE, SIG_DFL);
diff --git a/SOURCES/rpm-4.7.1-geode-i686.patch b/SOURCES/rpm-4.7.1-geode-i686.patch
new file mode 100644
index 0000000..2e8692a
--- /dev/null
+++ b/SOURCES/rpm-4.7.1-geode-i686.patch
@@ -0,0 +1,14 @@
+diff --git a/rpmrc.in b/rpmrc.in
+index 4a6cca9..d62ddaf 100644
+--- a/rpmrc.in
++++ b/rpmrc.in
+@@ -281,7 +281,7 @@ arch_compat: alphaev5: alpha
+ arch_compat: alpha: axp noarch
+ 
+ arch_compat: athlon: i686
+-arch_compat: geode: i586
++arch_compat: geode: i686
+ arch_compat: pentium4: pentium3
+ arch_compat: pentium3: i686
+ arch_compat: i686: i586
+
diff --git a/SOURCES/rpm-4.9.90-no-man-dirs.patch b/SOURCES/rpm-4.9.90-no-man-dirs.patch
new file mode 100644
index 0000000..04f276a
--- /dev/null
+++ b/SOURCES/rpm-4.9.90-no-man-dirs.patch
@@ -0,0 +1,12 @@
+diff -up rpm-4.9.90.git11486/scripts/find-lang.sh.no-man-dirs rpm-4.9.90.git11486/scripts/find-lang.sh
+--- rpm-4.9.90.git11486/scripts/find-lang.sh.no-man-dirs	2012-03-07 11:31:10.000000000 +0200
++++ rpm-4.9.90.git11486/scripts/find-lang.sh	2012-03-07 15:11:57.465801075 +0200
+@@ -181,7 +181,7 @@ s:%lang(C) ::
+ find "$TOP_DIR" -type d|sed '
+ s:'"$TOP_DIR"'::
+ '"$ALL_NAME$MAN"'s:\(.*/man/\([^/_]\+\).*/man[a-z0-9]\+/\)::
+-'"$ALL_NAME$MAN"'s:\(.*/man/\([^/_]\+\).*/man[a-z0-9]\+$\):%lang(\2) \1*:
++'"$ALL_NAME$MAN"'s:\(.*/man/\([^/_]\+\).*/man[a-z0-9]\+$\):%lang(\2) \1/*:
+ s:^\([^%].*\)::
+ s:%lang(C) ::
+ /^$/d' >> $MO_NAME
diff --git a/SOURCES/rpmdb-rebuild.service b/SOURCES/rpmdb-rebuild.service
new file mode 100644
index 0000000..0580adb
--- /dev/null
+++ b/SOURCES/rpmdb-rebuild.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=RPM database rebuild
+ConditionPathExists=/var/lib/rpm/.rebuilddb
+
+# This should run before any daemons that may open the rpmdb
+DefaultDependencies=no
+After=sysinit.target
+Before=basic.target shutdown.target
+Conflicts=shutdown.target
+# In case /var is remote-mounted
+RequiresMountsFor=/var
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/rpmdb --rebuilddb
+ExecStartPost=rm -f /var/lib/rpm/.rebuilddb
+
+[Install]
+WantedBy=basic.target
diff --git a/SPECS/rpm.spec b/SPECS/rpm.spec
new file mode 100644
index 0000000..a383e91
--- /dev/null
+++ b/SPECS/rpm.spec
@@ -0,0 +1,1075 @@
+
+# run internal testsuite?
+# fakechroot is severely broken beyond fedora 33, disable...
+%if 0%{?fedora} > 33 || 0%{?rhel} > 8
+%bcond_with check
+%else
+%bcond_without check
+%endif
+
+# build against xz?
+%bcond_without xz
+# build with plugins?
+%bcond_without plugins
+# build with libarchive? (needed for rpm2archive)
+%bcond_without libarchive
+# build with libimaevm.so
+%bcond_without libimaevm
+# build with zstd support?
+%bcond_without zstd
+# build with ndb backend?
+%bcond_without ndb
+# build with sqlite support?
+%bcond_without sqlite
+# build with bdb support?
+%bcond_with bdb
+# build with internal Berkeley DB?
+%bcond_with int_bdb
+# build with bdb_ro support?
+%bcond_without bdb_ro
+
+%define rpmhome /usr/lib/rpm
+
+%global rpmver 4.16.1.3
+#global snapver rc1
+%global rel 7
+%global sover 9
+
+%global srcver %{rpmver}%{?snapver:-%{snapver}}
+%global srcdir %{?snapver:testing}%{!?snapver:rpm-%(echo %{rpmver} | cut -d'.' -f1-2).x}
+
+%if %{with bdb}
+%define bdbver 5.3.15
+
+# Build-dependency on systemd for the sake of one macro would be a bit much...
+%{!?_tmpfilesdir:%global _tmpfilesdir /usr/lib/tmpfiles.d}
+%endif
+
+Summary: The RPM package management system
+Name: rpm
+Version: %{rpmver}
+Release: %{?snapver:0.%{snapver}.}%{rel}%{?dist}
+Url: http://www.rpm.org/
+Source0: http://ftp.rpm.org/releases/%{srcdir}/rpm-%{srcver}.tar.bz2
+%if %{with bdb} && %{with int_bdb}
+Source1: db-%{bdbver}.tar.gz
+%endif
+
+Source10: rpmdb-rebuild.service
+
+# Disable autoconf config.site processing (#962837)
+Patch1: rpm-4.15.x-siteconfig.patch
+# In current Fedora, man-pages pkg owns all the localized man directories
+Patch3: rpm-4.9.90-no-man-dirs.patch
+# Temporary band-aid for rpm2cpio whining on payload size mismatch (#1142949)
+Patch5: rpm-4.12.0-rpm2cpio-hack.patch
+# https://github.com/rpm-software-management/rpm/pull/473
+Patch6: 0001-find-debuginfo.sh-decompress-DWARF-compressed-ELF-se.patch
+Patch7: 0001-Issue-deprecation-warning-when-creating-BDB-database.patch
+
+# Patches already upstream:
+Patch100: rpm-4.16.1.3-imp-covscan-fixes.patch
+Patch101: rpm-4.16.1.3-rpmsign-support-EdDSA-sig.patch
+Patch102: rpm-4.16.1.3-add-fapolicyd-plugin.patch
+Patch103: rpm-4.16.1.3-unblock-signals-in-forked-scriptlets.patch
+
+# These are not yet upstream
+Patch906: rpm-4.7.1-geode-i686.patch
+# Probably to be upstreamed in slightly different form
+Patch907: rpm-4.15.x-ldflags.patch
+
+# Not yet (all) upstream, debugedit DWARF5
+# https://code.wildebeest.org/git/user/mjw/rpm/log/?h=gcc-dwarf5-4.16.1.2
+Patch911: 0001-NFC-debugedit-Protect-macro-arguments-by-parentheses.patch
+Patch912: 0002-NFC-debugedit-Move-code-from-edit_dwarf2-to-edit_inf.patch
+Patch913: 0003-debugedit-Fix-missing-relocation-of-.debug_types-sec.patch
+Patch914: 0004-NFC-debugedit-Move-code-to-separate-functions.patch
+Patch915: 0005-debugedit-Implement-DWARF-5-unit-header-and-new-form.patch
+Patch916: 0006-debugedit-Handle-DWARF-5-debug_line-and-debug_line_s.patch
+
+# Downstream-only patches
+Patch1000: rpm-4.16.1.3-hashtab-use-after-free-fix.patch
+
+# Partially GPL/LGPL dual-licensed and some bits with BSD
+# SourceLicense: (GPLv2+ and LGPLv2+ with exceptions) and BSD
+License: GPLv2+
+
+Requires: coreutils
+Requires: popt%{_isa} >= 1.10.2.1
+Requires: curl
+Obsoletes: python2-rpm < %{version}-%{release}
+
+%if %{with bdb} && %{without int_bdb}
+BuildRequires: libdb-devel
+%endif
+
+%if %{with check}
+BuildRequires: fakechroot gnupg2
+%endif
+
+# XXX generally assumed to be installed but make it explicit as rpm
+# is a bit special...
+BuildRequires: redhat-rpm-config >= 94
+BuildRequires: systemd-rpm-macros
+BuildRequires: gcc make
+BuildRequires: gawk
+BuildRequires: elfutils-devel >= 0.112
+BuildRequires: elfutils-libelf-devel
+BuildRequires: readline-devel zlib-devel
+BuildRequires: openssl-devel
+# The popt version here just documents an older known-good version
+BuildRequires: popt-devel >= 1.10.2
+BuildRequires: file-devel
+BuildRequires: gettext-devel
+BuildRequires: ncurses-devel
+BuildRequires: bzip2-devel >= 0.9.0c-2
+BuildRequires: lua-devel >= 5.1
+BuildRequires: libcap-devel
+BuildRequires: libacl-devel
+%if %{with xz}
+BuildRequires: xz-devel >= 4.999.8
+%endif
+%if %{with libarchive}
+BuildRequires: libarchive-devel
+%endif
+%if %{with zstd}
+BuildRequires: libzstd-devel
+%endif
+%if %{with sqlite}
+BuildRequires: sqlite-devel
+%endif
+# Couple of patches change makefiles so, require for now...
+BuildRequires: automake libtool
+
+%if %{with plugins}
+BuildRequires: libselinux-devel
+BuildRequires: dbus-devel
+BuildRequires: audit-libs-devel
+%endif
+
+%if %{with libimaevm}
+BuildRequires: ima-evm-utils-devel >= 1.0
+%endif
+
+%description
+The RPM Package Manager (RPM) is a powerful command line driven
+package management system capable of installing, uninstalling,
+verifying, querying, and updating software packages. Each software
+package consists of an archive of files along with information about
+the package like its version, a description, etc.
+
+%package libs
+Summary:  Libraries for manipulating RPM packages
+License: GPLv2+ and LGPLv2+ with exceptions
+Requires: %{name} = %{version}-%{release}
+
+%description libs
+This package contains the RPM shared libraries.
+
+%package build-libs
+Summary:  Libraries for building RPM packages
+License: GPLv2+ and LGPLv2+ with exceptions
+Requires: rpm-libs%{_isa} = %{version}-%{release}
+
+%description build-libs
+This package contains the RPM shared libraries for building packages.
+
+%package sign-libs
+Summary:  Libraries for signing RPM packages
+License: GPLv2+ and LGPLv2+ with exceptions
+Requires: rpm-libs%{_isa} = %{version}-%{release}
+Requires: %{_bindir}/gpg2
+
+%description sign-libs
+This package contains the RPM shared libraries for signing packages.
+
+%package devel
+Summary:  Development files for manipulating RPM packages
+License: GPLv2+ and LGPLv2+ with exceptions
+Requires: %{name} = %{version}-%{release}
+Requires: %{name}-libs%{_isa} = %{version}-%{release}
+Requires: %{name}-build-libs%{_isa} = %{version}-%{release}
+Requires: %{name}-sign-libs%{_isa} = %{version}-%{release}
+Requires: popt-devel%{_isa}
+
+%description devel
+This package contains the RPM C library and header files. These
+development files will simplify the process of writing programs that
+manipulate RPM packages and databases. These files are intended to
+simplify the process of creating graphical package managers or any
+other tools that need an intimate knowledge of RPM packages in order
+to function.
+
+This package should be installed if you want to develop programs that
+will manipulate RPM packages and databases.
+
+%package build
+Summary: Scripts and executable programs used to build packages
+Requires: rpm = %{version}-%{release}
+Requires: elfutils >= 0.128 binutils
+Requires: findutils sed grep gawk diffutils file patch >= 2.5
+Requires: tar unzip gzip bzip2 cpio xz
+%if %{with zstd}
+Requires: zstd
+%endif
+Requires: pkgconfig >= 1:0.24
+Requires: /usr/bin/gdb-add-index
+# https://fedoraproject.org/wiki/Changes/Minimal_GDB_in_buildroot
+Suggests: gdb-minimal
+# Technically rpmbuild doesn't require any external configuration, but
+# creating distro-compatible packages does. To make the common case
+# "just work" while allowing for alternatives, depend on a virtual
+# provide, typically coming from redhat-rpm-config.
+Requires: system-rpm-config
+
+%description build
+The rpm-build package contains the scripts and executable programs
+that are used to build packages using the RPM Package Manager.
+
+%package sign
+Summary: Package signing support
+Requires: rpm-sign-libs%{_isa} = %{version}-%{release}
+
+%description sign
+This package contains support for digitally signing RPM packages.
+
+%package -n python3-%{name}
+Summary: Python 3 bindings for apps which will manipulate RPM packages
+BuildRequires: python3-devel
+%{?python_provide:%python_provide python3-%{name}}
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
+Provides: %{name}-python3 = %{version}-%{release}
+Obsoletes: %{name}-python3 < %{version}-%{release}
+Obsoletes: platform-python-%{name} < %{version}-%{release}
+
+%description -n python3-%{name}
+The python3-rpm package contains a module that permits applications
+written in the Python programming language to use the interface
+supplied by RPM Package Manager libraries.
+
+This package should be installed if you want to develop Python 3
+programs that will manipulate RPM packages and databases.
+
+%package apidocs
+Summary: API documentation for RPM libraries
+BuildArch: noarch
+
+%description apidocs
+This package contains API documentation for developing applications
+that will manipulate RPM packages and databases.
+
+%package cron
+Summary: Create daily logs of installed packages.
+BuildArch: noarch
+Requires: crontabs logrotate rpm = %{version}-%{release}
+
+%description cron
+This package contains a cron job which creates daily logs of installed
+packages on a system.
+
+%if %{with plugins}
+%package plugin-selinux
+Summary: Rpm plugin for SELinux functionality
+Requires: rpm-libs%{_isa} = %{version}-%{release}
+Requires: selinux-policy-base
+
+%description plugin-selinux
+%{summary}.
+
+%package plugin-syslog
+Summary: Rpm plugin for syslog functionality
+Requires: rpm-libs%{_isa} = %{version}-%{release}
+
+%description plugin-syslog
+%{summary}.
+
+%package plugin-systemd-inhibit
+Summary: Rpm plugin for systemd inhibit functionality
+Requires: rpm-libs%{_isa} = %{version}-%{release}
+
+%description plugin-systemd-inhibit
+This plugin blocks systemd from entering idle, sleep or shutdown while an rpm
+transaction is running using the systemd-inhibit mechanism.
+
+%package plugin-ima
+Summary: Rpm plugin ima file signatures
+Requires: rpm-libs%{_isa} = %{version}-%{release}
+
+%description plugin-ima
+%{summary}.
+
+%package plugin-fapolicyd
+Summary: Rpm plugin for fapolicyd functionality
+Requires: rpm-libs%{_isa} = %{version}-%{release}
+Provides: fapolicyd-plugin
+Obsoletes: fapolicyd-dnf-plugin
+
+%description plugin-fapolicyd
+%{summary}.
+
+%package plugin-prioreset
+Summary: Rpm plugin for resetting scriptlet priorities for SysV init
+Requires: rpm-libs%{_isa} = %{version}-%{release}
+
+%description plugin-prioreset
+%{summary}.
+
+Useful on legacy SysV init systems if you run rpm transactions with
+nice/ionice priorities. Should not be used on systemd systems.
+
+%package plugin-audit
+Summary: Rpm plugin for logging audit events on package operations
+Requires: rpm-libs%{_isa} = %{version}-%{release}
+
+%description plugin-audit
+%{summary}.
+
+# with plugins
+%endif
+
+%prep
+%autosetup -n rpm-%{srcver} %{?with_int_bdb:-a 1} -p1
+
+%if %{with bdb} && %{with int_bdb}
+ln -s db-%{bdbver} db
+%endif
+
+# switch to sqlite db by default, including during build-time tests
+%if %{with sqlite}
+sed -i -e "/_db_backend/ s/ bdb/ sqlite/g" macros.in
+%endif
+
+%build
+%set_build_flags
+
+autoreconf -i -f
+
+# Hardening hack taken from macro %%configure defined in redhat-rpm-config
+for i in $(find . -name ltmain.sh) ; do
+     %{__sed} -i.backup -e 's~compiler_flags=$~compiler_flags="%{_hardened_ldflags}"~' $i
+done;
+
+# Using configure macro has some unwanted side-effects on rpm platform
+# setup, use the old-fashioned way for now only defining minimal paths.
+./configure \
+    --prefix=%{_usr} \
+    --sysconfdir=%{_sysconfdir} \
+    --localstatedir=%{_var} \
+    --sharedstatedir=%{_var}/lib \
+    --libdir=%{_libdir} \
+    --build=%{_target_platform} \
+    --host=%{_target_platform} \
+    --with-vendor=redhat \
+    --enable-bdb=%{?with_bdb:yes}%{!?with_bdb:no} \
+    %{!?with_int_bdb: --with-external-db} \
+    %{!?with_plugins: --disable-plugins} \
+    --with-lua \
+    --with-selinux \
+    --with-cap \
+    --with-acl \
+    %{?with_ndb: --enable-ndb} \
+    %{?with_libimaevm: --with-imaevm} \
+    %{?with_zstd: --enable-zstd} \
+    %{?with_sqlite: --enable-sqlite} \
+    %{?with_bdb_ro: --enable-bdb-ro} \
+    --with-fapolicyd \
+    --enable-python \
+    --with-crypto=openssl
+
+%make_build
+
+pushd python
+%py3_build
+popd
+
+%install
+%make_install
+
+# We need to build with --enable-python for the self-test suite, but we
+# actually package the bindings built with setup.py (#531543#c26)
+pushd python
+%py3_install
+popd
+
+mkdir -p $RPM_BUILD_ROOT%{_unitdir}
+install -m 644 %{SOURCE10} $RPM_BUILD_ROOT/%{_unitdir}
+
+# Save list of packages through cron
+mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/cron.daily
+install -m 755 scripts/rpm.daily ${RPM_BUILD_ROOT}%{_sysconfdir}/cron.daily/rpm
+
+mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d
+install -m 644 scripts/rpm.log ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/rpm
+
+%if %{with bdb}
+mkdir -p ${RPM_BUILD_ROOT}%{_tmpfilesdir}
+echo "r /var/lib/rpm/__db.*" > ${RPM_BUILD_ROOT}%{_tmpfilesdir}/rpm.conf
+%endif
+
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/rpm
+mkdir -p $RPM_BUILD_ROOT%{rpmhome}/macros.d
+mkdir -p $RPM_BUILD_ROOT/var/lib/rpm
+
+# init an empty database for %ghost'ing for all supported backends
+for be in %{?with_ndb:ndb} %{?with_sqlite:sqlite} %{?with_bdb:bdb}; do
+    ./rpmdb --define "_db_backend ${be}" --dbpath=${PWD}/${be} --initdb
+    cp -va ${be}/. $RPM_BUILD_ROOT/var/lib/rpm/
+done
+
+%find_lang rpm
+
+find $RPM_BUILD_ROOT -name "*.la"|xargs rm -f
+
+# These live in perl-generators and python-rpm-generators now
+rm -f $RPM_BUILD_ROOT/%{rpmhome}/{perldeps.pl,perl.*,pythond*}
+rm -f $RPM_BUILD_ROOT/%{_fileattrsdir}/{perl*,python*}
+rm -rf $RPM_BUILD_ROOT/var/tmp
+
+%if %{with check}
+%check
+make check TESTSUITEFLAGS=-j%{_smp_build_ncpus} || (cat tests/rpmtests.log; exit 1)
+# rpm >= 4.16.0 testsuite leaves a read-only tree behind, clean it up
+make clean
+%endif
+
+# Handle rpmdb rebuild service on erasure of old to avoid ordering issues
+# https://pagure.io/fesco/issue/2382
+%triggerun -- rpm < 4.15.90-0.git14971.10
+if [ -x /usr/bin/systemctl ]; then
+    systemctl --no-reload preset rpmdb-rebuild ||:
+fi
+
+%posttrans
+if [ -f /var/lib/rpm/Packages ]; then
+    touch /var/lib/rpm/.rebuilddb
+fi
+
+%files -f rpm.lang
+%license COPYING
+%doc CREDITS doc/manual/[a-z]*
+
+%if %{with bdb}
+%{_tmpfilesdir}/rpm.conf
+%endif
+
+%{_unitdir}/rpmdb-rebuild.service
+
+%dir %{_sysconfdir}/rpm
+
+%attr(0755, root, root) %dir /var/lib/rpm
+%attr(0644, root, root) %ghost %config(missingok,noreplace) /var/lib/rpm/*
+%attr(0644, root, root) %ghost /var/lib/rpm/.*.lock
+
+%{_bindir}/rpm
+%{_bindir}/rpm2archive
+%{_bindir}/rpm2cpio
+%{_bindir}/rpmdb
+%{_bindir}/rpmkeys
+%{_bindir}/rpmquery
+%{_bindir}/rpmverify
+
+%{_mandir}/man8/rpm.8*
+%{_mandir}/man8/rpmdb.8*
+%{_mandir}/man8/rpmkeys.8*
+%{_mandir}/man8/rpm2archive.8*
+%{_mandir}/man8/rpm2cpio.8*
+%{_mandir}/man8/rpm-misc.8*
+%{_mandir}/man8/rpm-plugins.8*
+
+# XXX this places translated manuals to wrong package wrt eg rpmbuild
+%lang(fr) %{_mandir}/fr/man[18]/*.[18]*
+%lang(ko) %{_mandir}/ko/man[18]/*.[18]*
+%lang(ja) %{_mandir}/ja/man[18]/*.[18]*
+%lang(pl) %{_mandir}/pl/man[18]/*.[18]*
+%lang(ru) %{_mandir}/ru/man[18]/*.[18]*
+%lang(sk) %{_mandir}/sk/man[18]/*.[18]*
+
+%attr(0755, root, root) %dir %{rpmhome}
+%{rpmhome}/macros
+%{rpmhome}/macros.d
+%{rpmhome}/lua
+%{rpmhome}/rpmpopt*
+%{rpmhome}/rpmrc
+
+%{rpmhome}/rpmdb_*
+%{rpmhome}/rpm.daily
+%{rpmhome}/rpm.log
+%{rpmhome}/rpm.supp
+%{rpmhome}/rpm2cpio.sh
+%{rpmhome}/tgpg
+
+%{rpmhome}/platform
+
+%dir %{rpmhome}/fileattrs
+
+%files libs
+%{_libdir}/librpmio.so.%{sover}
+%{_libdir}/librpm.so.%{sover}
+%{_libdir}/librpmio.so.%{sover}.*
+%{_libdir}/librpm.so.%{sover}.*
+%if %{with plugins}
+%dir %{_libdir}/rpm-plugins
+
+%files plugin-syslog
+%{_libdir}/rpm-plugins/syslog.so
+%{_mandir}/man8/rpm-plugin-syslog.8*
+
+%files plugin-selinux
+%{_libdir}/rpm-plugins/selinux.so
+%{_mandir}/man8/rpm-plugin-selinux.8*
+
+%files plugin-systemd-inhibit
+%{_libdir}/rpm-plugins/systemd_inhibit.so
+%{_mandir}/man8/rpm-plugin-systemd-inhibit.8*
+
+%files plugin-ima
+%{_libdir}/rpm-plugins/ima.so
+%{_mandir}/man8/rpm-plugin-ima.8*
+
+%files plugin-fapolicyd
+%{_libdir}/rpm-plugins/fapolicyd.so
+%{_mandir}/man8/rpm-plugin-fapolicyd.8*
+
+%files plugin-prioreset
+%{_libdir}/rpm-plugins/prioreset.so
+%{_mandir}/man8/rpm-plugin-prioreset.8*
+
+%files plugin-audit
+%{_libdir}/rpm-plugins/audit.so
+%{_mandir}/man8/rpm-plugin-audit.8*
+# with plugins
+%endif
+
+%files build-libs
+%{_libdir}/librpmbuild.so.%{sover}
+%{_libdir}/librpmbuild.so.%{sover}.*
+
+%files sign-libs
+%{_libdir}/librpmsign.so.%{sover}
+%{_libdir}/librpmsign.so.%{sover}.*
+
+%files build
+%{_bindir}/rpmbuild
+%{_bindir}/gendiff
+%{_bindir}/rpmspec
+
+%{_mandir}/man1/gendiff.1*
+%{_mandir}/man8/rpmbuild.8*
+%{_mandir}/man8/rpmdeps.8*
+%{_mandir}/man8/rpmspec.8*
+
+%{rpmhome}/brp-*
+%{rpmhome}/check-*
+%{rpmhome}/debugedit
+%{rpmhome}/sepdebugcrcfix
+%{rpmhome}/find-debuginfo.sh
+%{rpmhome}/find-lang.sh
+%{rpmhome}/*provides*
+%{rpmhome}/*requires*
+%{rpmhome}/*deps*
+%{rpmhome}/*.prov
+%{rpmhome}/*.req
+%{rpmhome}/mkinstalldirs
+%{rpmhome}/fileattrs/*
+
+%files sign
+%{_bindir}/rpmsign
+%{_mandir}/man8/rpmsign.8*
+
+%files -n python3-%{name}
+%{python3_sitearch}/rpm/
+%{python3_sitearch}/rpm-%{rpmver}*.egg-info
+
+%files devel
+%{_mandir}/man8/rpmgraph.8*
+%{_bindir}/rpmgraph
+%{_libdir}/librp*[a-z].so
+%{_libdir}/pkgconfig/rpm.pc
+%{_includedir}/rpm/
+
+%files cron
+%{_sysconfdir}/cron.daily/rpm
+%config(noreplace) %{_sysconfdir}/logrotate.d/rpm
+
+%files apidocs
+%license COPYING
+%doc doc/librpm/html/*
+
+%changelog
+* Thu Aug 19 2021 Michal Domonkos <mdomonko@redhat.com> - 4.16.1.3-7
+- Unblock signals in forked scriptlets (#1991667)
+
+* Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 4.16.1.3-6.1
+- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
+  Related: rhbz#1991688
+
+* Wed Jul 28 2021 Florian Weimer <fweimer@redhat.com> - 4.16.1.3-6
+- Rebuild to pick up OpenSSL 3.0 Beta ABI (#1984097)
+
+* Fri Jul 23 2021 Michal Domonkos <mdomonko@redhat.com> - 4.16.1.3-5
+- Rebuild for gating.yaml
+
+* Thu Jul 22 2021 Michal Domonkos <mdomonko@redhat.com> - 4.16.1.3-4
+- Add support for EdDSA signatures to rpmsign (#1962234)
+- Add fapolicyd plugin (#1942549)
+
+* Mon Jul 12 2021 Michal Domonkos <mdomonko@redhat.com> - 4.16.1.3-3
+- Release bump for a rebuild
+
+* Tue Jun 29 2021 Michal Domonkos <mdomonko@redhat.com> - 4.16.1.3-2
+- Address important covscan issues (#1938861)
+
+* Tue Jun 15 2021 Mohan Boddu <mboddu@redhat.com> - 4.16.1.3-1.2
+- Rebuilt for RHEL 9 BETA for openssl 3.0. Related: rhbz#1971065
+
+* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 4.16.1.3-1.1
+- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
+
+* Mon Mar 22 2021 Panu Matilainen <pmatilai@redhat.com> - 4.16.1.3-1
+- Rebase to rpm 4.16.1.3 (https://rpm.org/wiki/Releases/4.16.1.3)
+
+* Wed Feb 03 2021 Panu Matilainen <pmatilai@redhat.com> - 4.16.1.2-6
+- Drop support for read-write Berkeley DB format (#1787311)
+
+* Wed Feb 03 2021 Panu Matilainen <pmatilai@redhat.com> - 4.16.1.2-5
+- Make with/without bdb build option actually work
+- Clean up unpackaged /var/tmp from the build root
+
+* Wed Jan 27 2021 Fedora Release Engineering <releng@fedoraproject.org> - 4.16.1.2-4.1
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
+
+* Fri Jan 22 2021 Mark Wielaard <mjw@fedoraproject.org> - 4.16.1.2-4
+- Fix edit_attributes_str_comp_dir in Patch916 (#1919107)
+
+* Tue Jan 19 2021 Jeff Law <law@redhat.com> - 4.16.1.2-3
+- Fix typo in test for F33 or newer
+
+* Tue Jan 19 2021 Mark Wielaard <mjw@fedoraproject.org> - 4.16.1.2-2
+- Add debugedit DWARF5 support
+
+* Wed Dec 16 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.1.2-1
+- Rebase to rpm 4.16.1.2 (http://rpm.org/wiki/Releases/4.16.1.2)
+- Add a spec safeguard for accidental soname bumps
+
+* Wed Dec 16 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.1.1-1
+- Rebase to rpm 4.16.1.1 (http://rpm.org/wiki/Releases/4.16.1.1)
+
+* Thu Dec 10 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.1-1
+- Rebase to rpm 4.16.1 (http://rpm.org/wiki/Releases/4.16.1)
+
+* Mon Nov 30 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.0-5
+- Only disable test-suite where it's actually broken
+
+* Mon Nov 30 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.0-4
+- Fix BDB crashing on failed open attempts (#1902395, #1898299, #1900407)
+- Fix unnecessary double failure on lazy keyring open
+
+* Wed Oct 28 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.0-3
+- Issue deprecation warning when creating BDB databases (#1787311)
+- Temporarily disable test-suite due to massive fakechroot breakage
+
+* Mon Oct 05 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.0-2
+- Clean up after test-suite which leaves a read-only tree behind
+
+* Wed Sep 30 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.0-1
+- Rebase to 4.16.0 final (https://rpm.org/wiki/Releases/4.16.0)
+
+* Mon Aug 31 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.0-0.rc1.1
+- Rebase to 4.16.0-rc1
+- Run test-suite in parallel
+
+* Sat Aug 01 2020 Fedora Release Engineering <releng@fedoraproject.org> - 4.16.0-0.beta3.2.3
+- Second attempt - Rebuilt for
+  https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
+
+* Wed Jul 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 4.16.0-0.beta3.2.2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
+
+* Sun Jul 26 2020 Peter Robinson <pbrobinson@fedoraproject.org> - 4.16.0-0.beta3.2.1
+- rebuild for ima-evm-utils 1.3
+
+* Mon Jun 29 2020 Tom Callaway <spot@fedoraproject.org> - 4.16.0-0.beta3.2
+- rebuild for lua 5.4
+
+* Wed Jun 24 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.0-0.beta3.1
+- Rebase to beta3
+
+* Wed Jun 10 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.0-0.beta1.4
+- Fix prefix search on sqlite backend (many file triggers not running)
+
+* Mon Jun 8 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.0-0.beta1.3
+- Unbreak metainfo() provide generation
+
+* Wed Jun 3 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.0-0.beta1.2
+- Don't auto-enable _flush_io on non-rotational media, it's too costly
+
+* Mon Jun 1 2020 Panu Matilainen <pmatilai@redhat.com> - 4.16.0-0.beta1.1
+- Rebase to rpm 4.16.0-beta1
+
+* Fri May 22 2020 Miro Hrončok <mhroncok@redhat.com> - 4.15.90-0.git14971.12.1
+- Rebuilt for Python 3.9
+
+* Tue May 12 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.90-0.git14971.12
+- Fix segfault when trying to use unknown database backend
+
+* Thu May 7 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.90-0.git14971.11
+- Flag BDB databases for rebuild on next reboot whenever rpm is updated
+- Switch default database to sqlite (#1818910)
+
+* Mon May 4 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.90-0.git14971.10
+- Handle rpmdb-rebuild service enablement for upgrades
+
+* Thu Apr 23 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.90-0.git14971.9
+- Fix questionable uses of %%{name} and %%{version} in the spec
+
+* Wed Apr 22 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.90-0.git14971.8
+- Fix regression(s) on build dependency resolution
+
+* Wed Apr 22 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.90-0.git14971.7
+- Add rpmdb-rebuild systemd service
+
+* Fri Apr 17 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.90-0.git14971.6
+- Warn on undefined macros in buildtree setup macros (#1820349)
+
+* Thu Apr 09 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.90-0.git14971.5
+- Fix regression causing all ELF files classified as OCaml
+
+* Mon Apr 06 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.90-0.git14971.4
+- Fix invalid path passed to parametric macro generators
+
+* Thu Apr 02 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.90-0.git14971.3
+- Fix db lock files not getting packaged
+
+* Tue Mar 31 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.90-0.git14971.2
+- Move bdb specific systemd-tmpfiles cleanup crutch behind the bdb bcond
+
+* Tue Mar 31 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.90-0.git14971.1
+- Rebase to rpm 4.16 alpha (https://rpm.org/wiki/Releases/4.16.0)
+- Add bconds for and enable sqlite, ndb and bdb_ro database backends
+- Add bcond for disabling bdb backend
+- Drop lmdb bcond, the backend was removed upstream
+- Ensure all database backend files are owned
+- Fix external environment causing test-suite failures in spec build
+- Re-enable hard test-suite failures again
+
+* Thu Jan 30 2020 Fedora Release Engineering <releng@fedoraproject.org> - 4.15.1-2.1
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
+
+* Thu Jan 9 2020 Panu Matilainen <pmatilai@redhat.com> - 4.15.1-2
+- Obsolete python2-rpm to fix upgrade path (#1775113)
+
+* Mon Nov 18 2019 Panu Matilainen <pmatilai@redhat.com> - 4.15.1-1
+- Rebase to 4.15.1 (https://rpm.org/wiki/Releases/4.15.1)
+
+* Thu Nov 14 2019 Adam Williamson <awilliam@redhat.com> - 4.15.0-7
+- Really revert armv8 detection improvements (patch was not applied in -6)
+
+* Wed Oct 23 2019 Peter Robinson <pbrobinson@fedoraproject.org> 4.15.0-6
+- Revert armv8 detection improvements
+
+* Mon Oct 21 2019 Stephen Gallagher <sgallagh@redhat.com> - 4.15.0-5
+- Revert aliasing arm64 to aarch64
+- Resolves: rhbz#1763831
+
+* Fri Oct 18 2019 Panu Matilainen <pmatilai@redhat.com> - 4.15.0-4
+- Revert problematic sub-variants of armv8 (#1691430)
+
+* Thu Oct 17 2019 Panu Matilainen <pmatilai@redhat.com> - 4.15.0-3
+- Drop python2 bindings for good (#1761211)
+
+* Tue Oct 15 2019 Adam Williamson <awilliam@redhat.com> - 4.15.0-2
+- Revert systemd inhibit plugin's calling of dbus_shutdown (#1750575)
+
+* Thu Sep 26 2019 Panu Matilainen <pmatilai@redhat.com> - 4.15.0-1
+- Update to 4.15.0 final (https://rpm.org/wiki/Releases/4.15.0)
+
+* Wed Aug 28 2019 Panu Matilainen <pmatilai@redhat.com> - 4.15.0-0.rc1.1
+- Update to 4.15.0-rc1
+
+* Tue Aug 27 2019 Panu Matilainen <pmatilai@redhat.com> - 4.15.0-0.beta.6
+- Fix some issues in the thread cap logic
+
+* Mon Aug 26 2019 Panu Matilainen <pmatilai@redhat.com> - 4.15.0-0.beta.5
+- Re-enable test-suite, temporarily disabled during alpha troubleshooting
+
+* Fri Aug 23 2019 Panu Matilainen <pmatilai@redhat.com> - 4.15.0-0.beta.4
+- Cap number of threads on 32bit platforms (#1729382)
+- Drop %%_lto_cflags macro (reverted upstream)
+
+* Fri Aug 23 2019 Panu Matilainen <pmatilai@redhat.com> - 4.15.0-0.beta.3
+- Restore strict order of build scriptlet stdout/stderr output
+
+* Thu Aug 15 2019 Miro Hrončok <mhroncok@redhat.com> - 4.15.0-0.beta.2.3
+- Rebuilt for Python 3.8
+
+* Wed Jul 31 2019 Miro Hrončok <mhroncok@redhat.com> - 4.15.0-0.beta.2.2
+- Rebuilt for libimaevm.so.1
+
+* Fri Jul 26 2019 Fedora Release Engineering <releng@fedoraproject.org> - 4.15.0-0.beta.2.1
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
+
+* Sat Jul 20 18:30:10 CEST 2019 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.15.0-0.beta.2
+- Backport patch to not set RPMTAG_BUILDTIME to SOURCE_DATE_EPOCH
+
+* Thu Jun 27 2019 Panu Matilainen <pmatilai@redhat.com> - 4.15.0-0.beta.1
+- Rebase to 4.15.0 beta
+
+* Thu Jun 20 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.90-0.git14653.18
+- Fix excessive TLS use, part II (#1722181)
+
+* Thu Jun 20 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.90-0.git14653.17
+- Fix excessive TLS use (#1722181)
+
+* Wed Jun 19 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.90-0.git14653.16
+- Drop buildarch again now that python_provide no longer needs it (#1720139)
+
+* Fri Jun 14 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.90-0.git14653.15
+- Temporarily re-enable buildarch macro for python_provide macro use (#1720139)
+
+* Thu Jun 13 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.90-0.git14653.14
+- Don't fail build trying to kill a non-existent process (#1720143)
+
+* Tue Jun 11 14:59:16 CEST 2019 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.14.90-0.git14653.13
+- Fix build of binary packages in parallel
+
+* Tue Jun 11 00:08:50 CEST 2019 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.14.90-0.git14653.10
+- Revert generation of binary packages in parallel
+
+* Mon Jun 10 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.90-0.git14653.1
+- Update to 4.15.0 alpha
+
+* Mon Jun 10 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2.1-14
+- Drop support for sanitizer build, it never really worked anyway
+- Drop leftover build-dependency on binutils-devel
+- Truncate changelog to rpm 4.14.x (last two years)
+
+* Mon Jun 10 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2.1-13
+- Drop support for Fedora < 28 builds
+- Drop leftover BDB-related compiler flag foo
+
+* Fri Jun 07 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2.1-12
+- Use pre-determined buildhost in test-suite to avoid DNS usage
+- Drop obsolete specspo and gpg2 related patches
+
+* Fri Jun 07 2019 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.14.2.1-11
+- Use py2/3 macros for building and installing the bindings
+
+* Tue May 21 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2.1-10
+- Support build-id generation from compressed ELF files (#1650072)
+
+* Fri May 03 2019 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.14.2.1-9
+- Suggest gdb-minimal
+
+* Thu Apr 25 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2.1-8
+- Replace deprecated __global_ldflags uses with build_ldflags macro
+
+* Thu Apr 11 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2.1-7
+- Fix excessive reference counting on faked string .decode()
+
+* Wed Apr 10 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2.1-6
+- Unbreak Python 3 API by returning string data as surrogate-escaped utf-8
+  string objects instead of bytes (#1693751)
+- As a temporary crutch,  monkey-patch a .decode() method to returned strings
+  to give users time to migrate from the long-standing broken behavior
+
+* Wed Apr 10 2019 Panu Matilainen <pmatilai@redhat.com> - 4.14.2.1-5
+- Generate minidebug for PIE executables on file >= 5.33 too
+- Backport find-debuginfo --g-libs option for glibc's benefit (#1661512)
+
+* Sat Feb 02 2019 Fedora Release Engineering <releng@fedoraproject.org> - 4.14.2.1-4.1
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
+
+* Wed Dec 19 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2.1-4
+- Backport the new modularity label tag (#1650286)
+
+* Mon Nov 19 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2.1-3
+- Take prefix into account when compressing man pages etc for Flatpak builds
+
+* Wed Oct 24 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2.1-2
+- Selinux plugin requires a base policy to work (#1641631)
+
+* Mon Oct 22 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2.1-1
+- Rebase to rpm 4.14.2.1 (http://rpm.org/wiki/Releases/4.14.2.1)
+
+* Wed Oct 17 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.14.2-9
+- Push name/epoch/version/release macro before invoking depgens
+
+* Tue Oct 16 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.14.2-8
+- Resurrect long since broken Lua library path
+
+* Fri Oct 12 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-7
+- Actually fail build on test-suite failures again
+- Invoke python2 explicitly from test-suite to unbreak build, part II
+
+* Thu Oct 11 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-6
+- Drop duplicate BDB buildrequire
+- Drop nowadays unnecessary BDB macro foo
+- Drop nowadays unnecessary manual libcap dependency
+
+* Thu Oct 11 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-5
+- Own all rpmdb files and ensure the list remains up to date
+- Drop redundant verify exclusions on rpmdb ghosts
+- Fix build when systemd is not installed (duh)
+
+* Thu Oct 11 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-4
+- Erm, really use the macro for tmpfiles.d path
+- Erm, don't nuke buildroot at beginning of %%install
+- Use modern build/install helper macros
+
+* Thu Oct 11 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-3
+- Eh, selinux plugin dependency condition was upside down (#1493267)
+- Drop no longer necessary condition over imaevm name
+- Drop no longer necessary obsolete on compat-librpm3
+
+* Thu Oct 11 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-2
+- Fix ancient Python GIL locking bug (#1632488)
+- Use the appropriate macro for tmpfiles.d now that one exists
+
+* Tue Aug 21 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-1
+- Update to rpm 4.14.2 final (http://rpm.org/wiki/Releases/4.14.2)
+
+* Mon Aug 13 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-0.rc2.2
+- Move python-macro-helper to main package where the macros are (#1577860)
+
+* Wed Aug 08 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-0.rc2.1
+- Update to rpm 4.14.2-rc2
+
+* Sat Jul 21 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.14.2-0.rc1.2
+- Decompress DWARF compressed ELF sections
+
+* Sat Jul 14 2018 Fedora Release Engineering <releng@fedoraproject.org> - 4.14.2-0.rc1.1.2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
+
+* Mon Jul 02 2018 Miro Hrončok <mhroncok@redhat.com> - 4.14.2-0.rc1.1.1
+- Rebuilt for Python 3.7
+
+* Fri Jun 29 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.2-0.rc1.1
+- Update to rpm 4.14.2-rc1
+- Patching test-suite for python2 too painful, just sed it instead
+- Fix premature version increment from previous changelog entries, oops
+
+* Fri Jun 29 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.1-13
+- Ehm, need to patch the autogenerated rpmtests script too for python2
+- Ehm, it's ldconfig_scriptlets not scripts
+- Drop the non-working python envvar magic from obsoleted change
+
+* Fri Jun 29 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.1-12
+- Invoke python2 explicitly from test-suite to unbreak build
+
+* Fri Jun 29 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.1-11
+- Remove direct ldconfig calls, use compat macros instead
+
+* Fri Jun 15 2018 Miro Hrončok <mhroncok@redhat.com> - 4.14.1-10.1
+- Rebuilt for Python 3.7
+
+* Mon May 28 2018 Miro Hrončok <mhroncok@redhat.com> - 4.14.1-10
+- Backport upstream solution to make brp-python-bytecompile automagic part opt-outable
+  https://fedoraproject.org/wiki/Changes/No_more_automagic_Python_bytecompilation
+
+* Tue May 22 2018 Mark Wielaard <mjw@fedoraproject.org> - 4.14.1-9
+- find-debuginfo.sh: Handle application/x-pie-executable (#1581224)
+
+* Tue Feb 20 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.14.1-8
+- Split rpm-build-libs to one more subpackage rpm-sign-libs
+
+* Mon Feb 19 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.1-7
+- Explicitly BuildRequire gcc and make
+
+* Fri Feb 09 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.14.1-6.1
+- Escape macros in %%changelog
+
+* Wed Jan 31 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.1-6
+- Avoid unnecessary macro helper dependency on /usr/bin/python (#1538657)
+- Fix release of previous changelog entry
+
+* Tue Jan 30 2018 Tomas Orsava <torsava@redhat.com> - 4.14.1-5
+- Add envvar that will be present during RPM build,
+  Part of a Fedora Change for F28: "Avoid /usr/bin/python in RPM build"
+  https://fedoraproject.org/wiki/Changes/Avoid_usr_bin_python_in_RPM_Build
+
+* Tue Jan 30 2018 Petr Viktorin <pviktori@redhat.com> - 4.14.1-4
+- Skip automatic Python byte-compilation if *.py files are not present
+
+* Thu Jan 25 2018 Florian Weimer <fweimer@redhat.com> - 4.14.1-3
+- Rebuild to work around gcc bug leading to librpm miscompilation (#1538648)
+
+* Thu Jan 18 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.1-2
+- Avoid nuking the new python-macro-helper along with dep generators (#1535692)
+
+* Tue Jan 16 2018 Panu Matilainen <pmatilai@redhat.com> - 4.14.1-1
+- Rebase to rpm 4.14.1 (http://rpm.org/wiki/Releases/4.14.1)
+
+* Tue Nov 07 2017 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.14.0-5
+- Fix typo in Obsoletes
+
+* Mon Nov 06 2017 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.14.0-4
+- Remove platform-python bits
+
+* Thu Oct 26 2017 Panu Matilainen <pmatilai@redhat.com> - 4.14.0-3
+- Move selinux plugin dependency to selinux-policy in Fedora >= 28 (#1493267)
+
+* Thu Oct 12 2017 Panu Matilainen <pmatilai@redhat.com> - 4.14.0-2
+- Dump out test-suite log in case of failures again
+- Don't assume per-user groups in test-suite
+
+* Thu Oct 12 2017 Panu Matilainen <pmatilai@redhat.com> - 4.14.0-1
+- Rebase to rpm 4.14.0 final (http://rpm.org/wiki/Releases/4.14.0)
+
+* Tue Oct 10 2017 Troy Dawson <tdawson@redhat.com> - 4.14.0-0.rc2.6
+- Cleanup spec file conditionals
+
+* Tue Oct 03 2017 Panu Matilainen <pmatilai@redhat.com> - 4.14.0-0.rc2.5
+- Add build conditionals for zstd and lmdb support
+- Enable zstd support
+
+* Tue Oct 03 2017 Panu Matilainen <pmatilai@redhat.com> - 4.14.0-0.rc2.4
+- Spec cleanups
+
+* Fri Sep 29 2017 Panu Matilainen <pmatilai@redhat.com> - 4.14.0-0.rc2.3
+- BuildRequire gnupg2 for the testsuite
+
+* Fri Sep 29 2017 Panu Matilainen <pmatilai@redhat.com> - 4.14.0-0.rc2.2
+- ima-evm-utils only has a -devel package in fedora >= 28
+
+* Thu Sep 28 2017 Panu Matilainen <pmatilai@redhat.com> - 4.14.0-0.rc2.1
+- Rebase to rpm 4.14.0-rc2 (http://rpm.org/wiki/Releases/4.14.0)
+
+* Mon Sep 18 2017 Panu Matilainen <pmatilai@redhat.com> - 4.14.0-0.rc1.3
+- Fix Ftell() past 2GB on 32bit architectures (#1492587)
+
+* Thu Sep 07 2017 Panu Matilainen <pmatilai@redhat.com> - 4.14.0-0.rc1.2
+- Actually honor with/without libimaevm option
+- ima-evm-utils-devel >= 1.0 is required for rpm >= 4.14.0
+
+* Wed Sep 06 2017 Panu Matilainen <pmatilai@redhat.com> - 4.14.0-0.rc1.1
+- Rebase to rpm 4.14.0-rc1 (http://rpm.org/wiki/Releases/4.14.0)
+- Re-enable SHA256 header digest generation (see #1480407)
+
+* Mon Aug 28 2017 Panu Matilainen <pmatilai@redhat.com> - 4.13.90-0.git14000.8
+- Band-aid for DB_VERSION_MISMATCH errors on glibc updates (#1465809)
+
+* Thu Aug 24 2017 Panu Matilainen <pmatilai@redhat.com> - 4.13.90-0.git14000.7
+- Remove ugly kludges from posttrans script, BDB handles this now
+
+* Fri Aug 18 2017 Panu Matilainen <pmatilai@redhat.com> - 4.13.90-0.git14000.6
+- Silence harmless but bogus error message on noarch packages (#1482144)
+
+* Thu Aug 17 2017 Miro Hrončok <mhroncok@redhat.com> - 4.13.90-0.git14002.5
+- Build with platform_python
+
+* Mon Aug 14 2017 Miro Hrončok <mhroncok@redhat.com> - 4.13.90-0.git14000.4
+- Add platform-python bytecompilation patch: platform-python-bytecompile.patch
+- Add platform python deps generator patch: platform-python-abi.patch
+- Add a platform-python subpackage and remove system python related declarations
+- Build rpm without platform_python for bytecompilation
+  (https://fedoraproject.org/wiki/Changes/Platform_Python_Stack)
+
+* Mon Aug 14 2017 Panu Matilainen <pmatilai@redhat.com> - 4.13.90-0.git14000.3
+- Disable macro argument quoting as a band-aid to #1481025
+
+* Fri Aug 11 2017 Panu Matilainen <pmatilai@redhat.com> - 4.13.90-0.git14000.2
+- Disable SHA256 header-only digest generation temporarily (#1480407)
+
+* Thu Aug 10 2017 Panu Matilainen <pmatilai@redhat.com> - 4.13.90-0.git14000.1
+- Rebase to rpm 4.13.90 aka 4.14.0-alpha (#1474836)
+