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