From 6ff1afd362ad983b98f3b6b705a6a72d3654d7e1 Mon Sep 17 00:00:00 2001 From: DistroBaker Date: Jan 20 2021 13:04:28 +0000 Subject: Merged update from upstream sources This is an automated DistroBaker update from upstream sources. If you do not know what this is about or would like to opt out, contact the OSCI team. Source: https://src.fedoraproject.org/rpms/rpm.git#ff02e06b27ca4f7483f79d49f229310646364496 --- diff --git a/.gitignore b/.gitignore index 053a1b6..5731dc6 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,6 @@ /rpm-4.16.0-beta3.tar.bz2 /rpm-4.16.0-rc1.tar.bz2 /rpm-4.16.0.tar.bz2 +/rpm-4.16.1.tar.bz2 +/rpm-4.16.1.1.tar.bz2 +/rpm-4.16.1.2.tar.bz2 diff --git a/0001-NFC-debugedit-Protect-macro-arguments-by-parentheses.patch b/0001-NFC-debugedit-Protect-macro-arguments-by-parentheses.patch new file mode 100644 index 0000000..6607373 --- /dev/null +++ b/0001-NFC-debugedit-Protect-macro-arguments-by-parentheses.patch @@ -0,0 +1,61 @@ +From a93b0f5c9f0abef6efb5413df9e98b047a2a9a46 Mon Sep 17 00:00:00 2001 +From: Jan Kratochvil +Date: Mon, 17 Aug 2020 16:56:56 +0200 +Subject: [PATCH 1/6] [NFC] debugedit: Protect macro arguments by parentheses + +--- + tools/debugedit.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 6bea88551..a351adec8 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -233,7 +233,7 @@ typedef struct + int shift = 0; \ + do \ + { \ +- c = *ptr++; \ ++ c = *(ptr)++; \ + ret |= (c & 0x7f) << shift; \ + shift += 7; \ + } while (c & 0x80); \ +@@ -251,7 +251,7 @@ typedef struct + valv >>= 7; \ + if (valv) \ + c |= 0x80; \ +- *ptr++ = c; \ ++ *(ptr)++ = c; \ + } \ + while (valv); \ + }) +@@ -311,7 +311,7 @@ strptr (DSO *dso, int sec, off_t offset) + } + + +-#define read_8(ptr) *ptr++ ++#define read_8(ptr) *(ptr)++ + + #define read_16(ptr) ({ \ + uint16_t ret = do_read_16 (ptr); \ +@@ -328,13 +328,13 @@ strptr (DSO *dso, int sec, off_t offset) + REL *relptr, *relend; + int reltype; + +-#define do_read_32_relocated(ptr) ({ \ +- uint32_t dret = do_read_32 (ptr); \ ++#define do_read_32_relocated(xptr) ({ \ ++ uint32_t dret = do_read_32 (xptr); \ + if (relptr) \ + { \ +- while (relptr < relend && relptr->ptr < ptr) \ ++ while (relptr < relend && relptr->ptr < (xptr)) \ + ++relptr; \ +- if (relptr < relend && relptr->ptr == ptr) \ ++ if (relptr < relend && relptr->ptr == (xptr)) \ + { \ + if (reltype == SHT_REL) \ + dret += relptr->addend; \ +-- +2.18.4 + diff --git a/0001-Stop-on-first-failure-when-trying-to-open-a-database.patch b/0001-Stop-on-first-failure-when-trying-to-open-a-database.patch deleted file mode 100644 index 146ed23..0000000 --- a/0001-Stop-on-first-failure-when-trying-to-open-a-database.patch +++ /dev/null @@ -1,29 +0,0 @@ -From fd054a40b2ba005571455d749de0423975e77651 Mon Sep 17 00:00:00 2001 -Message-Id: -From: Panu Matilainen -Date: Wed, 18 Nov 2020 13:56:14 +0200 -Subject: [PATCH 1/2] Stop on first failure when trying to open a database - (RhBug:1898301) - -If an index open fails there's no point trying to go on, things are -not going to work and at least BDB will segfault in some cases... ---- - lib/rpmdb.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/lib/rpmdb.c b/lib/rpmdb.c -index 874f07911..41da9da71 100644 ---- a/lib/rpmdb.c -+++ b/lib/rpmdb.c -@@ -355,7 +355,7 @@ static int doOpen(rpmdb db, int justPkgs) - { - int rc = pkgdbOpen(db, db->db_flags, NULL); - if (!justPkgs) { -- for (int dbix = 0; dbix < db->db_ndbi; dbix++) { -+ for (int dbix = 0; rc == 0 && dbix < db->db_ndbi; dbix++) { - rc += indexOpen(db, db->db_tags[dbix], db->db_flags, NULL); - } - } --- -2.28.0 - diff --git a/0002-NFC-debugedit-Move-code-from-edit_dwarf2-to-edit_inf.patch b/0002-NFC-debugedit-Move-code-from-edit_dwarf2-to-edit_inf.patch new file mode 100644 index 0000000..74c37f7 --- /dev/null +++ b/0002-NFC-debugedit-Move-code-from-edit_dwarf2-to-edit_inf.patch @@ -0,0 +1,753 @@ +From de119ea9797f3ccfa3842e3926b6ea8198607207 Mon Sep 17 00:00:00 2001 +From: Jan Kratochvil +Date: Sat, 1 Aug 2020 10:43:12 +0200 +Subject: [PATCH 2/6] [NFC] debugedit: Move code from edit_dwarf2() to + edit_info(). + +--- + tools/debugedit.c | 672 +++++++++++++++++++++++----------------------- + 1 file changed, 343 insertions(+), 329 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index a351adec8..cad0cc349 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -1964,6 +1964,106 @@ line_rel_cmp (const void *a, const void *b) + return 0; + } + ++static int ++edit_info (DSO *dso, int phase) ++{ ++ unsigned char *ptr, *endcu, *endsec; ++ uint32_t value; ++ htab_t abbrev; ++ struct abbrev_tag tag, *t; ++ ++ ptr = debug_sections[DEBUG_INFO].data; ++ setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype); ++ endsec = ptr + debug_sections[DEBUG_INFO].size; ++ while (ptr < endsec) ++ { ++ if (ptr + 11 > endsec) ++ { ++ error (0, 0, "%s: .debug_info CU header too small", ++ dso->filename); ++ return 1; ++ } ++ ++ endcu = ptr + 4; ++ endcu += read_32 (ptr); ++ if (endcu == ptr + 0xffffffff) ++ { ++ error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); ++ return 1; ++ } ++ ++ if (endcu > endsec) ++ { ++ error (0, 0, "%s: .debug_info too small", dso->filename); ++ return 1; ++ } ++ ++ cu_version = read_16 (ptr); ++ if (cu_version != 2 && cu_version != 3 && cu_version != 4) ++ { ++ error (0, 0, "%s: DWARF version %d unhandled", dso->filename, ++ cu_version); ++ return 1; ++ } ++ ++ value = read_32_relocated (ptr); ++ if (value >= debug_sections[DEBUG_ABBREV].size) ++ { ++ if (debug_sections[DEBUG_ABBREV].data == NULL) ++ error (0, 0, "%s: .debug_abbrev not present", dso->filename); ++ else ++ error (0, 0, "%s: DWARF CU abbrev offset too large", ++ dso->filename); ++ return 1; ++ } ++ ++ if (ptr_size == 0) ++ { ++ ptr_size = read_8 (ptr); ++ if (ptr_size != 4 && ptr_size != 8) ++ { ++ error (0, 0, "%s: Invalid DWARF pointer size %d", ++ dso->filename, ptr_size); ++ return 1; ++ } ++ } ++ else if (read_8 (ptr) != ptr_size) ++ { ++ error (0, 0, "%s: DWARF pointer size differs between CUs", ++ dso->filename); ++ return 1; ++ } ++ ++ abbrev = read_abbrev (dso, ++ debug_sections[DEBUG_ABBREV].data + value); ++ if (abbrev == NULL) ++ return 1; ++ ++ while (ptr < endcu) ++ { ++ tag.entry = read_uleb128 (ptr); ++ if (tag.entry == 0) ++ continue; ++ t = htab_find_with_hash (abbrev, &tag, tag.entry); ++ if (t == NULL) ++ { ++ error (0, 0, "%s: Could not find DWARF abbreviation %d", ++ dso->filename, tag.entry); ++ htab_delete (abbrev); ++ return 1; ++ } ++ ++ ptr = edit_attributes (dso, ptr, t, phase); ++ if (ptr == NULL) ++ break; ++ } ++ ++ htab_delete (abbrev); ++ } ++ ++ return 0; ++} ++ + static int + edit_dwarf2 (DSO *dso) + { +@@ -2100,385 +2200,299 @@ edit_dwarf2 (DSO *dso) + return 1; + } + +- if (debug_sections[DEBUG_INFO].data != NULL) ++ if (debug_sections[DEBUG_INFO].data == NULL) ++ return 0; ++ ++ unsigned char *ptr, *endcu, *endsec; ++ uint32_t value; ++ htab_t abbrev; ++ struct abbrev_tag tag, *t; ++ int phase; ++ bool info_rel_updated = false; ++ bool macro_rel_updated = false; ++ ++ for (phase = 0; phase < 2; phase++) + { +- unsigned char *ptr, *endcu, *endsec; +- uint32_t value; +- htab_t abbrev; +- struct abbrev_tag tag, *t; +- int phase; +- bool info_rel_updated = false; +- bool macro_rel_updated = false; ++ /* If we don't need to update anyhing, skip phase 1. */ ++ if (phase == 1 ++ && !need_strp_update ++ && !need_string_replacement ++ && !need_stmt_update) ++ break; + +- for (phase = 0; phase < 2; phase++) ++ rel_updated = false; ++ if (edit_info (dso, phase)) ++ return 1; ++ ++ /* Remember whether any .debug_info relocations might need ++ to be updated. */ ++ info_rel_updated = rel_updated; ++ ++ /* We might have to recalculate/rewrite the debug_line ++ section. We need to do that before going into phase one ++ so we have all new offsets. We do this separately from ++ scanning the dirs/file names because the DW_AT_stmt_lists ++ might not be in order or skip some padding we might have ++ to (re)move. */ ++ if (phase == 0 && need_stmt_update) + { +- /* If we don't need to update anyhing, skip phase 1. */ +- if (phase == 1 +- && !need_strp_update +- && !need_string_replacement +- && !need_stmt_update) +- break; ++ edit_dwarf2_line (dso); + +- ptr = debug_sections[DEBUG_INFO].data; +- setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype); +- rel_updated = false; +- endsec = ptr + debug_sections[DEBUG_INFO].size; +- while (ptr < endsec) ++ /* The line table programs will be moved ++ forward/backwards a bit in the new data. Update the ++ debug_line relocations to the new offsets. */ ++ int rndx = debug_sections[DEBUG_LINE].relsec; ++ if (rndx != 0) + { +- if (ptr + 11 > endsec) +- { +- error (0, 0, "%s: .debug_info CU header too small", +- dso->filename); +- return 1; +- } +- +- endcu = ptr + 4; +- endcu += read_32 (ptr); +- if (endcu == ptr + 0xffffffff) +- { +- error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); +- return 1; +- } +- +- if (endcu > endsec) +- { +- error (0, 0, "%s: .debug_info too small", dso->filename); +- return 1; +- } +- +- cu_version = read_16 (ptr); +- if (cu_version != 2 && cu_version != 3 && cu_version != 4) +- { +- error (0, 0, "%s: DWARF version %d unhandled", dso->filename, +- cu_version); +- return 1; +- } +- +- value = read_32_relocated (ptr); +- if (value >= debug_sections[DEBUG_ABBREV].size) ++ LINE_REL *rbuf; ++ size_t rels; ++ Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL); ++ int rtype = dso->shdr[rndx].sh_type; ++ rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize; ++ rbuf = malloc (rels * sizeof (LINE_REL)); ++ if (rbuf == NULL) ++ error (1, errno, "%s: Could not allocate line relocations", ++ dso->filename); ++ ++ /* Sort them by offset into section. */ ++ for (size_t i = 0; i < rels; i++) + { +- if (debug_sections[DEBUG_ABBREV].data == NULL) +- error (0, 0, "%s: .debug_abbrev not present", dso->filename); ++ if (rtype == SHT_RELA) ++ { ++ GElf_Rela rela; ++ if (gelf_getrela (rdata, i, &rela) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ rbuf[i].r_offset = rela.r_offset; ++ rbuf[i].ndx = i; ++ } + else +- error (0, 0, "%s: DWARF CU abbrev offset too large", +- dso->filename); +- return 1; +- } +- +- if (ptr_size == 0) +- { +- ptr_size = read_8 (ptr); +- if (ptr_size != 4 && ptr_size != 8) + { +- error (0, 0, "%s: Invalid DWARF pointer size %d", +- dso->filename, ptr_size); +- return 1; ++ GElf_Rel rel; ++ if (gelf_getrel (rdata, i, &rel) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ rbuf[i].r_offset = rel.r_offset; ++ rbuf[i].ndx = i; + } + } +- else if (read_8 (ptr) != ptr_size) +- { +- error (0, 0, "%s: DWARF pointer size differs between CUs", +- dso->filename); +- return 1; +- } ++ qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp); + +- abbrev = read_abbrev (dso, +- debug_sections[DEBUG_ABBREV].data + value); +- if (abbrev == NULL) +- return 1; +- +- while (ptr < endcu) ++ size_t lndx = 0; ++ for (size_t i = 0; i < rels; i++) + { +- tag.entry = read_uleb128 (ptr); +- if (tag.entry == 0) +- continue; +- t = htab_find_with_hash (abbrev, &tag, tag.entry); +- if (t == NULL) ++ /* These relocations only happen in ET_REL files ++ and are section offsets. */ ++ GElf_Addr r_offset; ++ size_t ndx = rbuf[i].ndx; ++ ++ GElf_Rel rel; ++ GElf_Rela rela; ++ if (rtype == SHT_RELA) + { +- error (0, 0, "%s: Could not find DWARF abbreviation %d", +- dso->filename, tag.entry); +- htab_delete (abbrev); +- return 1; ++ if (gelf_getrela (rdata, ndx, &rela) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ r_offset = rela.r_offset; ++ } ++ else ++ { ++ if (gelf_getrel (rdata, ndx, &rel) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ r_offset = rel.r_offset; + } + +- ptr = edit_attributes (dso, ptr, t, phase); +- if (ptr == NULL) +- break; +- } ++ while (lndx < dso->lines.used ++ && r_offset > (dso->lines.table[lndx].old_idx ++ + 4 ++ + dso->lines.table[lndx].unit_length)) ++ lndx++; + +- htab_delete (abbrev); +- } ++ if (lndx >= dso->lines.used) ++ error (1, 0, ++ ".debug_line relocation offset out of range"); + +- /* Remember whether any .debug_info relocations might need +- to be updated. */ +- info_rel_updated = rel_updated; +- +- /* We might have to recalculate/rewrite the debug_line +- section. We need to do that before going into phase one +- so we have all new offsets. We do this separately from +- scanning the dirs/file names because the DW_AT_stmt_lists +- might not be in order or skip some padding we might have +- to (re)move. */ +- if (phase == 0 && need_stmt_update) +- { +- edit_dwarf2_line (dso); ++ /* Offset (pointing into the line program) moves ++ from old to new index including the header ++ size diff. */ ++ r_offset += (ssize_t)((dso->lines.table[lndx].new_idx ++ - dso->lines.table[lndx].old_idx) ++ + dso->lines.table[lndx].size_diff); + +- /* The line table programs will be moved +- forward/backwards a bit in the new data. Update the +- debug_line relocations to the new offsets. */ +- int rndx = debug_sections[DEBUG_LINE].relsec; +- if (rndx != 0) +- { +- LINE_REL *rbuf; +- size_t rels; +- Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL); +- int rtype = dso->shdr[rndx].sh_type; +- rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize; +- rbuf = malloc (rels * sizeof (LINE_REL)); +- if (rbuf == NULL) +- error (1, errno, "%s: Could not allocate line relocations", +- dso->filename); +- +- /* Sort them by offset into section. */ +- for (size_t i = 0; i < rels; i++) ++ if (rtype == SHT_RELA) + { +- if (rtype == SHT_RELA) +- { +- GElf_Rela rela; +- if (gelf_getrela (rdata, i, &rela) == NULL) +- error (1, 0, "Couldn't get relocation: %s", +- elf_errmsg (-1)); +- rbuf[i].r_offset = rela.r_offset; +- rbuf[i].ndx = i; +- } +- else +- { +- GElf_Rel rel; +- if (gelf_getrel (rdata, i, &rel) == NULL) +- error (1, 0, "Couldn't get relocation: %s", +- elf_errmsg (-1)); +- rbuf[i].r_offset = rel.r_offset; +- rbuf[i].ndx = i; +- } ++ rela.r_offset = r_offset; ++ if (gelf_update_rela (rdata, ndx, &rela) == 0) ++ error (1, 0, "Couldn't update relocation: %s", ++ elf_errmsg (-1)); + } +- qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp); +- +- size_t lndx = 0; +- for (size_t i = 0; i < rels; i++) ++ else + { +- /* These relocations only happen in ET_REL files +- and are section offsets. */ +- GElf_Addr r_offset; +- size_t ndx = rbuf[i].ndx; +- +- GElf_Rel rel; +- GElf_Rela rela; +- if (rtype == SHT_RELA) +- { +- if (gelf_getrela (rdata, ndx, &rela) == NULL) +- error (1, 0, "Couldn't get relocation: %s", +- elf_errmsg (-1)); +- r_offset = rela.r_offset; +- } +- else +- { +- if (gelf_getrel (rdata, ndx, &rel) == NULL) +- error (1, 0, "Couldn't get relocation: %s", +- elf_errmsg (-1)); +- r_offset = rel.r_offset; +- } +- +- while (lndx < dso->lines.used +- && r_offset > (dso->lines.table[lndx].old_idx +- + 4 +- + dso->lines.table[lndx].unit_length)) +- lndx++; +- +- if (lndx >= dso->lines.used) +- error (1, 0, +- ".debug_line relocation offset out of range"); +- +- /* Offset (pointing into the line program) moves +- from old to new index including the header +- size diff. */ +- r_offset += (ssize_t)((dso->lines.table[lndx].new_idx +- - dso->lines.table[lndx].old_idx) +- + dso->lines.table[lndx].size_diff); +- +- if (rtype == SHT_RELA) +- { +- rela.r_offset = r_offset; +- if (gelf_update_rela (rdata, ndx, &rela) == 0) +- error (1, 0, "Couldn't update relocation: %s", +- elf_errmsg (-1)); +- } +- else +- { +- rel.r_offset = r_offset; +- if (gelf_update_rel (rdata, ndx, &rel) == 0) +- error (1, 0, "Couldn't update relocation: %s", +- elf_errmsg (-1)); +- } ++ rel.r_offset = r_offset; ++ if (gelf_update_rel (rdata, ndx, &rel) == 0) ++ error (1, 0, "Couldn't update relocation: %s", ++ elf_errmsg (-1)); + } +- +- elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY); +- free (rbuf); + } ++ ++ elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY); ++ free (rbuf); + } ++ } + +- /* The .debug_macro section also contains offsets into the +- .debug_str section and references to the .debug_line +- tables, so we need to update those as well if we update +- the strings or the stmts. */ +- if ((need_strp_update || need_stmt_update) +- && debug_sections[DEBUG_MACRO].data) ++ /* The .debug_macro section also contains offsets into the ++ .debug_str section and references to the .debug_line ++ tables, so we need to update those as well if we update ++ the strings or the stmts. */ ++ if ((need_strp_update || need_stmt_update) ++ && debug_sections[DEBUG_MACRO].data) ++ { ++ /* There might be multiple (COMDAT) .debug_macro sections. */ ++ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO]; ++ while (macro_sec != NULL) + { +- /* There might be multiple (COMDAT) .debug_macro sections. */ +- struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO]; +- while (macro_sec != NULL) +- { +- setup_relbuf(dso, macro_sec, &reltype); +- rel_updated = false; ++ setup_relbuf(dso, macro_sec, &reltype); ++ rel_updated = false; + +- ptr = macro_sec->data; +- endsec = ptr + macro_sec->size; +- int op = 0, macro_version, macro_flags; +- int offset_len = 4, line_offset = 0; ++ ptr = macro_sec->data; ++ endsec = ptr + macro_sec->size; ++ int op = 0, macro_version, macro_flags; ++ int offset_len = 4, line_offset = 0; + +- while (ptr < endsec) ++ while (ptr < endsec) ++ { ++ if (!op) + { +- if (!op) +- { +- macro_version = read_16 (ptr); +- macro_flags = read_8 (ptr); +- if (macro_version < 4 || macro_version > 5) +- error (1, 0, "unhandled .debug_macro version: %d", +- macro_version); +- if ((macro_flags & ~2) != 0) +- error (1, 0, "unhandled .debug_macro flags: 0x%x", +- macro_flags); +- +- offset_len = (macro_flags & 0x01) ? 8 : 4; +- line_offset = (macro_flags & 0x02) ? 1 : 0; +- +- if (offset_len != 4) +- error (0, 1, +- "Cannot handle 8 byte macro offsets: %s", +- dso->filename); +- +- /* Update the line_offset if it is there. */ +- if (line_offset) +- { +- if (phase == 0) +- ptr += offset_len; +- else +- { +- size_t idx, new_idx; +- idx = do_read_32_relocated (ptr); +- new_idx = find_new_list_offs (&dso->lines, +- idx); +- write_32_relocated (ptr, new_idx); +- } +- } +- } ++ macro_version = read_16 (ptr); ++ macro_flags = read_8 (ptr); ++ if (macro_version < 4 || macro_version > 5) ++ error (1, 0, "unhandled .debug_macro version: %d", ++ macro_version); ++ if ((macro_flags & ~2) != 0) ++ error (1, 0, "unhandled .debug_macro flags: 0x%x", ++ macro_flags); ++ ++ offset_len = (macro_flags & 0x01) ? 8 : 4; ++ line_offset = (macro_flags & 0x02) ? 1 : 0; ++ ++ if (offset_len != 4) ++ error (0, 1, ++ "Cannot handle 8 byte macro offsets: %s", ++ dso->filename); + +- op = read_8 (ptr); +- if (!op) +- continue; +- switch(op) ++ /* Update the line_offset if it is there. */ ++ if (line_offset) + { +- case DW_MACRO_GNU_define: +- case DW_MACRO_GNU_undef: +- read_uleb128 (ptr); +- ptr = ((unsigned char *) strchr ((char *) ptr, '\0') +- + 1); +- break; +- case DW_MACRO_GNU_start_file: +- read_uleb128 (ptr); +- read_uleb128 (ptr); +- break; +- case DW_MACRO_GNU_end_file: +- break; +- case DW_MACRO_GNU_define_indirect: +- case DW_MACRO_GNU_undef_indirect: +- read_uleb128 (ptr); + if (phase == 0) +- { +- size_t idx = read_32_relocated (ptr); +- record_existing_string_entry_idx (&dso->strings, +- idx); +- } ++ ptr += offset_len; + else + { +- struct stridxentry *entry; + size_t idx, new_idx; + idx = do_read_32_relocated (ptr); +- entry = string_find_entry (&dso->strings, idx); +- new_idx = strent_offset (entry->entry); ++ new_idx = find_new_list_offs (&dso->lines, ++ idx); + write_32_relocated (ptr, new_idx); + } +- break; +- case DW_MACRO_GNU_transparent_include: +- ptr += offset_len; +- break; +- default: +- error (1, 0, "Unhandled DW_MACRO op 0x%x", op); +- break; + } + } + +- if (rel_updated) +- macro_rel_updated = true; +- macro_sec = macro_sec->next; ++ op = read_8 (ptr); ++ if (!op) ++ continue; ++ switch(op) ++ { ++ case DW_MACRO_GNU_define: ++ case DW_MACRO_GNU_undef: ++ read_uleb128 (ptr); ++ ptr = ((unsigned char *) strchr ((char *) ptr, '\0') ++ + 1); ++ break; ++ case DW_MACRO_GNU_start_file: ++ read_uleb128 (ptr); ++ read_uleb128 (ptr); ++ break; ++ case DW_MACRO_GNU_end_file: ++ break; ++ case DW_MACRO_GNU_define_indirect: ++ case DW_MACRO_GNU_undef_indirect: ++ read_uleb128 (ptr); ++ if (phase == 0) ++ { ++ size_t idx = read_32_relocated (ptr); ++ record_existing_string_entry_idx (&dso->strings, ++ idx); ++ } ++ else ++ { ++ struct stridxentry *entry; ++ size_t idx, new_idx; ++ idx = do_read_32_relocated (ptr); ++ entry = string_find_entry (&dso->strings, idx); ++ new_idx = strent_offset (entry->entry); ++ write_32_relocated (ptr, new_idx); ++ } ++ break; ++ case DW_MACRO_GNU_transparent_include: ++ ptr += offset_len; ++ break; ++ default: ++ error (1, 0, "Unhandled DW_MACRO op 0x%x", op); ++ break; ++ } + } +- } + +- /* Same for the debug_str section. Make sure everything is +- in place for phase 1 updating of debug_info +- references. */ +- if (phase == 0 && need_strp_update) +- { +- Strtab *strtab = dso->strings.str_tab; +- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data; +- int strndx = debug_sections[DEBUG_STR].sec; +- Elf_Scn *strscn = dso->scn[strndx]; +- +- /* Out with the old. */ +- strdata->d_size = 0; +- /* In with the new. */ +- strdata = elf_newdata (strscn); +- +- /* We really should check whether we had enough memory, +- but the old ebl version will just abort on out of +- memory... */ +- strtab_finalize (strtab, strdata); +- debug_sections[DEBUG_STR].size = strdata->d_size; +- dso->strings.str_buf = strdata->d_buf; ++ if (rel_updated) ++ macro_rel_updated = true; ++ macro_sec = macro_sec->next; + } ++ } + ++ /* Same for the debug_str section. Make sure everything is ++ in place for phase 1 updating of debug_info ++ references. */ ++ if (phase == 0 && need_strp_update) ++ { ++ Strtab *strtab = dso->strings.str_tab; ++ Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data; ++ int strndx = debug_sections[DEBUG_STR].sec; ++ Elf_Scn *strscn = dso->scn[strndx]; ++ ++ /* Out with the old. */ ++ strdata->d_size = 0; ++ /* In with the new. */ ++ strdata = elf_newdata (strscn); ++ ++ /* We really should check whether we had enough memory, ++ but the old ebl version will just abort on out of ++ memory... */ ++ strtab_finalize (strtab, strdata); ++ debug_sections[DEBUG_STR].size = strdata->d_size; ++ dso->strings.str_buf = strdata->d_buf; + } + +- /* After phase 1 we might have rewritten the debug_info with +- new strp, strings and/or linep offsets. */ +- if (need_strp_update || need_string_replacement || need_stmt_update) +- dirty_section (DEBUG_INFO); +- if (need_strp_update || need_stmt_update) +- dirty_section (DEBUG_MACRO); +- if (need_stmt_update) +- dirty_section (DEBUG_LINE); ++ } ++ ++ /* After phase 1 we might have rewritten the debug_info with ++ new strp, strings and/or linep offsets. */ ++ if (need_strp_update || need_string_replacement || need_stmt_update) ++ dirty_section (DEBUG_INFO); ++ if (need_strp_update || need_stmt_update) ++ dirty_section (DEBUG_MACRO); ++ if (need_stmt_update) ++ dirty_section (DEBUG_LINE); + +- /* Update any relocations addends we might have touched. */ +- if (info_rel_updated) +- update_rela_data (dso, &debug_sections[DEBUG_INFO]); ++ /* Update any relocations addends we might have touched. */ ++ if (info_rel_updated) ++ update_rela_data (dso, &debug_sections[DEBUG_INFO]); + +- if (macro_rel_updated) ++ if (macro_rel_updated) ++ { ++ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO]; ++ while (macro_sec != NULL) + { +- struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO]; +- while (macro_sec != NULL) +- { +- update_rela_data (dso, macro_sec); +- macro_sec = macro_sec->next; +- } ++ update_rela_data (dso, macro_sec); ++ macro_sec = macro_sec->next; + } + } + +-- +2.18.4 + diff --git a/0002-Only-attempt-loading-the-keyring-once-the-rpmdb-is-o.patch b/0002-Only-attempt-loading-the-keyring-once-the-rpmdb-is-o.patch deleted file mode 100644 index f934e44..0000000 --- a/0002-Only-attempt-loading-the-keyring-once-the-rpmdb-is-o.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 3cb955b77f07c70ba01d765aa6377908847608f5 Mon Sep 17 00:00:00 2001 -Message-Id: <3cb955b77f07c70ba01d765aa6377908847608f5.1606726599.git.pmatilai@redhat.com> -In-Reply-To: -References: -From: Panu Matilainen -Date: Mon, 23 Nov 2020 13:46:14 +0200 -Subject: [PATCH 2/2] Only attempt loading the keyring once the rpmdb is open - -When we do lazy rpmdb open in rpmtsInitIterator(), we also do a lazy -keyring open. Except that since the keyring typically lives in the rpmdb, -we PROBABLY should try open the database first. One of those "WTF I've -been smoking" moments, lol. - -Prevents an ugly if mostly harmless double error anything we can't open -the database for one reason or another. ---- - lib/rpmts.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/lib/rpmts.c b/lib/rpmts.c -index 9fa9cb0e2..8c8ae420a 100644 ---- a/lib/rpmts.c -+++ b/lib/rpmts.c -@@ -177,12 +177,12 @@ rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmDbiTagVal rpmtag, - if (ts == NULL) - return NULL; - -- if (ts && ts->keyring == NULL) -- loadKeyring(ts); -- - if (ts->rdb == NULL && rpmtsOpenDB(ts, ts->dbmode)) - return NULL; - -+ if (ts->keyring == NULL) -+ loadKeyring(ts); -+ - /* Parse out "N(EVR)" tokens from a label key if present */ - if (rpmtag == RPMDBI_LABEL && keyp != NULL && strchr(keyp, '(')) { - const char *se, *s = keyp; --- -2.28.0 - diff --git a/0003-debugedit-Fix-missing-relocation-of-.debug_types-sec.patch b/0003-debugedit-Fix-missing-relocation-of-.debug_types-sec.patch new file mode 100644 index 0000000..dd4abb1 --- /dev/null +++ b/0003-debugedit-Fix-missing-relocation-of-.debug_types-sec.patch @@ -0,0 +1,269 @@ +From 8cd4d5046d7cb1bc16f01e77a5ff50eca8d9da3d Mon Sep 17 00:00:00 2001 +From: Jan Kratochvil +Date: Sat, 1 Aug 2020 10:45:47 +0200 +Subject: [PATCH 3/6] debugedit: Fix missing relocation of .debug_types + section. + +--- + tools/debugedit.c | 123 ++++++++++++++++++++++++++++++---------------- + 1 file changed, 80 insertions(+), 43 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index cad0cc349..87c1cd622 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -433,7 +433,8 @@ typedef struct debug_section + int sec, relsec; + REL *relbuf; + REL *relend; +- struct debug_section *next; /* Only happens for COMDAT .debug_macro. */ ++ /* Only happens for COMDAT .debug_macro and .debug_types. */ ++ struct debug_section *next; + } debug_section; + + static debug_section debug_sections[] = +@@ -1269,7 +1270,9 @@ static int dirty_elf; + static void + dirty_section (unsigned int sec) + { +- elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY); ++ for (struct debug_section *secp = &debug_sections[sec]; secp != NULL; ++ secp = secp->next) ++ elf_flagdata (secp->elf_data, ELF_C_SET, ELF_F_DIRTY); + dirty_elf = 1; + } + +@@ -1469,12 +1472,7 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) + + if (get_line_table (dso, off, &table) == false + || table == NULL) +- { +- if (table != NULL) +- error (0, 0, ".debug_line offset 0x%x referenced multiple times", +- off); +- return false; +- } ++ return false; + + /* Skip to the directory table. The rest of the header has already + been read and checked by get_line_table. */ +@@ -1965,22 +1963,25 @@ line_rel_cmp (const void *a, const void *b) + } + + static int +-edit_info (DSO *dso, int phase) ++edit_info (DSO *dso, int phase, struct debug_section *sec) + { + unsigned char *ptr, *endcu, *endsec; + uint32_t value; + htab_t abbrev; + struct abbrev_tag tag, *t; + +- ptr = debug_sections[DEBUG_INFO].data; +- setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype); +- endsec = ptr + debug_sections[DEBUG_INFO].size; ++ ptr = sec->data; ++ if (ptr == NULL) ++ return 0; ++ ++ setup_relbuf(dso, sec, &reltype); ++ endsec = ptr + sec->size; + while (ptr < endsec) + { +- if (ptr + 11 > endsec) ++ if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec) + { +- error (0, 0, "%s: .debug_info CU header too small", +- dso->filename); ++ error (0, 0, "%s: %s CU header too small", ++ dso->filename, sec->name); + return 1; + } + +@@ -1994,7 +1995,7 @@ edit_info (DSO *dso, int phase) + + if (endcu > endsec) + { +- error (0, 0, "%s: .debug_info too small", dso->filename); ++ error (0, 0, "%s: %s too small", dso->filename, sec->name); + return 1; + } + +@@ -2034,6 +2035,9 @@ edit_info (DSO *dso, int phase) + return 1; + } + ++ if (sec != &debug_sections[DEBUG_INFO]) ++ ptr += 12; /* Skip type_signature and type_offset. */ ++ + abbrev = read_abbrev (dso, + debug_sections[DEBUG_ABBREV].data + value); + if (abbrev == NULL) +@@ -2095,7 +2099,7 @@ edit_dwarf2 (DSO *dso) + struct debug_section *debug_sec = &debug_sections[j]; + if (debug_sections[j].data) + { +- if (j != DEBUG_MACRO) ++ if (j != DEBUG_MACRO && j != DEBUG_TYPES) + { + error (0, 0, "%s: Found two copies of %s section", + dso->filename, name); +@@ -2103,22 +2107,21 @@ edit_dwarf2 (DSO *dso) + } + else + { +- /* In relocatable files .debug_macro might +- appear multiple times as COMDAT +- section. */ ++ /* In relocatable files .debug_macro and .debug_types ++ might appear multiple times as COMDAT section. */ + struct debug_section *sec; + sec = calloc (sizeof (struct debug_section), 1); + if (sec == NULL) + error (1, errno, +- "%s: Could not allocate more macro sections", +- dso->filename); +- sec->name = ".debug_macro"; ++ "%s: Could not allocate more %s sections", ++ dso->filename, name); ++ sec->name = name; + +- struct debug_section *macro_sec = debug_sec; +- while (macro_sec->next != NULL) +- macro_sec = macro_sec->next; ++ struct debug_section *multi_sec = debug_sec; ++ while (multi_sec->next != NULL) ++ multi_sec = multi_sec->next; + +- macro_sec->next = sec; ++ multi_sec->next = sec; + debug_sec = sec; + } + } +@@ -2155,23 +2158,23 @@ edit_dwarf2 (DSO *dso) + + (dso->shdr[i].sh_type == SHT_RELA), + debug_sections[j].name) == 0) + { +- if (j == DEBUG_MACRO) ++ if (j == DEBUG_MACRO || j == DEBUG_TYPES) + { + /* Pick the correct one. */ + int rel_target = dso->shdr[i].sh_info; +- struct debug_section *macro_sec = &debug_sections[j]; +- while (macro_sec != NULL) ++ struct debug_section *multi_sec = &debug_sections[j]; ++ while (multi_sec != NULL) + { +- if (macro_sec->sec == rel_target) ++ if (multi_sec->sec == rel_target) + { +- macro_sec->relsec = i; ++ multi_sec->relsec = i; + break; + } +- macro_sec = macro_sec->next; ++ multi_sec = multi_sec->next; + } +- if (macro_sec == NULL) +- error (0, 1, "No .debug_macro reloc section: %s", +- dso->filename); ++ if (multi_sec == NULL) ++ error (0, 1, "No %s reloc section: %s", ++ debug_sections[j].name, dso->filename); + } + else + debug_sections[j].relsec = i; +@@ -2203,12 +2206,10 @@ edit_dwarf2 (DSO *dso) + if (debug_sections[DEBUG_INFO].data == NULL) + return 0; + +- unsigned char *ptr, *endcu, *endsec; +- uint32_t value; +- htab_t abbrev; +- struct abbrev_tag tag, *t; ++ unsigned char *ptr, *endsec; + int phase; + bool info_rel_updated = false; ++ bool types_rel_updated = false; + bool macro_rel_updated = false; + + for (phase = 0; phase < 2; phase++) +@@ -2221,13 +2222,26 @@ edit_dwarf2 (DSO *dso) + break; + + rel_updated = false; +- if (edit_info (dso, phase)) +- return 1; ++ if (edit_info (dso, phase, &debug_sections[DEBUG_INFO])) ++ return 1; + + /* Remember whether any .debug_info relocations might need + to be updated. */ + info_rel_updated = rel_updated; + ++ rel_updated = false; ++ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES]; ++ while (types_sec != NULL) ++ { ++ if (edit_info (dso, phase, types_sec)) ++ return 1; ++ types_sec = types_sec->next; ++ } ++ ++ /* Remember whether any .debug_types relocations might need ++ to be updated. */ ++ types_rel_updated = rel_updated; ++ + /* We might have to recalculate/rewrite the debug_line + section. We need to do that before going into phase one + so we have all new offsets. We do this separately from +@@ -2475,8 +2489,11 @@ edit_dwarf2 (DSO *dso) + + /* After phase 1 we might have rewritten the debug_info with + new strp, strings and/or linep offsets. */ +- if (need_strp_update || need_string_replacement || need_stmt_update) ++ if (need_strp_update || need_string_replacement || need_stmt_update) { + dirty_section (DEBUG_INFO); ++ if (debug_sections[DEBUG_TYPES].data != NULL) ++ dirty_section (DEBUG_TYPES); ++ } + if (need_strp_update || need_stmt_update) + dirty_section (DEBUG_MACRO); + if (need_stmt_update) +@@ -2485,6 +2502,15 @@ edit_dwarf2 (DSO *dso) + /* Update any relocations addends we might have touched. */ + if (info_rel_updated) + update_rela_data (dso, &debug_sections[DEBUG_INFO]); ++ if (types_rel_updated) ++ { ++ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES]; ++ while (types_sec != NULL) ++ { ++ update_rela_data (dso, types_sec); ++ types_sec = types_sec->next; ++ } ++ } + + if (macro_rel_updated) + { +@@ -3037,6 +3063,17 @@ main (int argc, char *argv[]) + macro_sec = next; + } + ++ /* In case there were multiple (COMDAT) .debug_types sections, ++ free them. */ ++ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES]; ++ types_sec = types_sec->next; ++ while (types_sec != NULL) ++ { ++ struct debug_section *next = types_sec->next; ++ free (types_sec); ++ types_sec = next; ++ } ++ + poptFreeContext (optCon); + + return 0; +-- +2.18.4 + diff --git a/0004-NFC-debugedit-Move-code-to-separate-functions.patch b/0004-NFC-debugedit-Move-code-to-separate-functions.patch new file mode 100644 index 0000000..5f13953 --- /dev/null +++ b/0004-NFC-debugedit-Move-code-to-separate-functions.patch @@ -0,0 +1,455 @@ +From bab443ab4f756ef80f814af0353143f41e90e6a6 Mon Sep 17 00:00:00 2001 +From: Jan Kratochvil +Date: Mon, 17 Aug 2020 21:58:19 +0200 +Subject: [PATCH 4/6] [NFC] debugedit: Move code to separate functions. + +New functions edit_strp, skip_form and edit_attributes_str_comp_dir +called by edit_attributes. +Split part of read_dwarf2_line into a read_dwarf4_line function. +New function edit_dwarf2_any_str called by edit_dwarf2 at the end of +phase 0 to rebuild .debug_str. +--- + tools/debugedit.c | 367 ++++++++++++++++++++++++++-------------------- + 1 file changed, 212 insertions(+), 155 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 87c1cd622..7464883c5 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -1457,37 +1457,128 @@ edit_dwarf2_line (DSO *dso) + } + } + +-/* Called during phase zero for each debug_line table referenced from +- .debug_info. Outputs all source files seen and records any +- adjustments needed in the debug_list data structures. Returns true +- if line_table needs to be rewrite either the dir or file paths. */ ++/* Record or adjust (according to phase) DW_FORM_strp. */ ++static void ++edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp) ++{ ++ unsigned char *ptr_orig = ptr; ++ ++ /* In the first pass we collect all strings, in the ++ second we put the new references back (if there are ++ any changes). */ ++ if (phase == 0) ++ { ++ /* handled_strp is set for attributes referring to ++ files. If it is set the string is already ++ recorded. */ ++ if (! handled_strp) ++ { ++ size_t idx = do_read_32_relocated (ptr); ++ record_existing_string_entry_idx (&dso->strings, idx); ++ } ++ } ++ else if (need_strp_update) /* && phase == 1 */ ++ { ++ struct stridxentry *entry; ++ size_t idx, new_idx; ++ idx = do_read_32_relocated (ptr); ++ entry = string_find_entry (&dso->strings, idx); ++ new_idx = strent_offset (entry->entry); ++ do_write_32_relocated (ptr, new_idx); ++ } ++ ++ assert (ptr == ptr_orig); ++} ++ ++/* Adjust *PTRP after the current *FORMP, update *FORMP for FORM_INDIRECT. */ ++static enum { FORM_OK, FORM_ERROR, FORM_INDIRECT } ++skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp) ++{ ++ size_t len = 0; ++ ++ switch (*formp) ++ { ++ case DW_FORM_ref_addr: ++ if (cu_version == 2) ++ *ptrp += ptr_size; ++ else ++ *ptrp += 4; ++ break; ++ case DW_FORM_flag_present: ++ break; ++ case DW_FORM_addr: ++ *ptrp += ptr_size; ++ break; ++ case DW_FORM_ref1: ++ case DW_FORM_flag: ++ case DW_FORM_data1: ++ ++*ptrp; ++ break; ++ case DW_FORM_ref2: ++ case DW_FORM_data2: ++ *ptrp += 2; ++ break; ++ case DW_FORM_ref4: ++ case DW_FORM_data4: ++ case DW_FORM_sec_offset: ++ *ptrp += 4; ++ break; ++ case DW_FORM_ref8: ++ case DW_FORM_data8: ++ case DW_FORM_ref_sig8: ++ *ptrp += 8; ++ break; ++ case DW_FORM_sdata: ++ case DW_FORM_ref_udata: ++ case DW_FORM_udata: ++ read_uleb128 (*ptrp); ++ break; ++ case DW_FORM_strp: ++ *ptrp += 4; ++ break; ++ case DW_FORM_string: ++ *ptrp = (unsigned char *) strchr ((char *)*ptrp, '\0') + 1; ++ break; ++ case DW_FORM_indirect: ++ *formp = read_uleb128 (*ptrp); ++ return FORM_INDIRECT; ++ case DW_FORM_block1: ++ len = *(*ptrp)++; ++ break; ++ case DW_FORM_block2: ++ len = read_16 (*ptrp); ++ *formp = DW_FORM_block1; ++ break; ++ case DW_FORM_block4: ++ len = read_32 (*ptrp); ++ *formp = DW_FORM_block1; ++ break; ++ case DW_FORM_block: ++ case DW_FORM_exprloc: ++ len = read_uleb128 (*ptrp); ++ *formp = DW_FORM_block1; ++ assert (len < UINT_MAX); ++ break; ++ default: ++ error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, *formp); ++ return FORM_ERROR; ++ } ++ ++ if (*formp == DW_FORM_block1) ++ *ptrp += len; ++ ++ return FORM_OK; ++} ++ ++/* Part of read_dwarf2_line processing DWARF-4. */ + static bool +-read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) ++read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir, ++ struct line_table *table) + { +- unsigned char *ptr, *dir; + unsigned char **dirt; + uint32_t value, dirt_cnt; + size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir); +- struct line_table *table; +- +- if (get_line_table (dso, off, &table) == false +- || table == NULL) +- return false; +- +- /* Skip to the directory table. The rest of the header has already +- been read and checked by get_line_table. */ +- ptr = debug_sections[DEBUG_LINE].data + off; +- ptr += (4 /* unit len */ +- + 2 /* version */ +- + 4 /* header len */ +- + 1 /* min instr len */ +- + (table->version >= 4) /* max op per instr, if version >= 4 */ +- + 1 /* default is stmt */ +- + 1 /* line base */ +- + 1 /* line range */ +- + 1 /* opcode base */ +- + table->opcode_base - 1); /* opcode len table */ +- dir = ptr; ++ unsigned char *dir = ptr; + + /* dir table: */ + value = 1; +@@ -1620,6 +1711,40 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) + read_uleb128 (ptr); + } + ++ return true; ++} ++ ++/* Called during phase zero for each debug_line table referenced from ++ .debug_info. Outputs all source files seen and records any ++ adjustments needed in the debug_list data structures. Returns true ++ if line_table needs to be rewrite either the dir or file paths. */ ++static bool ++read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) ++{ ++ unsigned char *ptr; ++ struct line_table *table; ++ ++ if (get_line_table (dso, off, &table) == false ++ || table == NULL) ++ return false; ++ ++ /* Skip to the directory table. The rest of the header has already ++ been read and checked by get_line_table. */ ++ ptr = debug_sections[DEBUG_LINE].data + off; ++ ptr += (4 /* unit len */ ++ + 2 /* version */ ++ + 4 /* header len */ ++ + 1 /* min instr len */ ++ + (table->version >= 4) /* max op per instr, if version >= 4 */ ++ + 1 /* default is stmt */ ++ + 1 /* line base */ ++ + 1 /* line range */ ++ + 1 /* opcode base */ ++ + table->opcode_base - 1); /* opcode len table */ ++ ++ if (! read_dwarf4_line (dso, ptr, comp_dir, table)) ++ return false; ++ + dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff; + return table->replace_dirs || table->replace_files; + } +@@ -1637,6 +1762,33 @@ find_new_list_offs (struct debug_lines *lines, size_t idx) + return table->new_idx; + } + ++/* Read DW_FORM_strp collecting compilation directory. */ ++static void ++edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase, ++ char **comp_dirp, bool *handled_strpp) ++{ ++ const char *dir; ++ size_t idx = do_read_32_relocated (*ptrp); ++ /* In phase zero we collect the comp_dir. */ ++ if (phase == 0) ++ { ++ if (idx >= debug_sections[DEBUG_STR].size) ++ error (1, 0, "%s: Bad string pointer index %zd for comp_dir", ++ dso->filename, idx); ++ dir = (char *) debug_sections[DEBUG_STR].data + idx; ++ ++ free (*comp_dirp); ++ *comp_dirp = strdup (dir); ++ } ++ ++ if (dest_dir != NULL && phase == 0) ++ { ++ if (record_file_string_entry_idx (&dso->strings, idx)) ++ need_strp_update = true; ++ *handled_strpp = true; ++ } ++} ++ + /* This scans the attributes of one DIE described by the given abbrev_tag. + PTR points to the data in the debug_info. It will be advanced till all + abbrev data is consumed. In phase zero data is collected, in phase one +@@ -1655,7 +1807,6 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + for (i = 0; i < t->nattr; ++i) + { + uint32_t form = t->attr[i].form; +- size_t len = 0; + while (1) + { + /* Whether we already handled a string as file for this +@@ -1743,29 +1894,8 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + } + else if (form == DW_FORM_strp && + debug_sections[DEBUG_STR].data) +- { +- const char *dir; +- size_t idx = do_read_32_relocated (ptr); +- /* In phase zero we collect the comp_dir. */ +- if (phase == 0) +- { +- if (idx >= debug_sections[DEBUG_STR].size) +- error (1, 0, +- "%s: Bad string pointer index %zd for comp_dir", +- dso->filename, idx); +- dir = (char *) debug_sections[DEBUG_STR].data + idx; +- +- free (comp_dir); +- comp_dir = strdup (dir); +- } +- +- if (dest_dir != NULL && phase == 0) +- { +- if (record_file_string_entry_idx (&dso->strings, idx)) +- need_strp_update = true; +- handled_strp = true; +- } +- } ++ edit_attributes_str_comp_dir (dso, &ptr, phase, &comp_dir, ++ &handled_strp); + } + else if ((t->tag == DW_TAG_compile_unit + || t->tag == DW_TAG_partial_unit) +@@ -1815,99 +1945,21 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + + switch (form) + { +- case DW_FORM_ref_addr: +- if (cu_version == 2) +- ptr += ptr_size; +- else +- ptr += 4; +- break; +- case DW_FORM_flag_present: +- break; +- case DW_FORM_addr: +- ptr += ptr_size; +- break; +- case DW_FORM_ref1: +- case DW_FORM_flag: +- case DW_FORM_data1: +- ++ptr; +- break; +- case DW_FORM_ref2: +- case DW_FORM_data2: +- ptr += 2; +- break; +- case DW_FORM_ref4: +- case DW_FORM_data4: +- case DW_FORM_sec_offset: +- ptr += 4; +- break; +- case DW_FORM_ref8: +- case DW_FORM_data8: +- case DW_FORM_ref_sig8: +- ptr += 8; +- break; +- case DW_FORM_sdata: +- case DW_FORM_ref_udata: +- case DW_FORM_udata: +- read_uleb128 (ptr); +- break; + case DW_FORM_strp: +- /* In the first pass we collect all strings, in the +- second we put the new references back (if there are +- any changes). */ +- if (phase == 0) +- { +- /* handled_strp is set for attributes referring to +- files. If it is set the string is already +- recorded. */ +- if (! handled_strp) +- { +- size_t idx = do_read_32_relocated (ptr); +- record_existing_string_entry_idx (&dso->strings, idx); +- } +- } +- else if (need_strp_update) /* && phase == 1 */ +- { +- struct stridxentry *entry; +- size_t idx, new_idx; +- idx = do_read_32_relocated (ptr); +- entry = string_find_entry (&dso->strings, idx); +- new_idx = strent_offset (entry->entry); +- do_write_32_relocated (ptr, new_idx); +- } +- ptr += 4; +- break; +- case DW_FORM_string: +- ptr = (unsigned char *) strchr ((char *)ptr, '\0') + 1; +- break; +- case DW_FORM_indirect: +- form = read_uleb128 (ptr); +- continue; +- case DW_FORM_block1: +- len = *ptr++; +- break; +- case DW_FORM_block2: +- len = read_16 (ptr); +- form = DW_FORM_block1; ++ edit_strp (dso, ptr, phase, handled_strp); + break; +- case DW_FORM_block4: +- len = read_32 (ptr); +- form = DW_FORM_block1; +- break; +- case DW_FORM_block: +- case DW_FORM_exprloc: +- len = read_uleb128 (ptr); +- form = DW_FORM_block1; +- assert (len < UINT_MAX); ++ } ++ ++ switch (skip_form (dso, &form, &ptr)) ++ { ++ case FORM_OK: + break; +- default: +- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, +- form); ++ case FORM_ERROR: + return NULL; ++ case FORM_INDIRECT: ++ continue; + } + +- if (form == DW_FORM_block1) +- ptr += len; +- + break; + } + } +@@ -2068,6 +2120,28 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + return 0; + } + ++/* Rebuild .debug_str. */ ++static void ++edit_dwarf2_any_str (DSO *dso) ++{ ++ Strtab *strtab = dso->strings.str_tab; ++ Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data; ++ int strndx = debug_sections[DEBUG_STR].sec; ++ Elf_Scn *strscn = dso->scn[strndx]; ++ ++ /* Out with the old. */ ++ strdata->d_size = 0; ++ /* In with the new. */ ++ strdata = elf_newdata (strscn); ++ ++ /* We really should check whether we had enough memory, ++ but the old ebl version will just abort on out of ++ memory... */ ++ strtab_finalize (strtab, strdata); ++ debug_sections[DEBUG_STR].size = strdata->d_size; ++ dso->strings.str_buf = strdata->d_buf; ++} ++ + static int + edit_dwarf2 (DSO *dso) + { +@@ -2466,24 +2540,7 @@ edit_dwarf2 (DSO *dso) + in place for phase 1 updating of debug_info + references. */ + if (phase == 0 && need_strp_update) +- { +- Strtab *strtab = dso->strings.str_tab; +- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data; +- int strndx = debug_sections[DEBUG_STR].sec; +- Elf_Scn *strscn = dso->scn[strndx]; +- +- /* Out with the old. */ +- strdata->d_size = 0; +- /* In with the new. */ +- strdata = elf_newdata (strscn); +- +- /* We really should check whether we had enough memory, +- but the old ebl version will just abort on out of +- memory... */ +- strtab_finalize (strtab, strdata); +- debug_sections[DEBUG_STR].size = strdata->d_size; +- dso->strings.str_buf = strdata->d_buf; +- } ++ edit_dwarf2_any_str (dso); + + } + +-- +2.18.4 + diff --git a/0005-debugedit-Implement-DWARF-5-unit-header-and-new-form.patch b/0005-debugedit-Implement-DWARF-5-unit-header-and-new-form.patch new file mode 100644 index 0000000..4bef1ef --- /dev/null +++ b/0005-debugedit-Implement-DWARF-5-unit-header-and-new-form.patch @@ -0,0 +1,217 @@ +From 8b5dcb4c2175ac706a4e1c34ce83301213800689 Mon Sep 17 00:00:00 2001 +From: Jan Kratochvil +Date: Mon, 18 Jan 2021 22:56:53 +0100 +Subject: [PATCH 5/6] debugedit: Implement DWARF-5 unit header and new forms + parsing. + +Recognize the various new DWARF5 .debug sections. +Parse and skip new DWARF5 forms in read_abbrev and skip_form. +Read DWARF5 unit headers for compile and partial units in edit_info. + +This is enough to be able to process gcc -gdwarf-5 produced binaries +without the new DWARF5 .debug_line format (which isn't produced with +binutils < 2.36). + +Patches slightly edited/merged by Mark Wielaard +--- + tools/debugedit.c | 88 +++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 81 insertions(+), 7 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 7464883c5..be5fee85b 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -453,6 +453,11 @@ static debug_section debug_sections[] = + #define DEBUG_TYPES 11 + #define DEBUG_MACRO 12 + #define DEBUG_GDB_SCRIPT 13 ++#define DEBUG_RNGLISTS 14 ++#define DEBUG_LINE_STR 15 ++#define DEBUG_ADDR 16 ++#define DEBUG_STR_OFFSETS 17 ++#define DEBUG_LOCLISTS 18 + { ".debug_info", NULL, NULL, 0, 0, 0 }, + { ".debug_abbrev", NULL, NULL, 0, 0, 0 }, + { ".debug_line", NULL, NULL, 0, 0, 0 }, +@@ -467,6 +472,11 @@ static debug_section debug_sections[] = + { ".debug_types", NULL, NULL, 0, 0, 0 }, + { ".debug_macro", NULL, NULL, 0, 0, 0 }, + { ".debug_gdb_scripts", NULL, NULL, 0, 0, 0 }, ++ { ".debug_rnglists", NULL, NULL, 0, 0, 0 }, ++ { ".debug_line_str", NULL, NULL, 0, 0, 0 }, ++ { ".debug_addr", NULL, NULL, 0, 0, 0 }, ++ { ".debug_str_offsets", NULL, NULL, 0, 0, 0 }, ++ { ".debug_loclists", NULL, NULL, 0, 0, 0 }, + { NULL, NULL, NULL, 0, 0, 0 } + }; + +@@ -755,12 +765,28 @@ no_memory: + } + form = read_uleb128 (ptr); + if (form == 2 +- || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8)) ++ || (form > DW_FORM_flag_present ++ && !(form == DW_FORM_ref_sig8 ++ || form == DW_FORM_data16 ++ || form == DW_FORM_implicit_const ++ || form == DW_FORM_addrx ++ || form == DW_FORM_loclistx ++ || form == DW_FORM_rnglistx ++ || form == DW_FORM_addrx1 ++ || form == DW_FORM_addrx2 ++ || form == DW_FORM_addrx3 ++ || form == DW_FORM_addrx4))) + { +- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form); ++ error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename, ++ form); + htab_delete (h); + return NULL; + } ++ if (form == DW_FORM_implicit_const) ++ { ++ /* It is SLEB128 but the value is dropped anyway. */ ++ read_uleb128 (ptr); ++ } + + t->attr[t->nattr].attr = attr; + t->attr[t->nattr++].form = form; +@@ -1505,6 +1531,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp) + *ptrp += 4; + break; + case DW_FORM_flag_present: ++ case DW_FORM_implicit_const: + break; + case DW_FORM_addr: + *ptrp += ptr_size; +@@ -1512,14 +1539,24 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp) + case DW_FORM_ref1: + case DW_FORM_flag: + case DW_FORM_data1: ++ case DW_FORM_strx1: ++ case DW_FORM_addrx1: + ++*ptrp; + break; + case DW_FORM_ref2: + case DW_FORM_data2: ++ case DW_FORM_strx2: ++ case DW_FORM_addrx2: + *ptrp += 2; + break; ++ case DW_FORM_strx3: ++ case DW_FORM_addrx3: ++ *ptrp += 3; ++ break; + case DW_FORM_ref4: + case DW_FORM_data4: ++ case DW_FORM_strx4: ++ case DW_FORM_addrx4: + case DW_FORM_sec_offset: + *ptrp += 4; + break; +@@ -1528,12 +1565,20 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp) + case DW_FORM_ref_sig8: + *ptrp += 8; + break; ++ case DW_FORM_data16: ++ *ptrp += 16; ++ break; + case DW_FORM_sdata: + case DW_FORM_ref_udata: + case DW_FORM_udata: ++ case DW_FORM_strx: ++ case DW_FORM_loclistx: ++ case DW_FORM_rnglistx: ++ case DW_FORM_addrx: + read_uleb128 (*ptrp); + break; + case DW_FORM_strp: ++ case DW_FORM_line_strp: + *ptrp += 4; + break; + case DW_FORM_string: +@@ -1560,7 +1605,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp) + assert (len < UINT_MAX); + break; + default: +- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, *formp); ++ error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename, *formp); + return FORM_ERROR; + } + +@@ -2030,7 +2075,10 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + endsec = ptr + sec->size; + while (ptr < endsec) + { +- if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec) ++ unsigned char *cu_start = ptr; ++ ++ /* header size, version, unit_type, ptr_size. */ ++ if (ptr + 4 + 2 + 1 + 1 > endsec) + { + error (0, 0, "%s: %s CU header too small", + dso->filename, sec->name); +@@ -2052,13 +2100,36 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + } + + cu_version = read_16 (ptr); +- if (cu_version != 2 && cu_version != 3 && cu_version != 4) ++ if (cu_version != 2 && cu_version != 3 && cu_version != 4 ++ && cu_version != 5) + { + error (0, 0, "%s: DWARF version %d unhandled", dso->filename, + cu_version); + return 1; + } + ++ int cu_ptr_size = 0; ++ ++ if (cu_version >= 5) ++ { ++ uint8_t unit_type = read_8 (ptr); ++ if (unit_type != DW_UT_compile && unit_type != DW_UT_partial) ++ { ++ error (0, 0, "%s: Unit type %u unhandled", dso->filename, ++ unit_type); ++ return 1; ++ } ++ ++ cu_ptr_size = read_8 (ptr); ++ } ++ ++ unsigned char *header_end = (cu_start + 23 + (cu_version < 5 ? 0 : 1)); ++ if (header_end > endsec) ++ { ++ error (0, 0, "%s: %s CU header too small", dso->filename, sec->name); ++ return 1; ++ } ++ + value = read_32_relocated (ptr); + if (value >= debug_sections[DEBUG_ABBREV].size) + { +@@ -2070,9 +2141,12 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + return 1; + } + ++ if (cu_version < 5) ++ cu_ptr_size = read_8 (ptr); ++ + if (ptr_size == 0) + { +- ptr_size = read_8 (ptr); ++ ptr_size = cu_ptr_size; + if (ptr_size != 4 && ptr_size != 8) + { + error (0, 0, "%s: Invalid DWARF pointer size %d", +@@ -2080,7 +2154,7 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + return 1; + } + } +- else if (read_8 (ptr) != ptr_size) ++ else if (cu_ptr_size != ptr_size) + { + error (0, 0, "%s: DWARF pointer size differs between CUs", + dso->filename); +-- +2.18.4 + diff --git a/0006-debugedit-Handle-DWARF-5-debug_line-and-debug_line_s.patch b/0006-debugedit-Handle-DWARF-5-debug_line-and-debug_line_s.patch new file mode 100644 index 0000000..f85ff17 --- /dev/null +++ b/0006-debugedit-Handle-DWARF-5-debug_line-and-debug_line_s.patch @@ -0,0 +1,772 @@ +From d9947f2dc0c2cd812f8e64380d5f6f53705a5280 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Tue, 19 Jan 2021 04:12:33 +0100 +Subject: [PATCH 6/6] debugedit: Handle DWARF-5 debug_line and debug_line_str. + +Handle the new DWARF5 .debug_line tables and the new DW_FORM_line_strp. +DWARF5 tables are handled separately from the earlier tables. They +will never change size, but they do need updates to the .debug_str +or .debug_line_str references. + +Based on a patch from Jan Kratochvil +--- + tools/debugedit.c | 471 ++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 410 insertions(+), 61 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index be5fee85b..d6a0058e9 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -103,6 +103,8 @@ static bool need_string_replacement = false; + /* Whether we need to do any updates of the string indexes (DW_FORM_strp) + in debug_info for string indexes. */ + static bool need_strp_update = false; ++/* Likewise for DW_FORM_line_strp. */ ++static bool need_line_strp_update = false; + /* If the debug_line changes size we will need to update the + DW_AT_stmt_list attributes indexes in the debug_info. */ + static bool need_stmt_update = false; +@@ -192,7 +194,7 @@ typedef struct + const char *filename; + int lastscn; + size_t phnum; +- struct strings strings; ++ struct strings debug_str, debug_line_str; + struct debug_lines lines; + GElf_Shdr shdr[0]; + } DSO; +@@ -553,10 +555,11 @@ setup_relbuf (DSO *dso, debug_section *sec, int *reltype) + /* Relocations against section symbols are uninteresting in REL. */ + if (dso->shdr[i].sh_type == SHT_REL && sym.st_value == 0) + continue; +- /* Only consider relocations against .debug_str, .debug_line +- and .debug_abbrev. */ ++ /* Only consider relocations against .debug_str, .debug_line, ++ .debug_line_str, and .debug_abbrev. */ + if (sym.st_shndx != debug_sections[DEBUG_STR].sec + && sym.st_shndx != debug_sections[DEBUG_LINE].sec ++ && sym.st_shndx != debug_sections[DEBUG_LINE_STR].sec + && sym.st_shndx != debug_sections[DEBUG_ABBREV].sec) + continue; + rela.r_addend += sym.st_value; +@@ -768,6 +771,7 @@ no_memory: + || (form > DW_FORM_flag_present + && !(form == DW_FORM_ref_sig8 + || form == DW_FORM_data16 ++ || form == DW_FORM_line_strp + || form == DW_FORM_implicit_const + || form == DW_FORM_addrx + || form == DW_FORM_loclistx +@@ -1049,17 +1053,20 @@ string_find_entry (struct strings *strings, size_t old_idx) + a replacement file string has been recorded for it, otherwise + returns false. */ + static bool +-record_file_string_entry_idx (struct strings *strings, size_t old_idx) ++record_file_string_entry_idx (bool line_strp, DSO *dso, size_t old_idx) + { ++ struct strings *strings = line_strp ? &dso->debug_line_str : &dso->debug_str; + bool ret = false; + struct stridxentry *entry = string_find_new_entry (strings, old_idx); + if (entry != NULL) + { +- if (old_idx >= debug_sections[DEBUG_STR].size) +- error (1, 0, "Bad string pointer index %zd", old_idx); ++ debug_section *sec = &debug_sections[line_strp ++ ? DEBUG_LINE_STR : DEBUG_STR]; ++ if (old_idx >= sec->size) ++ error (1, 0, "Bad string pointer index %zd (%s)", old_idx, sec->name); + + Strent *strent; +- const char *old_str = (char *)debug_sections[DEBUG_STR].data + old_idx; ++ const char *old_str = (char *)sec->data + old_idx; + const char *file = skip_dir_prefix (old_str, base_dir); + if (file == NULL) + { +@@ -1103,15 +1110,18 @@ record_file_string_entry_idx (struct strings *strings, size_t old_idx) + base_dir with dest_dir, just records the existing string associated + with the index. */ + static void +-record_existing_string_entry_idx (struct strings *strings, size_t old_idx) ++record_existing_string_entry_idx (bool line_strp, DSO *dso, size_t old_idx) + { ++ struct strings *strings = line_strp ? &dso->debug_line_str : &dso->debug_str; + struct stridxentry *entry = string_find_new_entry (strings, old_idx); + if (entry != NULL) + { +- if (old_idx >= debug_sections[DEBUG_STR].size) +- error (1, 0, "Bad string pointer index %zd", old_idx); ++ debug_section *sec = &debug_sections[line_strp ++ ? DEBUG_LINE_STR : DEBUG_STR]; ++ if (old_idx >= sec->size) ++ error (1, 0, "Bad string pointer index %zd (%s)", old_idx, sec->name); + +- const char *str = (char *)debug_sections[DEBUG_STR].data + old_idx; ++ const char *str = (char *)sec->data + old_idx; + Strent *strent = strtab_add_len (strings->str_tab, + str, strlen (str) + 1); + if (strent == NULL) +@@ -1244,13 +1254,28 @@ get_line_table (DSO *dso, size_t off, struct line_table **table) + + /* version */ + t->version = read_16 (ptr); +- if (t->version != 2 && t->version != 3 && t->version != 4) ++ if (t->version != 2 && t->version != 3 && t->version != 4 && t->version != 5) + { + error (0, 0, "%s: DWARF version %d unhandled", dso->filename, + t->version); + return false; + } + ++ if (t->version >= 5) ++ { ++ /* address_size */ ++ assert (ptr_size != 0); ++ if (ptr_size != read_8 (ptr)) ++ { ++ error (0, 0, "%s: .debug_line address size differs from .debug_info", ++ dso->filename); ++ return false; ++ } ++ ++ /* segment_selector_size */ ++ (void) read_8 (ptr); ++ } ++ + /* header_length */ + unsigned char *endprol = ptr + 4; + t->header_length = read_32 (ptr); +@@ -1343,7 +1368,9 @@ edit_dwarf2_line (DSO *dso) + + linedata->d_size = dso->lines.debug_lines_len; + linedata->d_buf = dso->lines.line_buf; ++ debug_sections[DEBUG_LINE].data = linedata->d_buf; + debug_sections[DEBUG_LINE].size = linedata->d_size; ++ debug_sections[DEBUG_LINE].elf_data = linedata; + + /* Make sure the line tables are sorted on the old index. */ + qsort (dso->lines.table, dso->lines.used, sizeof (struct line_table), +@@ -1483,9 +1510,10 @@ edit_dwarf2_line (DSO *dso) + } + } + +-/* Record or adjust (according to phase) DW_FORM_strp. */ ++/* Record or adjust (according to phase) DW_FORM_strp or DW_FORM_line_strp. */ + static void +-edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp) ++edit_strp (DSO *dso, bool line_strp, unsigned char *ptr, int phase, ++ bool handled_strp) + { + unsigned char *ptr_orig = ptr; + +@@ -1500,15 +1528,18 @@ edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp) + if (! handled_strp) + { + size_t idx = do_read_32_relocated (ptr); +- record_existing_string_entry_idx (&dso->strings, idx); ++ record_existing_string_entry_idx (line_strp, dso, idx); + } + } +- else if (need_strp_update) /* && phase == 1 */ ++ else if (line_strp ++ ? need_line_strp_update : need_strp_update) /* && phase == 1 */ + { + struct stridxentry *entry; + size_t idx, new_idx; ++ struct strings *strings = (line_strp ++ ? &dso->debug_line_str : &dso->debug_str); + idx = do_read_32_relocated (ptr); +- entry = string_find_entry (&dso->strings, idx); ++ entry = string_find_entry (strings, idx); + new_idx = strent_offset (entry->entry); + do_write_32_relocated (ptr, new_idx); + } +@@ -1759,6 +1790,254 @@ read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir, + return true; + } + ++/* Called by read_dwarf5_line first for directories and then file ++ names as they both have the same format. */ ++static bool ++read_dwarf5_line_entries (DSO *dso, unsigned char **ptrp, ++ struct line_table *table, int phase, ++ char ***dirs, int *ndir, ++ const char *entry_name) ++{ ++ /* directory_entry_format_count */ ++ /* file_name_entry_format_count */ ++ unsigned format_count = read_8 (*ptrp); ++ ++ unsigned char *formats = *ptrp; ++ ++ /* directory_entry_format */ ++ /* file_name_entry_format */ ++ for (unsigned formati = 0; formati < format_count; ++formati) ++ { ++ read_uleb128 (*ptrp); ++ read_uleb128 (*ptrp); ++ } ++ ++ /* directories_count */ ++ /* file_names_count */ ++ unsigned entry_count = read_uleb128 (*ptrp); ++ ++ bool collecting_dirs = dest_dir && phase == 0 && *dirs == NULL; ++ bool writing_files = dest_dir && phase == 0 && *dirs != NULL; ++ if (collecting_dirs) ++ { ++ *ndir = entry_count; ++ *dirs = malloc (entry_count * sizeof (char *)); ++ if (*dirs == NULL) ++ error (1, errno, "%s: Could not allocate debug_line dirs", ++ dso->filename); ++ } ++ ++ /* directories */ ++ /* file_names */ ++ for (unsigned entryi = 0; entryi < entry_count; ++entryi) ++ { ++ char *dir = NULL; ++ char *file = NULL;; ++ unsigned char *format_ptr = formats; ++ for (unsigned formati = 0; formati < format_count; ++formati) ++ { ++ unsigned lnct = read_uleb128 (format_ptr); ++ unsigned form = read_uleb128 (format_ptr); ++ bool handled_form = false; ++ bool handled_strp = false; ++ bool line_strp = form == DW_FORM_line_strp; ++ if (lnct == DW_LNCT_path) ++ { ++ switch (form) ++ { ++ case DW_FORM_strp: ++ case DW_FORM_line_strp: ++ if (dest_dir && phase == 0) ++ { ++ size_t idx = do_read_32_relocated (*ptrp); ++ if (record_file_string_entry_idx (line_strp, dso, idx)) ++ { ++ if (line_strp) ++ need_line_strp_update = true; ++ else ++ need_strp_update = true; ++ } ++ handled_strp = true; ++ if (collecting_dirs || writing_files) ++ { ++ debug_section *sec = &debug_sections[line_strp ++ ? DEBUG_LINE_STR : DEBUG_STR]; ++ if (collecting_dirs) ++ dir = (char *)sec->data + idx; ++ if (writing_files) ++ file = (char *)sec->data + idx; ++ } ++ } ++ break; ++ default: ++ error (0, 0, "%s: Unsupported " ++ ".debug_line %s %u path DW_FORM_0x%x", ++ dso->filename, entry_name, entryi, form); ++ return false; ++ } ++ } ++ if (writing_files && lnct == DW_LNCT_directory_index) ++ { ++ int dirndx; ++ switch (form) ++ { ++ case DW_FORM_udata: ++ handled_form = true; ++ dirndx = read_uleb128 (*ptrp); ++ break; ++ case DW_FORM_data1: ++ dirndx = **ptrp; ++ break; ++ case DW_FORM_data2: ++ dirndx = do_read_16 (*ptrp); ++ break; ++ case DW_FORM_data4: ++ dirndx = do_read_32 (*ptrp); ++ break; ++ default: ++ error (0, 0, "%s: Unsupported " ++ ".debug_line %s %u dirndx DW_FORM_0x%x", ++ dso->filename, entry_name, entryi, form); ++ return false; ++ } ++ ++ if (dirndx > *ndir) ++ { ++ error (0, 0, "%s: Bad dir number %u in .debug_line %s", ++ dso->filename, entryi, entry_name); ++ return false; ++ } ++ dir = (*dirs)[dirndx]; ++ } ++ ++ switch (form) ++ { ++ case DW_FORM_strp: ++ case DW_FORM_line_strp: ++ edit_strp (dso, line_strp, *ptrp, phase, handled_strp); ++ break; ++ } ++ ++ if (!handled_form) ++ { ++ switch (skip_form (dso, &form, ptrp)) ++ { ++ case FORM_OK: ++ break; ++ case FORM_ERROR: ++ return false; ++ case FORM_INDIRECT: ++ error (0, 0, "%s: Unsupported " ++ ".debug_line %s %u DW_FORM_indirect", ++ dso->filename, entry_name, entryi); ++ return false; ++ } ++ } ++ } ++ ++ if (collecting_dirs) ++ (*dirs)[entryi] = dir; ++ ++ if (writing_files) ++ { ++ char *comp_dir = (*dirs)[0]; ++ size_t comp_dir_len = strlen(comp_dir); ++ size_t file_len = strlen (file); ++ size_t dir_len = strlen (dir); ++ ++ char *s = malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1); ++ if (s == NULL) ++ { ++ error (0, ENOMEM, "%s: Reading file table", dso->filename); ++ return false; ++ } ++ if (file[0] == '/') ++ { ++ memcpy (s, file, file_len + 1); ++ } ++ else if (dir[0] == '/') ++ { ++ memcpy (s, dir, dir_len); ++ s[dir_len] = '/'; ++ memcpy (s + dir_len + 1, file, file_len + 1); ++ } ++ else ++ { ++ char *p = s; ++ if (comp_dir_len != 0) ++ { ++ memcpy (s, comp_dir, comp_dir_len); ++ s[comp_dir_len] = '/'; ++ p += comp_dir_len + 1; ++ } ++ memcpy (p, dir, dir_len); ++ p[dir_len] = '/'; ++ memcpy (p + dir_len + 1, file, file_len + 1); ++ } ++ canonicalize_path (s, s); ++ if (list_file_fd != -1) ++ { ++ const char *p = NULL; ++ if (base_dir == NULL) ++ p = s; ++ else ++ { ++ p = skip_dir_prefix (s, base_dir); ++ if (p == NULL && dest_dir != NULL) ++ p = skip_dir_prefix (s, dest_dir); ++ } ++ ++ if (p) ++ { ++ size_t size = strlen (p) + 1; ++ while (size > 0) ++ { ++ ssize_t ret = write (list_file_fd, p, size); ++ if (ret == -1) ++ break; ++ size -= ret; ++ p += ret; ++ } ++ } ++ } ++ ++ free (s); ++ } ++ } ++ ++ return true; ++} ++ ++/* Part of read_dwarf2_line processing DWARF-5. */ ++static bool ++read_dwarf5_line (DSO *dso, unsigned char *ptr, struct line_table *table, ++ int phase) ++{ ++ char **dirs = NULL; ++ int ndir; ++ /* Skip header. */ ++ ptr += (4 /* unit len */ ++ + 2 /* version */ ++ + (table->version < 5 ? 0 : 0 ++ + 1 /* address_size */ ++ + 1 /* segment_selector*/) ++ + 4 /* header len */ ++ + 1 /* min instr len */ ++ + (table->version >= 4) /* max op per instr, if version >= 4 */ ++ + 1 /* default is stmt */ ++ + 1 /* line base */ ++ + 1 /* line range */ ++ + 1 /* opcode base */ ++ + table->opcode_base - 1); /* opcode len table */ ++ ++ bool retval = (read_dwarf5_line_entries (dso, &ptr, table, phase, ++ &dirs, &ndir, "directory") ++ && read_dwarf5_line_entries (dso, &ptr, table, phase, ++ &dirs, &ndir, "file name")); ++ free (dirs); ++ return retval; ++} ++ + /* Called during phase zero for each debug_line table referenced from + .debug_info. Outputs all source files seen and records any + adjustments needed in the debug_list data structures. Returns true +@@ -1778,6 +2057,9 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) + ptr = debug_sections[DEBUG_LINE].data + off; + ptr += (4 /* unit len */ + + 2 /* version */ ++ + (table->version < 5 ? 0 : 0 ++ + 1 /* address_size */ ++ + 1 /* segment_selector*/) + + 4 /* header len */ + + 1 /* min instr len */ + + (table->version >= 4) /* max op per instr, if version >= 4 */ +@@ -1787,8 +2069,13 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) + + 1 /* opcode base */ + + table->opcode_base - 1); /* opcode len table */ + +- if (! read_dwarf4_line (dso, ptr, comp_dir, table)) +- return false; ++ /* DWARF version 5 line tables won't change size. But they might need ++ [line]strp recording/updates. Handle that part later. */ ++ if (table->version < 5) ++ { ++ if (! read_dwarf4_line (dso, ptr, comp_dir, table)) ++ return false; ++ } + + dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff; + return table->replace_dirs || table->replace_files; +@@ -1807,20 +2094,22 @@ find_new_list_offs (struct debug_lines *lines, size_t idx) + return table->new_idx; + } + +-/* Read DW_FORM_strp collecting compilation directory. */ ++/* Read DW_FORM_strp or DW_FORM_line_strp collecting compilation directory. */ + static void +-edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase, +- char **comp_dirp, bool *handled_strpp) ++edit_attributes_str_comp_dir (bool line_strp, DSO *dso, unsigned char **ptrp, ++ int phase, char **comp_dirp, bool *handled_strpp) + { + const char *dir; + size_t idx = do_read_32_relocated (*ptrp); + /* In phase zero we collect the comp_dir. */ + if (phase == 0) + { +- if (idx >= debug_sections[DEBUG_STR].size) +- error (1, 0, "%s: Bad string pointer index %zd for comp_dir", +- dso->filename, idx); +- dir = (char *) debug_sections[DEBUG_STR].data + idx; ++ debug_section *sec = &debug_sections[line_strp ++ ? DEBUG_LINE_STR : DEBUG_STR]; ++ if (sec->data == NULL || idx >= debug_sections[DEBUG_STR].size) ++ error (1, 0, "%s: Bad string pointer index %zd for comp_dir (%s)", ++ dso->filename, idx, sec->name); ++ dir = (char *) sec->data + idx; + + free (*comp_dirp); + *comp_dirp = strdup (dir); +@@ -1828,8 +2117,13 @@ edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase, + + if (dest_dir != NULL && phase == 0) + { +- if (record_file_string_entry_idx (&dso->strings, idx)) +- need_strp_update = true; ++ if (record_file_string_entry_idx (line_strp, dso, idx)) ++ { ++ if (line_strp) ++ need_line_strp_update = true; ++ else ++ need_strp_update = true; ++ } + *handled_strpp = true; + } + } +@@ -1937,17 +2231,24 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + } + } + } +- else if (form == DW_FORM_strp && +- debug_sections[DEBUG_STR].data) +- edit_attributes_str_comp_dir (dso, &ptr, phase, &comp_dir, ++ else if (form == DW_FORM_strp) ++ edit_attributes_str_comp_dir (false /* line_strp */, dso, ++ &ptr, phase, &comp_dir, + &handled_strp); ++ else if (form == DW_FORM_line_strp) ++ edit_attributes_str_comp_dir (true /* line_strp */, dso, &ptr, ++ phase, &comp_dir, &handled_strp); + } + else if ((t->tag == DW_TAG_compile_unit + || t->tag == DW_TAG_partial_unit) +- && t->attr[i].attr == DW_AT_name +- && form == DW_FORM_strp +- && debug_sections[DEBUG_STR].data) ++ && ((form == DW_FORM_strp ++ && debug_sections[DEBUG_STR].data) ++ || (form == DW_FORM_line_strp ++ && debug_sections[DEBUG_LINE_STR].data)) ++ && t->attr[i].attr == DW_AT_name) + { ++ bool line_strp = form == DW_FORM_line_strp; ++ + /* DW_AT_name is the primary file for this compile + unit. If starting with / it is a full path name. + Note that we don't handle DW_FORM_string in this +@@ -1957,11 +2258,14 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + /* In phase zero we will look for a comp_dir to use. */ + if (phase == 0) + { +- if (idx >= debug_sections[DEBUG_STR].size) ++ debug_section *sec = &debug_sections[line_strp ++ ? DEBUG_LINE_STR ++ : DEBUG_STR]; ++ if (idx >= sec->size) + error (1, 0, +- "%s: Bad string pointer index %zd for unit name", +- dso->filename, idx); +- char *name = (char *) debug_sections[DEBUG_STR].data + idx; ++ "%s: Bad string pointer index %zd for unit name (%s)", ++ dso->filename, idx, sec->name); ++ char *name = (char *) sec->data + idx; + if (*name == '/' && comp_dir == NULL) + { + char *enddir = strrchr (name, '/'); +@@ -1982,8 +2286,13 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + pass (1) stores it (the new index). */ + if (dest_dir && phase == 0) + { +- if (record_file_string_entry_idx (&dso->strings, idx)) +- need_strp_update = true; ++ if (record_file_string_entry_idx (line_strp, dso, idx)) ++ { ++ if (line_strp) ++ need_line_strp_update = true; ++ else ++ need_strp_update = true; ++ } + handled_strp = true; + } + } +@@ -1991,7 +2300,10 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + switch (form) + { + case DW_FORM_strp: +- edit_strp (dso, ptr, phase, handled_strp); ++ edit_strp (dso, false /* line_strp */, ptr, phase, handled_strp); ++ break; ++ case DW_FORM_line_strp: ++ edit_strp (dso, true /* line_strp */, ptr, phase, handled_strp); + break; + } + +@@ -2196,11 +2508,11 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + + /* Rebuild .debug_str. */ + static void +-edit_dwarf2_any_str (DSO *dso) ++edit_dwarf2_any_str (DSO *dso, struct strings *strings, debug_section *secp) + { +- Strtab *strtab = dso->strings.str_tab; +- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data; +- int strndx = debug_sections[DEBUG_STR].sec; ++ Strtab *strtab = strings->str_tab; ++ Elf_Data *strdata = secp->elf_data; ++ int strndx = secp->sec; + Elf_Scn *strscn = dso->scn[strndx]; + + /* Out with the old. */ +@@ -2212,8 +2524,8 @@ edit_dwarf2_any_str (DSO *dso) + but the old ebl version will just abort on out of + memory... */ + strtab_finalize (strtab, strdata); +- debug_sections[DEBUG_STR].size = strdata->d_size; +- dso->strings.str_buf = strdata->d_buf; ++ secp->size = strdata->d_size; ++ strings->str_buf = strdata->d_buf; + } + + static int +@@ -2359,12 +2671,14 @@ edit_dwarf2 (DSO *dso) + bool info_rel_updated = false; + bool types_rel_updated = false; + bool macro_rel_updated = false; ++ bool line_rel_updated = false; + + for (phase = 0; phase < 2; phase++) + { + /* If we don't need to update anyhing, skip phase 1. */ + if (phase == 1 + && !need_strp_update ++ && !need_line_strp_update + && !need_string_replacement + && !need_stmt_update) + break; +@@ -2582,15 +2896,14 @@ edit_dwarf2 (DSO *dso) + if (phase == 0) + { + size_t idx = read_32_relocated (ptr); +- record_existing_string_entry_idx (&dso->strings, +- idx); ++ record_existing_string_entry_idx (false, dso, idx); + } + else + { + struct stridxentry *entry; + size_t idx, new_idx; + idx = do_read_32_relocated (ptr); +- entry = string_find_entry (&dso->strings, idx); ++ entry = string_find_entry (&dso->debug_str, idx); + new_idx = strent_offset (entry->entry); + write_32_relocated (ptr, new_idx); + } +@@ -2610,24 +2923,50 @@ edit_dwarf2 (DSO *dso) + } + } + +- /* Same for the debug_str section. Make sure everything is +- in place for phase 1 updating of debug_info ++ ++ /* Now handle all the DWARF5 line tables, they contain strp ++ and/or line_strp entries that need to be registered/rewritten. */ ++ setup_relbuf(dso, &debug_sections[DEBUG_LINE], &reltype); ++ rel_updated = false; ++ ++ /* edit_dwarf2_line will have set this up, unless there are no ++ moved/resized (DWARF4) lines. In which case we can just use ++ the original section data. new_idx will have been setup ++ correctly, even if it is the same as old_idx. */ ++ unsigned char *line_buf = (unsigned char *)dso->lines.line_buf; ++ if (line_buf == NULL) ++ line_buf = debug_sections[DEBUG_LINE].data; ++ for (int ldx = 0; ldx < dso->lines.used; ldx++) ++ { ++ struct line_table *t = &dso->lines.table[ldx]; ++ if (t->version >= 5) ++ read_dwarf5_line (dso, line_buf + t->new_idx, t, phase); ++ } ++ if (rel_updated) ++ line_rel_updated = true; ++ ++ /* Same for the debug_str and debug_line_str sections. ++ Make sure everything is in place for phase 1 updating of debug_info + references. */ + if (phase == 0 && need_strp_update) +- edit_dwarf2_any_str (dso); +- ++ edit_dwarf2_any_str (dso, &dso->debug_str, ++ &debug_sections[DEBUG_STR]); ++ if (phase == 0 && need_line_strp_update) ++ edit_dwarf2_any_str (dso, &dso->debug_line_str, ++ &debug_sections[DEBUG_LINE_STR]); + } + + /* After phase 1 we might have rewritten the debug_info with + new strp, strings and/or linep offsets. */ +- if (need_strp_update || need_string_replacement || need_stmt_update) { ++ if (need_strp_update || need_line_strp_update ++ || need_string_replacement || need_stmt_update) { + dirty_section (DEBUG_INFO); + if (debug_sections[DEBUG_TYPES].data != NULL) + dirty_section (DEBUG_TYPES); + } + if (need_strp_update || need_stmt_update) + dirty_section (DEBUG_MACRO); +- if (need_stmt_update) ++ if (need_stmt_update || need_line_strp_update) + dirty_section (DEBUG_LINE); + + /* Update any relocations addends we might have touched. */ +@@ -2653,6 +2992,9 @@ edit_dwarf2 (DSO *dso) + } + } + ++ if (line_rel_updated) ++ update_rela_data (dso, &debug_sections[DEBUG_LINE]); ++ + return 0; + } + +@@ -2745,7 +3087,8 @@ fdopen_dso (int fd, const char *name) + } + + dso->filename = (const char *) strdup (name); +- setup_strings (&dso->strings); ++ setup_strings (&dso->debug_str); ++ setup_strings (&dso->debug_line_str); + setup_lines (&dso->lines); + return dso; + +@@ -2753,7 +3096,8 @@ error_out: + if (dso) + { + free ((char *) dso->filename); +- destroy_strings (&dso->strings); ++ destroy_strings (&dso->debug_str); ++ destroy_strings (&dso->debug_line_str); + destroy_lines (&dso->lines); + free (dso); + } +@@ -3034,7 +3378,9 @@ main (int argc, char *argv[]) + in elfutils before 0.169 we will have to update and write out all + section data if any data has changed (when ELF_F_LAYOUT was + set). https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */ +- bool need_update = need_strp_update || need_stmt_update; ++ bool need_update = (need_strp_update ++ || need_line_strp_update ++ || need_stmt_update); + + #if !_ELFUTILS_PREREQ (0, 169) + /* string replacements or build_id updates don't change section size. */ +@@ -3106,10 +3452,12 @@ main (int argc, char *argv[]) + GElf_Xword sec_size = shdr->sh_size; + + /* We might have changed the size (and content) of the +- debug_str or debug_line section. */ ++ debug_str, debug_line_str or debug_line section. */ + size_t secnum = elf_ndxscn (scn); + if (secnum == debug_sections[DEBUG_STR].sec) + sec_size = debug_sections[DEBUG_STR].size; ++ if (secnum == debug_sections[DEBUG_LINE_STR].sec) ++ sec_size = debug_sections[DEBUG_LINE_STR].size; + if (secnum == debug_sections[DEBUG_LINE].sec) + sec_size = debug_sections[DEBUG_LINE].size; + +@@ -3179,7 +3527,8 @@ main (int argc, char *argv[]) + chmod (file, stat_buf.st_mode); + + free ((char *) dso->filename); +- destroy_strings (&dso->strings); ++ destroy_strings (&dso->debug_str); ++ destroy_strings (&dso->debug_line_str); + destroy_lines (&dso->lines); + free (dso); + +-- +2.18.4 + diff --git a/rpm.spec b/rpm.spec index 2e9a888..6dc0d70 100644 --- a/rpm.spec +++ b/rpm.spec @@ -1,7 +1,14 @@ -# build against xz? -%bcond_without xz + # run internal testsuite? +# fakechroot is severely broken beyond fedora 33, disable... +%if 0%{?fedora} > 33 || 0%{?rhel} > 8 %bcond_with check +%else +%bcond_without check +%endif + +# build against xz? +%bcond_without xz # build with plugins? %bcond_without plugins # build with libarchive? (needed for rpm2archive) @@ -23,9 +30,10 @@ %define rpmhome /usr/lib/rpm -%global rpmver 4.16.0 +%global rpmver 4.16.1.2 #global snapver rc1 -%global rel 4 +%global rel 3 +%global sover 9 %global srcver %{rpmver}%{?snapver:-%{snapver}} %global srcdir %{?snapver:testing}%{!?snapver:rpm-%(echo %{rpmver} | cut -d'.' -f1-2).x} @@ -60,14 +68,20 @@ Patch6: 0001-find-debuginfo.sh-decompress-DWARF-compressed-ELF-se.patch Patch7: 0001-Issue-deprecation-warning-when-creating-BDB-database.patch # Patches already upstream: -Patch100: 0001-Stop-on-first-failure-when-trying-to-open-a-database.patch -Patch101: 0002-Only-attempt-loading-the-keyring-once-the-rpmdb-is-o.patch # These are not yet upstream Patch906: rpm-4.7.1-geode-i686.patch # Probably to be upstreamed in slightly different form Patch907: rpm-4.15.x-ldflags.patch +# Not yet (all) upstream, debugedit DWARF5 +Patch911: 0001-NFC-debugedit-Protect-macro-arguments-by-parentheses.patch +Patch912: 0002-NFC-debugedit-Move-code-from-edit_dwarf2-to-edit_inf.patch +Patch913: 0003-debugedit-Fix-missing-relocation-of-.debug_types-sec.patch +Patch914: 0004-NFC-debugedit-Move-code-to-separate-functions.patch +Patch915: 0005-debugedit-Implement-DWARF-5-unit-header-and-new-form.patch +Patch916: 0006-debugedit-Handle-DWARF-5-debug_line-and-debug_line_s.patch + # Partially GPL/LGPL dual-licensed and some bits with BSD # SourceLicense: (GPLv2+ and LGPLv2+ with exceptions) and BSD License: GPLv2+ @@ -470,8 +484,10 @@ fi %dir %{rpmhome}/fileattrs %files libs -%{_libdir}/librpmio.so.* -%{_libdir}/librpm.so.* +%{_libdir}/librpmio.so.%{sover} +%{_libdir}/librpm.so.%{sover} +%{_libdir}/librpmio.so.%{sover}.* +%{_libdir}/librpm.so.%{sover}.* %if %{with plugins} %dir %{_libdir}/rpm-plugins @@ -502,10 +518,12 @@ fi %endif %files build-libs -%{_libdir}/librpmbuild.so.* +%{_libdir}/librpmbuild.so.%{sover} +%{_libdir}/librpmbuild.so.%{sover}.* %files sign-libs -%{_libdir}/librpmsign.so.* +%{_libdir}/librpmsign.so.%{sover} +%{_libdir}/librpmsign.so.%{sover}.* %files build %{_bindir}/rpmbuild @@ -555,6 +573,25 @@ fi %doc doc/librpm/html/* %changelog +* Tue Jan 19 2021 Jeff Law - 4.16.1.2-3 +- Fix typo in test for F33 or newer + +* Tue Jan 19 2021 Mark Wielaard - 4.16.1.2-2 +- Add debugedit DWARF5 support + +* Wed Dec 16 2020 Panu Matilainen - 4.16.1.2-1 +- Rebase to rpm 4.16.1.2 (http://rpm.org/wiki/Releases/4.16.1.2) +- Add a spec safeguard for accidental soname bumps + +* Wed Dec 16 2020 Panu Matilainen - 4.16.1.1-1 +- Rebase to rpm 4.16.1.1 (http://rpm.org/wiki/Releases/4.16.1.1) + +* Thu Dec 10 2020 Panu Matilainen - 4.16.1-1 +- Rebase to rpm 4.16.1 (http://rpm.org/wiki/Releases/4.16.1) + +* Mon Nov 30 2020 Panu Matilainen - 4.16.0-5 +- Only disable test-suite where it's actually broken + * Mon Nov 30 2020 Panu Matilainen - 4.16.0-4 - Fix BDB crashing on failed open attempts (#1902395, #1898299, #1900407) - Fix unnecessary double failure on lazy keyring open diff --git a/sources b/sources index 284d259..6ff9108 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (rpm-4.16.0.tar.bz2) = 177119c3ac3d48980db55bb4ba0fdbb2a911968e5efc690bfa8cc343f850fc90531cc0dee6dd8e45d2b14f0d951ced35bd8893d24011b7f270745d281ddf4e3d +SHA512 (rpm-4.16.1.2.tar.bz2) = 066b67838312f9ad076285fe8f43527aded694f5562ead4e90df48675f2e99c1f2d68693fd20b2037e2614b978ed94c417753e2dbd055a9869b45264cd932afc