From ef05feae29a8c5d9fd06b4afa072fbb41a59e18c Mon Sep 17 00:00:00 2001
From: factory-maintainer <>
Date: Jun 01 2021 08:37:42 +0000
Subject: Update rpm to version 4.16.1.3 / rev 290 via SR 894744
https://build.opensuse.org/request/show/894744
by user factory-maintainer + dimstar_suse
Automatic submission by obs-autosubmit
---
diff --git a/.files b/.files
index 8cced0a..73f4da7 100644
Binary files a/.files and b/.files differ
diff --git a/.rev b/.rev
index 7319d29..6db05f8 100644
--- a/.rev
+++ b/.rev
@@ -2227,4 +2227,57 @@ See bugzilla 1167537 for the gory details.
- update to rpm-4.16.0
861385
+
+ 253033e20bd313b25a008a41815dded9
+ 4.16.0
+
+ dimstar_suse
+ - Add explicit requirement on python-rpm-macros to avoid widespread
+ breakage by package mistakenly ignoring their requirement of
+ python-rpm-macros (bsc#1180125). (forwarded request 864326 from mcepl)
+ 864328
+
+
+ 579e242641bcbd54138500028eb125be
+ 4.16.0
+
+ dimstar_suse
+ - Use shipped config.sub/config.guess instead of stone-aged from libtool
+- auto-config-update-aarch64-ppc64le.diff: update grep regex (forwarded request 870226 from Andreas_Schwab)
+ 870434
+
+
+ a1d0c34d49337a95597c66b6308ed8b9
+ 4.16.0
+
+ dimstar_suse
+ Automatic submission by obs-autosubmit
+ 877741
+
+
+ b23af4a472c2353a0ac79253b09efcc2
+ 4.16.1.3
+
+ dimstar_suse
+ change dump_posttrans mechanism to imply --noposttrans
+ 884038
+
+
+ 538375daaa742dfd1be37fa392654e7a
+ 4.16.1.3
+
+ dimstar_suse
+ - Use --dwz-single-file-mode for packages that use
+ baselibs.conf mechanism.
+- Add add-dwz-single-file-mode-option.patch patch. (forwarded request 886611 from marxin)
+ 887970
+
+
+ afea8c8fd4310f92cdf9aeb68e55ba64
+ 4.16.1.3
+
+ dimstar_suse
+ Automatic submission by obs-autosubmit
+ 894744
+
diff --git a/add-dwz-single-file-mode-option.patch b/add-dwz-single-file-mode-option.patch
new file mode 100644
index 0000000..e6133b1
--- /dev/null
+++ b/add-dwz-single-file-mode-option.patch
@@ -0,0 +1,62 @@
+From d741374effd75baaa35047c29c7a8adf819138ff Mon Sep 17 00:00:00 2001
+From: Martin Liska
+Date: Mon, 15 Mar 2021 16:58:34 +0100
+Subject: [PATCH] Add --dwz-single-file-mode argument for find-debuginfo.sh.
+
+Sometime it's handy to disable multi-file mode and the patch
+adds option for that: --dwz-single-file-mode.
+
+It will be used in openSUSE for packages that use baselibs.conf
+mechanism.
+---
+ scripts/find-debuginfo.sh | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh
+index e0c36ebb6..2503b0f01 100755
+--- a/scripts/find-debuginfo.sh
++++ b/scripts/find-debuginfo.sh
+@@ -10,6 +10,7 @@
+ # [-S debugsourcefiles.list]
+ # [--run-dwz] [--dwz-low-mem-die-limit N]
+ # [--dwz-max-die-limit N]
++# [--dwz-single-file-mode]
+ # [--build-id-seed SEED]
+ # [--unique-debug-suffix SUFFIX]
+ # [--unique-debug-src-base BASE]
+@@ -45,6 +46,8 @@
+ # The --run-dwz flag instructs find-debuginfo.sh to run the dwz utility
+ # if available, and --dwz-low-mem-die-limit and --dwz-max-die-limit
+ # provide detailed limits. See dwz(1) -l and -L option for details.
++# Use --dwz-single-file-mode to disable multi-file mode, see -m
++# for more details.
+ #
+ # If --build-id-seed SEED is given then debugedit is called to
+ # update the build-ids it finds adding the SEED as seed to recalculate
+@@ -96,6 +99,7 @@ no_recompute_build_id=false
+ run_dwz=false
+ dwz_low_mem_die_limit=
+ dwz_max_die_limit=
++dwz_single_file_mode=false
+
+ # build id seed given by the --build-id-seed option
+ build_id_seed=
+@@ -129,6 +133,9 @@ while [ $# -gt 0 ]; do
+ dwz_max_die_limit=$2
+ shift
+ ;;
++ --dwz-single-file-mode)
++ dwz_single_file_mode=true
++ ;;
+ --build-id-seed)
+ build_id_seed=$2
+ shift
+@@ -523,7 +530,7 @@ if $run_dwz \
+ done
+ dwz_multifile_name="${dwz_multifile_name}${dwz_multifile_suffix}"
+ dwz_opts="-h -q -r"
+- [ ${#dwz_files[@]} -gt 1 ] \
++ [ ${#dwz_files[@]} -gt 1 ] && [ "$dwz_single_file_mode" = "false" ] \
+ && dwz_opts="${dwz_opts} -m .dwz/${dwz_multifile_name}"
+ mkdir -p "${RPM_BUILD_ROOT}/usr/lib/debug/.dwz"
+ [ -n "${dwz_low_mem_die_limit}" ] \
diff --git a/auto-config-update-aarch64-ppc64le.diff b/auto-config-update-aarch64-ppc64le.diff
index 3ad440c..ef59b7d 100644
--- a/auto-config-update-aarch64-ppc64le.diff
+++ b/auto-config-update-aarch64-ppc64le.diff
@@ -1,6 +1,8 @@
---- ./build/parseSpec.c.orig 2019-10-02 12:38:51.836127743 +0000
-+++ ./build/parseSpec.c 2019-10-02 12:52:33.818447657 +0000
-@@ -926,7 +926,22 @@ static rpmSpec parseSpec(const char *spe
+Index: build/parseSpec.c
+===================================================================
+--- build/parseSpec.c.orig
++++ build/parseSpec.c
+@@ -942,7 +942,30 @@ static rpmSpec parseSpec(const char *spe
&(spec->buildrequires));
break;
case PART_BUILD:
@@ -12,11 +14,19 @@
+ }
+ spec->build = newStringBuf();
+ appendLineStringBuf(spec->build,
-+ "ref=/usr/lib/rpm; testarch=$(uname -m)\n"
++ "ref=/usr/lib/rpm\n"
++ "mints=0\n"
++ "case $(uname -m) in\n"
++ " aarch64) mints=20120610;;\n"
++ " ppc64le) mints=20130610;;\n"
++ " riscv64) mints=20160911;;\n"
++ "esac\n"
+ "for s in guess sub; do\n"
+ " for c in $(find -maxdepth 8 -name \"config.$s\"); do\n"
+ " grep -q config-patches@ $c || continue\n"
-+ " grep -q $testarch\\[-:\\] $c || install -m 755 $ref/config.$s $c\n"
++ " timestamp=$(sed -n \"/^timestamp=/{s///;s/[-'\\\"]//g;p;q;}\" $c)\n"
++ " test -n \"$timestamp\" || timestamp=0\n"
++ " test $timestamp -ge $mints || install -m 755 $ref/config.$s $c\n"
+ " done\n"
+ "done\n"
+ );
diff --git a/debugedit.diff b/debugedit.diff
deleted file mode 100644
index c8cf989..0000000
--- a/debugedit.diff
+++ /dev/null
@@ -1,69 +0,0 @@
-Make debugedit build without dwarf.h
-
---- ./Makefile.am.orig 2019-06-26 14:17:31.394985722 +0000
-+++ ./Makefile.am 2019-10-02 09:48:35.949316743 +0000
-@@ -167,7 +167,6 @@ rpm2archive_LDADD += @WITH_POPT_LIB@ @WI
-
-
- if LIBELF
--if LIBDWARF
- if LIBDW
- rpmconfig_SCRIPTS += scripts/find-debuginfo.sh
-
-@@ -181,7 +180,6 @@ else
- debugedit_LDADD += @WITH_LIBDW_LIB@ -lebl
- endif # HAVE_LIBDW_STRTAB
- endif # LIBDW
--endif # LIBDWARF
- rpmlibexec_PROGRAMS += elfdeps
- elfdeps_SOURCES = tools/elfdeps.c
- elfdeps_LDADD = rpmio/librpmio.la
---- ./tools/debugedit.c.orig 2019-06-26 14:17:31.462985619 +0000
-+++ ./tools/debugedit.c 2019-10-02 09:48:35.953316735 +0000
-@@ -39,7 +39,45 @@
- #include
-
- #include
--#include
-+
-+
-+/* some defines taken from the dwarf standard */
-+
-+#define DW_TAG_compile_unit 0x11
-+
-+#define DW_AT_name 0x03
-+#define DW_AT_stmt_list 0x10
-+#define DW_AT_comp_dir 0x1b
-+
-+#define DW_FORM_addr 0x01
-+#define DW_FORM_block2 0x03
-+#define DW_FORM_block4 0x04
-+#define DW_FORM_data2 0x05
-+#define DW_FORM_data4 0x06
-+#define DW_FORM_data8 0x07
-+#define DW_FORM_string 0x08
-+#define DW_FORM_block 0x09
-+#define DW_FORM_block1 0x0a
-+#define DW_FORM_data1 0x0b
-+#define DW_FORM_flag 0x0c
-+#define DW_FORM_sdata 0x0d
-+#define DW_FORM_strp 0x0e
-+#define DW_FORM_udata 0x0f
-+#define DW_FORM_ref_addr 0x10
-+#define DW_FORM_ref1 0x11
-+#define DW_FORM_ref2 0x12
-+#define DW_FORM_ref4 0x13
-+#define DW_FORM_ref8 0x14
-+#define DW_FORM_ref_udata 0x15
-+#define DW_FORM_indirect 0x16
-+
-+#define DW_MACRO_GNU_define 1
-+#define DW_MACRO_GNU_undef 2
-+#define DW_MACRO_GNU_start_file 3
-+#define DW_MACRO_GNU_end_file 4
-+#define DW_MACRO_GNU_define_indirect 5
-+#define DW_MACRO_GNU_undef_indirect 6
-+#define DW_MACRO_GNU_transparent_include 7
-
-
- /* Unfortunately strtab manipulation functions were only officially added
diff --git a/dwarf5.diff b/dwarf5.diff
new file mode 100644
index 0000000..b72b011
--- /dev/null
+++ b/dwarf5.diff
@@ -0,0 +1,1951 @@
+# Contains DWARF 5 support and includes the following upstream patches:
+
+6b0019cd0c5ae18a59affa49a857b4d610d403e4
+a834fccf3c94f78ad6a1b35ae352b1ede183dde4
+86408cd826c32229817071bd008d9856cda4aca5
+0d1003bc723ba30bfe325bb51aeafe7dbfed6a5c
+
+--- ./tools/debugedit.c.orig 2021-03-30 09:34:25.206392109 +0000
++++ ./tools/debugedit.c 2021-03-30 09:34:40.186365656 +0000
+@@ -103,6 +103,8 @@ static bool need_string_replacement = fa
+ /* 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;
+@@ -233,7 +235,7 @@ typedef struct
+ int shift = 0; \
+ do \
+ { \
+- c = *ptr++; \
++ c = *(ptr)++; \
+ ret |= (c & 0x7f) << shift; \
+ shift += 7; \
+ } while (c & 0x80); \
+@@ -251,7 +253,7 @@ typedef struct
+ valv >>= 7; \
+ if (valv) \
+ c |= 0x80; \
+- *ptr++ = c; \
++ *(ptr)++ = c; \
+ } \
+ while (valv); \
+ })
+@@ -311,7 +313,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 +330,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; \
+@@ -433,7 +435,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[] =
+@@ -452,6 +455,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 },
+@@ -466,6 +474,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 }
+ };
+
+@@ -542,10 +555,11 @@ setup_relbuf (DSO *dso, debug_section *s
+ /* 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;
+@@ -754,12 +768,29 @@ 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_line_strp
++ || 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;
+@@ -1022,17 +1053,20 @@ string_find_entry (struct strings *strin
+ 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)
+ {
+@@ -1076,15 +1110,18 @@ record_file_string_entry_idx (struct str
+ 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)
+@@ -1217,13 +1254,28 @@ get_line_table (DSO *dso, size_t off, st
+
+ /* 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);
+@@ -1269,7 +1321,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;
+ }
+
+@@ -1314,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),
+@@ -1454,42 +1510,151 @@ 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. */
+-static bool
+-read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
++/* Record or adjust (according to phase) DW_FORM_strp or DW_FORM_line_strp. */
++static void
++edit_strp (DSO *dso, bool line_strp, unsigned char *ptr, int phase,
++ bool handled_strp)
+ {
+- 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;
++ unsigned char *ptr_orig = ptr;
+
+- if (get_line_table (dso, off, &table) == false
+- || table == NULL)
++ /* 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)
+ {
+- if (table != NULL)
+- error (0, 0, ".debug_line offset 0x%x referenced multiple times",
+- off);
+- return false;
++ /* 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 (line_strp, dso, idx);
++ }
++ }
++ 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 (strings, idx);
++ new_idx = strent_offset (entry->entry);
++ do_write_32_relocated (ptr, new_idx);
+ }
+
+- /* 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;
++ 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:
++ case DW_FORM_implicit_const:
++ break;
++ case DW_FORM_addr:
++ *ptrp += ptr_size;
++ break;
++ 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;
++ case DW_FORM_ref8:
++ case DW_FORM_data8:
++ 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:
++ *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_0x%x", 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_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
++ struct line_table *table)
++{
++ unsigned char **dirt;
++ uint32_t value, dirt_cnt;
++ size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir);
++ unsigned char *dir = ptr;
+
+ /* dir table: */
+ value = 1;
+@@ -1622,6 +1787,296 @@ read_dwarf2_line (DSO *dso, uint32_t off
+ read_uleb128 (ptr);
+ }
+
++ 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
++ 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 */
++ + (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 */
++
++ /* 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;
+ }
+@@ -1639,6 +2094,40 @@ find_new_list_offs (struct debug_lines *
+ return table->new_idx;
+ }
+
++/* Read DW_FORM_strp or DW_FORM_line_strp collecting compilation directory. */
++static void
++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)
++ {
++ 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);
++ }
++
++ if (dest_dir != NULL && phase == 0)
++ {
++ 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;
++ }
++}
++
+ /* 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
+@@ -1657,7 +2146,6 @@ edit_attributes (DSO *dso, unsigned char
+ 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,38 +2231,24 @@ edit_attributes (DSO *dso, unsigned char
+ }
+ }
+ }
+- 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;
+- }
+- }
++ 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
+@@ -1784,11 +2258,14 @@ edit_attributes (DSO *dso, unsigned char
+ /* 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, '/');
+@@ -1809,107 +2286,37 @@ edit_attributes (DSO *dso, unsigned char
+ 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;
+ }
+ }
+
+ 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, false /* line_strp */, ptr, phase, handled_strp);
+ break;
+- case DW_FORM_block4:
+- len = read_32 (ptr);
+- form = DW_FORM_block1;
++ case DW_FORM_line_strp:
++ edit_strp (dso, true /* line_strp */, ptr, phase, handled_strp);
+ 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;
+ }
+ }
+@@ -1965,6 +2372,163 @@ line_rel_cmp (const void *a, const void
+ }
+
+ static int
++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 = sec->data;
++ if (ptr == NULL)
++ return 0;
++
++ setup_relbuf(dso, sec, &reltype);
++ endsec = ptr + sec->size;
++ while (ptr < 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);
++ 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: %s too small", dso->filename, sec->name);
++ return 1;
++ }
++
++ cu_version = read_16 (ptr);
++ 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)
++ {
++ 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 (cu_version < 5)
++ cu_ptr_size = read_8 (ptr);
++
++ if (ptr_size == 0)
++ {
++ ptr_size = cu_ptr_size;
++ if (ptr_size != 4 && ptr_size != 8)
++ {
++ error (0, 0, "%s: Invalid DWARF pointer size %d",
++ dso->filename, ptr_size);
++ return 1;
++ }
++ }
++ else if (cu_ptr_size != ptr_size)
++ {
++ error (0, 0, "%s: DWARF pointer size differs between CUs",
++ dso->filename);
++ return 1;
++ }
++
++ if (sec != &debug_sections[DEBUG_INFO])
++ ptr += 12; /* Skip type_signature and type_offset. */
++
++ 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;
++}
++
++/* Rebuild .debug_str. */
++static void
++edit_dwarf2_any_str (DSO *dso, struct strings *strings, debug_section *secp)
++{
++ 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. */
++ 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);
++ secp->size = strdata->d_size;
++ strings->str_buf = strdata->d_buf;
++}
++
++static int
+ edit_dwarf2 (DSO *dso)
+ {
+ Elf_Data *data;
+@@ -1995,7 +2559,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);
+@@ -2003,22 +2567,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;
+ }
+ }
+@@ -2055,23 +2618,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;
+@@ -2100,388 +2663,338 @@ 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, *endsec;
++ int phase;
++ 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++)
+ {
+- 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_line_strp_update
++ && !need_string_replacement
++ && !need_stmt_update)
++ break;
+
+- for (phase = 0; phase < 2; phase++)
+- {
+- /* If we don't need to update anyhing, skip phase 1. */
+- if (phase == 1
+- && !need_strp_update
+- && !need_string_replacement
+- && !need_stmt_update)
+- break;
++ rel_updated = false;
++ if (edit_info (dso, phase, &debug_sections[DEBUG_INFO]))
++ return 1;
+
+- 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)
+- {
+- if (ptr + 11 > endsec)
+- {
+- error (0, 0, "%s: .debug_info CU header too small",
+- dso->filename);
+- return 1;
+- }
++ /* Remember whether any .debug_info relocations might need
++ to be updated. */
++ info_rel_updated = rel_updated;
+
+- endcu = ptr + 4;
+- endcu += read_32 (ptr);
+- if (endcu == ptr + 0xffffffff)
+- {
+- error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
+- return 1;
+- }
++ 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;
++ }
+
+- if (endcu > endsec)
+- {
+- error (0, 0, "%s: .debug_info too small", dso->filename);
+- return 1;
+- }
++ /* Remember whether any .debug_types relocations might need
++ to be updated. */
++ types_rel_updated = rel_updated;
+
+- 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;
+- }
++ /* 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);
+
+- 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;
+- }
++ /* 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);
+
+- if (ptr_size == 0)
++ /* Sort them by offset into section. */
++ for (size_t i = 0; i < rels; i++)
+ {
+- ptr_size = read_8 (ptr);
+- if (ptr_size != 4 && ptr_size != 8)
++ if (rtype == SHT_RELA)
+ {
+- error (0, 0, "%s: Invalid DWARF pointer size %d",
+- dso->filename, ptr_size);
+- return 1;
++ 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 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)
++ else
+ {
+- error (0, 0, "%s: Could not find DWARF abbreviation %d",
+- dso->filename, tag.entry);
+- htab_delete (abbrev);
+- 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;
+ }
+-
+- ptr = edit_attributes (dso, ptr, t, phase);
+- if (ptr == NULL)
+- break;
+ }
++ qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp);
+
+- htab_delete (abbrev);
+- }
+-
+- /* 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);
+-
+- /* 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)
++ size_t lndx = 0;
++ for (size_t i = 0; i < rels; i++)
+ {
+- 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);
++ /* These relocations only happen in ET_REL files
++ and are section offsets. */
++ GElf_Addr r_offset;
++ size_t ndx = rbuf[i].ndx;
+
+- /* Sort them by offset into section. */
+- for (size_t i = 0; i < rels; i++)
++ GElf_Rel rel;
++ GElf_Rela rela;
++ 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;
+- }
++ if (gelf_getrela (rdata, ndx, &rela) == NULL)
++ error (1, 0, "Couldn't get relocation: %s",
++ elf_errmsg (-1));
++ r_offset = rela.r_offset;
+ }
+- 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;
+- }
++ 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++;
++ 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");
++ 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);
++ /* 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));
+- }
++ 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));
+ }
+-
+- 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;
++ 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);
+
+- if (offset_len != 4)
+- error (0, 1,
+- "Cannot handle 8 byte macro offsets: %s",
+- dso->filename);
++ offset_len = (macro_flags & 0x01) ? 8 : 4;
++ line_offset = (macro_flags & 0x02) ? 1 : 0;
+
+- /* 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);
+- }
+- }
+- }
++ 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 (false, dso, idx);
++ }
++ else
++ {
++ struct stridxentry *entry;
++ size_t idx, new_idx;
++ idx = do_read_32_relocated (ptr);
++ entry = string_find_entry (&dso->debug_str, 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];
++ if (rel_updated)
++ macro_rel_updated = true;
++ macro_sec = macro_sec->next;
++ }
++ }
+
+- /* 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;
+- }
++ /* 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;
+
+- /* 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);
++ /* 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, &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]);
++ }
+
+- /* Update any relocations addends we might have touched. */
+- if (info_rel_updated)
+- update_rela_data (dso, &debug_sections[DEBUG_INFO]);
++ /* After phase 1 we might have rewritten the debug_info with
++ new strp, strings and/or linep offsets. */
++ 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 || need_line_strp_update)
++ dirty_section (DEBUG_LINE);
+
+- if (macro_rel_updated)
++ /* 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)
+ {
+- 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, types_sec);
++ types_sec = types_sec->next;
+ }
+ }
+
++ if (macro_rel_updated)
++ {
++ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
++ while (macro_sec != NULL)
++ {
++ update_rela_data (dso, macro_sec);
++ macro_sec = macro_sec->next;
++ }
++ }
++
++ if (line_rel_updated)
++ update_rela_data (dso, &debug_sections[DEBUG_LINE]);
++
+ return 0;
+ }
+
+@@ -2574,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;
+
+@@ -2582,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);
+ }
+@@ -2862,7 +3377,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. */
+@@ -2934,10 +3451,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;
+
+@@ -3007,7 +3526,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);
+
+@@ -3022,6 +3542,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;
diff --git a/empty_dbbackend.diff b/empty_dbbackend.diff
deleted file mode 100644
index e4f33f8..0000000
--- a/empty_dbbackend.diff
+++ /dev/null
@@ -1,20 +0,0 @@
---- ./lib/backend/dbi.c.orig 2020-11-18 09:37:08.314743771 +0000
-+++ ./lib/backend/dbi.c 2020-11-18 09:42:34.025792074 +0000
-@@ -77,7 +77,7 @@ dbDetectBackend(rpmdb rdb)
- }
- }
-
-- if (!cfg) {
-+ if (!cfg && (rdb->db_flags & RPMDB_FLAG_REBUILD) != 0) {
- rpmlog(RPMLOG_WARNING, _("invalid %%_db_backend: %s\n"), db_backend);
- goto exit;
- }
-@@ -97,7 +97,7 @@ dbDetectBackend(rpmdb rdb)
- rpmlog(RPMLOG_WARNING,
- _("Converting database from %s to %s backend\n"),
- ondisk->name, cfg->name);
-- } else {
-+ } else if (*db_backend) {
- rpmlog(RPMLOG_WARNING,
- _("Found %s %s database while attempting %s backend: "
- "using %s backend.\n"),
diff --git a/finddebuginfo-check-res-file.patch b/finddebuginfo-check-res-file.patch
deleted file mode 100644
index 0fbefc9..0000000
--- a/finddebuginfo-check-res-file.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From a20edbb561f74ba608c0aa36be637e7245e596b5 Mon Sep 17 00:00:00 2001
-From: ggardet
-Date: Fri, 9 Oct 2020 13:10:09 +0200
-Subject: [PATCH] Do not fail if there is no "$temp"/res.* file
-
-find-debuginfo is multi-threaded and rpm runs
-scripts usually with "-e" to abort on error.
-If the debug-splitting tool fails, that job will abort.
-But if you have X files that are problematic in the tree,
-and you have X or less jobs, find-debuginfo will abort
-as no single res.$number has been written.
-But if you have more than X jobs, the build will succeed,
-which makes the whole process random.
-This commit remove this randomness.
-
---- scripts/find-debuginfo.sh.orig
-+++ scripts/find-debuginfo.sh
-@@ -498,6 +498,7 @@ else
- wait
- )
- for f in "$temp"/res.*; do
-+ test -f "$f" || continue
- res=$(< "$f")
- if [ "$res" != "0" ]; then
- exit 1
diff --git a/macrosin.diff b/macrosin.diff
index 9de921f..4747c52 100644
--- a/macrosin.diff
+++ b/macrosin.diff
@@ -1,11 +1,10 @@
--- ./macros.in.orig 2020-09-30 12:42:09.146057387 +0000
+++ ./macros.in 2020-09-30 12:45:30.517611707 +0000
-@@ -177,7 +177,7 @@
- %{?_unique_build_ids:--build-id-seed "%{VERSION}-%{RELEASE}"} \\\
+@@ -168,6 +168,7 @@
%{?_unique_debug_names:--unique-debug-suffix "-%{VERSION}-%{RELEASE}.%{_arch}"} \\\
%{?_unique_debug_srcs:--unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}"} \\\
-- %{?_find_debuginfo_dwz_opts} \\\
-+ %{lua:if not posix.access(rpm.expand("%_sourcedir/baselibs.conf"), "r") then print(rpm.expand("%{?_find_debuginfo_dwz_opts}")) end} \\\
+ %{?_find_debuginfo_dwz_opts} \\\
++ %{lua:if posix.access(rpm.expand("%_sourcedir/baselibs.conf"), "r") then print("--dwz-single-file-mode") end} \\\
%{?_find_debuginfo_opts} \\\
%{?_debugsource_packages:-S debugsourcefiles.list} \\\
"%{_builddir}/%{?buildsubdir}"\
diff --git a/posttrans.diff b/posttrans.diff
new file mode 100644
index 0000000..356d357
--- /dev/null
+++ b/posttrans.diff
@@ -0,0 +1,375 @@
+--- ./lib/poptI.c.orig 2021-04-09 11:28:12.359647290 +0000
++++ ./lib/poptI.c 2021-04-09 11:28:15.523640983 +0000
+@@ -265,6 +265,10 @@ struct poptOption rpmInstallPoptTable[]
+ &rpmIArgs.installInterfaceFlags, (INSTALL_REINSTALL|INSTALL_INSTALL),
+ N_("reinstall package(s)"),
+ N_("+") },
++ { "runposttrans", '\0', POPT_BIT_SET,
++ &rpmIArgs.installInterfaceFlags, INSTALL_RUNPOSTTRANS,
++ N_("run posttrans scriptlet"),
++ N_("") },
+
+ POPT_TABLEEND
+ };
+--- ./lib/psm.c.orig 2021-04-09 11:28:12.359647290 +0000
++++ ./lib/psm.c 2021-04-09 11:28:15.527640975 +0000
+@@ -810,7 +810,7 @@ static rpmRC rpmPackageErase(rpmts ts, r
+ }
+ if (rc) break;
+
+- if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOSTTRANS|RPMTRANS_FLAG_NOTRIGGERPOSTUN))) {
++ if (ts->dump_posttrans || !(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOSTTRANS|RPMTRANS_FLAG_NOTRIGGERPOSTUN))) {
+ /* Prepare post transaction uninstall triggers */
+ rpmtriggersPrepPostUnTransFileTrigs(psm->ts, psm->te);
+ }
+--- ./lib/rpmcli.h.orig 2021-04-09 11:28:12.359647290 +0000
++++ ./lib/rpmcli.h 2021-04-09 11:28:15.527640975 +0000
+@@ -304,6 +304,7 @@ enum rpmInstallFlags_e {
+ INSTALL_ERASE = (1 << 8), /*!< from --erase */
+ INSTALL_ALLMATCHES = (1 << 9), /*!< from --allmatches */
+ INSTALL_REINSTALL = (1 << 10), /*!< from --reinstall */
++ INSTALL_RUNPOSTTRANS = (1 << 11), /*!< from --runposttrans */
+ };
+
+ typedef rpmFlags rpmInstallFlags;
+@@ -385,6 +386,15 @@ int rpmInstall(rpmts ts, struct rpmInsta
+ int rpmErase(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_const_t argv);
+
+ /** \ingroup rpmcli
++ * Run posttrans scriptlets
++ * @param ts transaction set
++ * @param ia control args/bits
++ * @param argv array of trigger manifest file names (NULL terminated)
++ * @return 0 on success
++ */
++int rpmRunPostTrans(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_const_t argv);
++
++/** \ingroup rpmcli
+ */
+ extern struct rpmInstallArguments_s rpmIArgs;
+
+--- ./lib/rpminstall.c.orig 2021-04-09 11:28:12.363647282 +0000
++++ ./lib/rpminstall.c 2021-04-09 11:28:15.527640975 +0000
+@@ -4,6 +4,8 @@
+
+ #include "system.h"
+
++#include
++
+ #include
+ #include
+ #include /* rpmReadPackageFile, vercmp etc */
+@@ -772,3 +774,32 @@ int rpmInstallSource(rpmts ts, const cha
+ return rc;
+ }
+
++int rpmRunPostTrans(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_const_t fileArgv)
++{
++ ARGV_t manifest = NULL;
++ FILE *f;
++ char line[BUFSIZ], *s, *p;
++ int rc = 1;
++
++ if (fileArgv == NULL) return 0;
++ if (!fileArgv[0] || fileArgv[1] != NULL) {
++ rpmlog(RPMLOG_ERR, _("runposttrans needs exactly one manifest file\n"));
++ goto exit;
++ }
++ if (!(f = fopen(fileArgv[0], "r"))) {
++ rpmlog(RPMLOG_ERR, _("cannot open %s: %s\n"), fileArgv[0], strerror(errno));
++ goto exit;
++ }
++ while ((s = fgets(line, sizeof(line) - 1, f)) != 0) {
++ if (p = strrchr(s, '\n'))
++ *p = 0;
++ argvAdd(&manifest, s);
++ }
++ fclose(f);
++ rpmlog(RPMLOG_DEBUG, "running posttrans scriptlets\n");
++ rpmtsClean(ts);
++ rc = rpmtsRunPostTrans(ts, manifest);
++exit:
++ argvFree(manifest);
++ return rc;
++}
+--- ./lib/rpmtriggers.c.orig 2021-04-09 11:28:12.363647282 +0000
++++ ./lib/rpmtriggers.c 2021-04-09 11:31:46.999219563 +0000
+@@ -1,5 +1,6 @@
+ #include "system.h"
+
++#include
+ #include
+ #include
+ #include
+@@ -34,7 +35,7 @@ rpmtriggers rpmtriggersFree(rpmtriggers
+ return NULL;
+ }
+
+-static void rpmtriggersAdd(rpmtriggers trigs, unsigned int hdrNum,
++void rpmtriggersAdd(rpmtriggers trigs, unsigned int hdrNum,
+ unsigned int tix, unsigned int priority)
+ {
+ if (trigs->count == trigs->alloced) {
+@@ -177,6 +178,14 @@ int runPostUnTransFileTrigs(rpmts ts)
+ if (trigH == NULL)
+ continue;
+
++ if (ts->dump_posttrans) {
++ char *trigNEVRA = headerGetAsString(trigH, RPMTAG_NEVRA);
++ rpmlog(RPMLOG_NOTICE, "dump_posttrans: transfiletriggerpostun %u %u %s\n", trigs->triggerInfo[i].tix, trigs->triggerInfo[i].hdrNum, trigNEVRA);
++ free(trigNEVRA);
++ headerFree(trigH);
++ continue;
++ }
++
+ /* Prepare and run script */
+ script = rpmScriptFromTriggerTag(trigH,
+ triggertag(RPMSENSE_TRIGGERPOSTUN),
+@@ -583,6 +592,16 @@ rpmRC runImmedFileTriggers(rpmts ts, rpm
+ rpmTagVal priorityTag;
+ rpmtriggers triggers;
+
++ if (sense == RPMSENSE_TRIGGERIN && tm == RPMSCRIPT_TRANSFILETRIGGER && ts->dump_posttrans) {
++ unsigned int hdrNum = headerGetInstance(trigH);
++ if (hdrNum) {
++ char *trigNEVRA = headerGetAsString(trigH, RPMTAG_NEVRA);
++ rpmlog(RPMLOG_NOTICE, "dump_posttrans: install %u %s\n", hdrNum, trigNEVRA);
++ free(trigNEVRA);
++ }
++ headerFree(trigH);
++ return RPMRC_OK;
++ }
+ if (tm == RPMSCRIPT_FILETRIGGER) {
+ priorityTag = RPMTAG_FILETRIGGERPRIORITIES;
+ } else {
+--- ./lib/rpmtriggers.h.orig 2021-04-09 11:28:12.363647282 +0000
++++ ./lib/rpmtriggers.h 2021-04-09 11:28:15.527640975 +0000
+@@ -27,6 +27,10 @@ rpmtriggers rpmtriggersCreate(unsigned i
+ RPM_GNUC_INTERNAL
+ rpmtriggers rpmtriggersFree(rpmtriggers triggers);
+
++RPM_GNUC_INTERNAL
++void rpmtriggersAdd(rpmtriggers trigs, unsigned int hdrNum,
++ unsigned int tix, unsigned int priority);
++
+ /*
+ * Prepare post trans uninstall file triggers. After transcation uninstalled
+ * files are not saved anywhere. So we need during uninstalation of every
+--- ./lib/rpmts.h.orig 2021-04-09 11:28:12.363647282 +0000
++++ ./lib/rpmts.h 2021-04-09 11:28:15.527640975 +0000
+@@ -229,6 +229,15 @@ int rpmtsOrder(rpmts ts);
+ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet);
+
+ /** \ingroup rpmts
++ * Run all posttrans scriptlets described in the manifest data.
++ *
++ * @param ts transaction set
++ * @param manifest the manifest data
++ * @return 0 on success, -1 on error
++ */
++int rpmtsRunPostTrans(rpmts ts, ARGV_const_t manifest);
++
++/** \ingroup rpmts
+ * Reference a transaction set instance.
+ * @param ts transaction set
+ * @return new transaction set reference
+--- ./lib/rpmts_internal.h.orig 2021-04-09 11:28:12.363647282 +0000
++++ ./lib/rpmts_internal.h 2021-04-09 11:28:15.527640975 +0000
+@@ -87,6 +87,7 @@ struct rpmts_s {
+ rpmtriggers trigs2run; /*!< Transaction file triggers */
+
+ int min_writes; /*!< macro minimize_writes used */
++ int dump_posttrans; /*!< macro dump_posttrans used */
+ };
+
+ #ifdef __cplusplus
+--- ./lib/transaction.c.orig 2021-04-09 11:28:12.363647282 +0000
++++ ./lib/transaction.c 2021-04-09 11:33:22.247029757 +0000
+@@ -1468,6 +1468,8 @@ static int rpmtsSetup(rpmts ts, rpmprobF
+ /* Get available space on mounted file systems. */
+ (void) rpmtsInitDSI(ts);
+
++ /* Initialize the dump_posttrans flag */
++ ts->dump_posttrans = (rpmExpandNumeric("%{?_dump_posttrans}") > 0);
+ return 0;
+ }
+
+@@ -1846,22 +1848,26 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rp
+ /* Actually install and remove packages */
+ nfailed = rpmtsProcess(ts);
+
++ if (ts->dump_posttrans) {
++ rpmlog(RPMLOG_NOTICE, "dump_posttrans: enabled\n");
++ }
++
+ /* Run %posttrans scripts unless disabled */
+- if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOSTTRANS))) {
++ if (!ts->dump_posttrans && !(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOSTTRANS))) {
+ rpmlog(RPMLOG_DEBUG, "running post-transaction scripts\n");
+ runTransScripts(ts, PKG_POSTTRANS);
+ }
+
+ /* Run %transfiletriggerpostun scripts unless disabled */
+- if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOSTTRANS|RPMTRANS_FLAG_NOTRIGGERIN))) {
++ if (!ts->dump_posttrans && !(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOSTTRANS|RPMTRANS_FLAG_NOTRIGGERIN))) {
+ runFileTriggers(ts, NULL, RPMSENSE_TRIGGERIN, RPMSCRIPT_TRANSFILETRIGGER, 0);
+ }
+- if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOSTTRANS|RPMTRANS_FLAG_NOTRIGGERPOSTUN))) {
++ if (ts->dump_posttrans || !(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOSTTRANS|RPMTRANS_FLAG_NOTRIGGERPOSTUN))) {
+ runPostUnTransFileTrigs(ts);
+ }
+
+ /* Run %transfiletriggerin scripts unless disabled */
+- if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOSTTRANS|RPMTRANS_FLAG_NOTRIGGERIN))) {
++ if (ts->dump_posttrans || !(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOSTTRANS|RPMTRANS_FLAG_NOTRIGGERIN))) {
+ runTransScripts(ts, PKG_TRANSFILETRIGGERIN);
+ }
+ /* Final exit code */
+@@ -1884,3 +1890,110 @@ exit:
+ rpmsqSetAction(SIGPIPE, oact);
+ return rc;
+ }
++
++static unsigned int runPostTransFindPkgNum(const char **lpp)
++{
++ const char *lp = *lpp;
++ unsigned int num = strtoul(lp, 0, 10);
++ while (*lp >= '0' && *lp <= '9')
++ lp++;
++ while (*lp == ' ')
++ lp++;
++ *lpp = lp;
++ return num;
++}
++
++static Header runPostTransFindPkg(rpmts ts, const char *lp)
++{
++ rpmdbMatchIterator mi;
++ Header h = NULL;
++ unsigned int hdrnum = runPostTransFindPkgNum(&lp);
++ if (!*lp)
++ return NULL;
++ if (hdrnum) {
++ mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, &hdrnum, sizeof(hdrnum));
++ h = headerLink(rpmdbNextIterator(mi));
++ rpmdbFreeIterator(mi);
++ }
++ if (h) {
++ char *NEVRA = headerGetAsString(h, RPMTAG_NEVRA);
++ if (!NEVRA || strcmp(NEVRA, lp) != 0)
++ h = headerFree(h);
++ _free(NEVRA);
++ }
++ if (!h) {
++ mi = rpmtsInitIterator(ts, RPMDBI_LABEL, lp, strlen(lp));
++ h = headerLink(rpmdbNextIterator(mi));
++ rpmdbFreeIterator(mi);
++ }
++ if (!h)
++ rpmlog(RPMLOG_WARNING, "package %s is not installed\n", lp);
++ return h;
++}
++
++int rpmtsRunPostTrans(rpmts ts, ARGV_const_t manifest)
++{
++ int rc = -1; /* assume failure */
++ /* setup */
++ tsMembers tsmem = rpmtsMembers(ts);
++ rpmtxn txn = NULL;
++ /* Ignore SIGPIPE for the duration of transaction */
++ rpmsqAction_t oact = rpmsqSetAction(SIGPIPE, RPMSQ_IGN);
++ /* Force default 022 umask during transaction for consistent results */
++ mode_t oldmask = umask(022);
++
++ if (tsmem->orderCount)
++ goto exit;
++ char *line;
++ while ((line = *manifest++) != 0) {
++ if (!strncmp(line, "dump_posttrans: install ", 24)) {
++ const char *lp = line + 24;
++ Header h = runPostTransFindPkg(ts, lp);
++ if (!h)
++ continue;
++ rpmte p = rpmteNew(ts, h, TR_ADDED, line + 45, NULL, RPMTE_INSTALL);
++ if (tsmem->orderCount >= tsmem->orderAlloced) {
++ tsmem->orderAlloced += (tsmem->orderCount - tsmem->orderAlloced) + tsmem->delta;
++ tsmem->order = xrealloc(tsmem->order, tsmem->orderAlloced * sizeof(*tsmem->order));
++ }
++ tsmem->order[tsmem->orderCount++] = p;
++
++ if (tsmem->addedPackages == NULL)
++ tsmem->addedPackages = rpmalCreate(ts, 5);
++ rpmalAdd(tsmem->addedPackages, p);
++ packageHashAddEntry(tsmem->installedPackages, headerGetInstance(h), p);
++ } else if (!strncmp(line, "dump_posttrans: transfiletriggerpostun ", 39)) {
++ const char *lp = line + 39;
++ unsigned int tix = runPostTransFindPkgNum(&lp);
++ Header h = runPostTransFindPkg(ts, lp);
++ struct rpmtd_s priorities;
++ if (!h)
++ continue;
++ headerGet(h, RPMTAG_TRANSFILETRIGGERPRIORITIES, &priorities, HEADERGET_MINMEM);
++ if (rpmtdSetIndex(&priorities, tix) >= 0)
++ rpmtriggersAdd(ts->trigs2run, headerGetInstance(h), tix, *rpmtdGetUint32(&priorities));
++ headerFree(h);
++ }
++ }
++
++ if (!(txn = rpmtxnBegin(ts, RPMTXN_WRITE)))
++ goto exit;
++
++ /* run posttrans scripts */
++ rpmlog(RPMLOG_DEBUG, "running post-transaction scripts\n");
++ runTransScripts(ts, PKG_POSTTRANS);
++ /* run %transfiletriggerin scripts */
++ runFileTriggers(ts, NULL, RPMSENSE_TRIGGERIN, RPMSCRIPT_TRANSFILETRIGGER, 0);
++ /* run %transfiletriggerpostun scrips */
++ runPostUnTransFileTrigs(ts);
++ /* Run immed %transfiletriggerin scripts */
++ runTransScripts(ts, PKG_TRANSFILETRIGGERIN);
++ rc = 0;
++
++exit:
++ (void) umask(oldmask);
++ rpmtxnEnd(txn);
++ rpmsqSetAction(SIGPIPE, oact);
++ rpmtsEmpty(ts);
++ return rc;
++}
+--- ./rpm.c.orig 2021-04-09 11:28:12.363647282 +0000
++++ ./rpm.c 2021-04-09 11:28:15.527640975 +0000
+@@ -19,6 +19,7 @@ enum modes {
+ MODE_INSTALL = (1 << 1),
+ MODE_ERASE = (1 << 2),
+ #define MODES_IE (MODE_INSTALL | MODE_ERASE)
++ MODE_RUNPOSTTRANS = (1 << 4),
+
+ MODE_UNKNOWN = 0
+ };
+@@ -114,6 +115,11 @@ int main(int argc, char *argv[])
+ INSTALL_INSTALL|INSTALL_REINSTALL));
+ int eflags = (ia->installInterfaceFlags & INSTALL_ERASE);
+
++ if (ia->installInterfaceFlags & INSTALL_RUNPOSTTRANS) {
++ if (iflags || eflags)
++ argerror(_("only one major mode may be specified"));
++ bigMode = MODE_RUNPOSTTRANS;
++ }
+ if (iflags & eflags)
+ argerror(_("only one major mode may be specified"));
+ else if (iflags)
+@@ -286,6 +292,14 @@ int main(int argc, char *argv[])
+ ec = rpmcliVerify(ts, qva, (ARGV_const_t) poptGetArgs(optCon));
+ } break;
+
++ case MODE_RUNPOSTTRANS:
++ if (!poptPeekArg(optCon)) {
++ argerror(_("need posttrans manifest for --runposttrans"));
++ } else {
++ ec += rpmRunPostTrans(ts, ia, (ARGV_const_t) poptGetArgs(optCon));
++ }
++ break;
++
+ case MODE_UNKNOWN:
+ if (poptPeekArg(optCon) != NULL || argc <= 1) {
+ printUsage(optCon, stderr, 0);
diff --git a/python-rpm.changes b/python-rpm.changes
index 1ded4f0..4bba5c3 100644
--- a/python-rpm.changes
+++ b/python-rpm.changes
@@ -1,4 +1,9 @@
-------------------------------------------------------------------
+Tue Mar 30 11:15:44 CEST 2021 - mls@suse.de
+
+- update to rpm-4.16.1.3
+
+-------------------------------------------------------------------
Wed Sep 30 14:17:40 CEST 2020 - mls@suse.de
- update to rpm-4.16.0
diff --git a/python-rpm.spec b/python-rpm.spec
index 48c2934..70911e7 100644
--- a/python-rpm.spec
+++ b/python-rpm.spec
@@ -21,7 +21,7 @@
%global with_python 1
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-rpm
-Version: 4.16.0
+Version: 4.16.1.3
Release: 0
Summary: Python Bindings for Manipulating RPM Packages
License: GPL-2.0-or-later
diff --git a/rpm-4.16.0.tar.bz2 b/rpm-4.16.0.tar.bz2
deleted file mode 120000
index f410b60..0000000
--- a/rpm-4.16.0.tar.bz2
+++ /dev/null
@@ -1 +0,0 @@
-/ipfs/bafybeiddqsr5nxto5baptdsgrm5yrhobndpoctdgurzfcqohegidc3a7lq
\ No newline at end of file
diff --git a/rpm-4.16.1.3.tar.bz2 b/rpm-4.16.1.3.tar.bz2
new file mode 120000
index 0000000..384fbe7
--- /dev/null
+++ b/rpm-4.16.1.3.tar.bz2
@@ -0,0 +1 @@
+/ipfs/bafybeiekpeiw3w24t4ly4jub44lzsebevdmixjn5fexpimmyyvlig7n4by
\ No newline at end of file
diff --git a/rpm.changes b/rpm.changes
index 827c183..487e992 100644
--- a/rpm.changes
+++ b/rpm.changes
@@ -1,4 +1,64 @@
-------------------------------------------------------------------
+Wed May 12 13:28:38 UTC 2021 - Andreas Schwab
+
+- auto-config-update-aarch64-ppc64le.diff: Treat missing timestamp as
+ infinitely old.
+
+-------------------------------------------------------------------
+Tue Apr 16 07:49:37 UTC 2021 - Martin Liška
+
+- Use --dwz-single-file-mode for packages that use
+ baselibs.conf mechanism.
+- Add add-dwz-single-file-mode-option.patch patch.
+
+-------------------------------------------------------------------
+Fri Apr 9 13:34:24 CEST 2021 - mls@suse.de
+
+- change dump_posttrans mechanism to imply --noposttrans so that
+ libzypp can be compatible with older rpm versions
+ changed patch: posttrans.diff
+
+-------------------------------------------------------------------
+Tue Apr 6 08:42:29 UTC 2021 - Andreas Schwab
+
+- auto-config-update-aarch64-ppc64le.diff: Use timestamp in file instead
+ of searching for arch name, which cannot handle all cases
+
+-------------------------------------------------------------------
+Tue Mar 30 11:15:44 CEST 2021 - mls@suse.de
+
+- update to rpm-4.16.1.3
+ * security fixes for CVE-2021-3421, CVE-2021-20271, CVE-2021-20266
+ * fix bdb_ro failing to open database with missing secondary indexes
+ * dropped: finddebuginfo-check-res-file.patch
+ * dropped: empty_dbbackend.diff
+- require the exact version of librpmbuild in the rpm-build
+ package [bnc#1180965]
+- reformat dwarf5.diff
+- add dump_posttrans and --runposttrans options to make it possible
+ for libzypp to implement file triggers
+ new patch: posttrans.diff
+
+-------------------------------------------------------------------
+Mon Feb 22 12:57:44 UTC 2021 - Martin Liška
+
+- Remove debugedit.diff and include dwarf5.diff in order to support
+ debug DWARF 5 that will be added with GCC 11.
+
+-------------------------------------------------------------------
+Mon Feb 8 09:38:33 UTC 2021 - Andreas Schwab
+
+- Use shipped config.sub/config.guess instead of stone-aged from libtool
+- auto-config-update-aarch64-ppc64le.diff: update grep regex
+
+-------------------------------------------------------------------
+Thu Jan 14 15:40:39 UTC 2021 - Matej Cepl
+
+- Add explicit requirement on python-rpm-macros to avoid widespread
+ breakage by package mistakenly ignoring their requirement of
+ python-rpm-macros (bsc#1180125).
+
+-------------------------------------------------------------------
Mon Dec 21 16:29:40 CET 2020 - mls@suse.de
- fix potential access of freed mem in ndb's glue code [bnc#1179416]
@@ -64,6 +124,11 @@ Mon Oct 19 11:53:00 CEST 2020 - mls@suse.de
* new patch: touch_backport.diff
-------------------------------------------------------------------
+Fri Oct 16 08:42:08 UTC 2020 - Ludwig Nussel
+
+- prepare usrmerge (boo#1029961)
+
+-------------------------------------------------------------------
Fri Oct 9 13:28:33 UTC 2020 - Guillaume GARDET
- Add patch to fix finddebuginfo when no res.* file are found:
diff --git a/rpm.spec b/rpm.spec
index 5cd2cf0..7738060 100644
--- a/rpm.spec
+++ b/rpm.spec
@@ -59,7 +59,7 @@ Requires: /usr/bin/awk
Summary: The RPM Package Manager
License: GPL-2.0-or-later
Group: System/Packages
-Version: 4.16.0
+Version: 4.16.1.3
Release: 0
URL: https://rpm.org/
#Git-Clone: https://github.com/rpm-software-management/rpm
@@ -74,7 +74,6 @@ Source13: rpmconfigcheck.service
Patch2: db.diff
Patch5: usr-lib-sysimage-rpm.patch
# quilt patches start here
-Patch11: debugedit.diff
Patch13: ignore-auxv.diff
Patch12: localetag.diff
Patch15: dbfsync.diff
@@ -126,9 +125,10 @@ Patch109: pythondistdeps.diff
Patch117: findsupplements.diff
Patch122: db_conversion.diff
Patch123: nextiteratorheaderblob.diff
-Patch127: finddebuginfo-check-res-file.patch
-Patch128: empty_dbbackend.diff
Patch129: ndbglue.diff
+Patch130: dwarf5.diff
+Patch131: posttrans.diff
+Patch132: add-dwz-single-file-mode-option.patch
Patch6464: auto-config-update-aarch64-ppc64le.diff
BuildRoot: %{_tmppath}/%{name}-%{version}-build
#
@@ -171,6 +171,7 @@ need an intimate knowledge of RPM packages in order to function.
%package build
Summary: Tools and Scripts to create rpm packages
Group: System/Packages
+Requires: librpmbuild%{librpmsover} = %{version}
Requires: rpm = %{version}
Provides: rpm:%_bindir/rpmbuild
Provides: rpmbuild
@@ -215,6 +216,9 @@ and requires some packages that are usually required.
Summary: RPM dependency generator for Python
Group: Development/Languages/Python
Requires: python3-base
+# To avoid widespread breakage by package mistakenly ignoring
+# their requirement of python-rpm-macros (bsc#1180125)
+Requires: python-rpm-macros
%description build-python
Provides and requires generator for .py files and modules.
@@ -230,7 +234,6 @@ Provides and requires generator for .pl files and modules.
%prep
%setup -q -n rpm-%{version}
rm -rf sqlite
-cp /usr/share/libtool/build-aux/config.guess /usr/share/libtool/build-aux/config.sub .
%if 0%{?!without_bdb:1}
tar xjf %{SOURCE11}
ln -s db-4.8.30 db
@@ -239,10 +242,10 @@ cd db
cd ..
chmod -R u+w db/*
rm -f rpmdb/db.h
-cp config.guess config.sub db/dist/
+cp build-aux/config.guess build-aux/config.sub db/dist/
%endif
%patch5 -p1
-%patch -P 11 -P 12 -P 13 -P 15 -P 16 -P 18
+%patch -P 12 -P 13 -P 15 -P 16 -P 18
%patch -P 20 -P 21 -P 24 -P 25 -P 26 -P 27 -P 29
%patch -P 30 -P 32 -P 33 -P 34 -P 35 -P 36 -P 38
%patch -P 43 -P 45 -P 46 -P 47 -P 49
@@ -253,7 +256,8 @@ cp config.guess config.sub db/dist/
%patch -P 93 -P 94 -P 99
%patch -P 100 -P 102 -P 103
%patch -P 109 -P 117
-%patch -P 122 -P 123 -P 127 -P 128 -P 129
+%patch -P 122 -P 123 -P 129 -P 130 -P 131
+%patch132 -p1
%ifarch aarch64 ppc64le riscv64
%patch6464
@@ -304,7 +308,9 @@ mkdir -p %{buildroot}/usr/share/locale
ln -s ../share/locale %{buildroot}/usr/lib/locale
%make_install
mkdir -p %{buildroot}/bin
+%if !0%{?usrmerged}
ln -s /usr/bin/rpm %{buildroot}/bin/rpm
+%endif
%if 0%{?!without_bdb:1}
install -m 644 db3/db.h %{buildroot}/usr/include/rpm
%endif
@@ -364,8 +370,8 @@ for i in /usr/share/automake-*/*; do
done
popd
%ifarch aarch64 ppc64le riscv64
-install -m 755 config.guess %{buildroot}/usr/lib/rpm
-install -m 755 config.sub %{buildroot}/usr/lib/rpm
+install -m 755 build-aux/config.guess %{buildroot}/usr/lib/rpm
+install -m 755 build-aux/config.sub %{buildroot}/usr/lib/rpm
%endif
rm -rf %{buildroot}/%{_libdir}/python%{py_ver}
rm -f %{buildroot}%{_libdir}/*.la
@@ -425,7 +431,9 @@ fi
%doc doc/manual
%doc RPM-HOWTO
/etc/rpm
+%if !0%{?usrmerged}
/bin/rpm
+%endif
%{_bindir}/gendiff
%{_bindir}/rpm
%{_bindir}/rpm2cpio