import rpm-4.16.1.3-7.el9

This commit is contained in:
CentOS Sources 2021-11-03 19:36:12 -04:00 committed by Stepan Oksanichenko
commit 3d7ad814bf
22 changed files with 4437 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
SOURCES/rpm-4.16.1.3.tar.bz2

1
.rpm.metadata Normal file
View File

@ -0,0 +1 @@
4c70c0dc08aec5ba29f3ee72eda774bd32230f77 SOURCES/rpm-4.16.1.3.tar.bz2

View File

@ -0,0 +1,28 @@
From 5a80033676f331de2b0979fe7be9557279b6bff3 Mon Sep 17 00:00:00 2001
Message-Id: <5a80033676f331de2b0979fe7be9557279b6bff3.1603865959.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 28 Oct 2020 08:14:55 +0200
Subject: [PATCH] Issue deprecation warning when creating BDB databases
---
lib/backend/db3.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/backend/db3.c b/lib/backend/db3.c
index 68cfa6fb2..cb31676e7 100644
--- a/lib/backend/db3.c
+++ b/lib/backend/db3.c
@@ -874,6 +874,10 @@ static int db3_dbiOpen(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flag
oflags &= ~DB_RDONLY;
dbtype = (rpmtag == RPMDBI_PACKAGES) ? DB_HASH : DB_BTREE;
retry_open--;
+ if (rpmtag == RPMDBI_PACKAGES) {
+ rpmlog(RPMLOG_WARNING,
+ "using deprecated bdb database backend");
+ }
} else {
retry_open = 0;
}
--
2.28.0

View File

@ -0,0 +1,61 @@
From a93b0f5c9f0abef6efb5413df9e98b047a2a9a46 Mon Sep 17 00:00:00 2001
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Date: Mon, 17 Aug 2020 16:56:56 +0200
Subject: [PATCH 1/6] [NFC] debugedit: Protect macro arguments by parentheses
---
tools/debugedit.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index 6bea88551..a351adec8 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -233,7 +233,7 @@ typedef struct
int shift = 0; \
do \
{ \
- c = *ptr++; \
+ c = *(ptr)++; \
ret |= (c & 0x7f) << shift; \
shift += 7; \
} while (c & 0x80); \
@@ -251,7 +251,7 @@ typedef struct
valv >>= 7; \
if (valv) \
c |= 0x80; \
- *ptr++ = c; \
+ *(ptr)++ = c; \
} \
while (valv); \
})
@@ -311,7 +311,7 @@ strptr (DSO *dso, int sec, off_t offset)
}
-#define read_8(ptr) *ptr++
+#define read_8(ptr) *(ptr)++
#define read_16(ptr) ({ \
uint16_t ret = do_read_16 (ptr); \
@@ -328,13 +328,13 @@ strptr (DSO *dso, int sec, off_t offset)
REL *relptr, *relend;
int reltype;
-#define do_read_32_relocated(ptr) ({ \
- uint32_t dret = do_read_32 (ptr); \
+#define do_read_32_relocated(xptr) ({ \
+ uint32_t dret = do_read_32 (xptr); \
if (relptr) \
{ \
- while (relptr < relend && relptr->ptr < ptr) \
+ while (relptr < relend && relptr->ptr < (xptr)) \
++relptr; \
- if (relptr < relend && relptr->ptr == ptr) \
+ if (relptr < relend && relptr->ptr == (xptr)) \
{ \
if (reltype == SHT_REL) \
dret += relptr->addend; \
--
2.18.4

View File

@ -0,0 +1,30 @@
From f2bc669cd0a080792522dd1bb7f50ef7025f16f0 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
Date: Sat, 21 Jul 2018 10:13:04 +0200
Subject: [PATCH] find-debuginfo.sh: decompress DWARF compressed ELF sections
debugedit and dwz do not support DWARF compressed ELF sections, let's
just decompress those before extracting debuginfo.
Tested-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
---
scripts/find-debuginfo.sh | 3 +++
1 file changed, 3 insertions(+)
diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh
index 90a44942d..7b01bc036 100755
--- a/scripts/find-debuginfo.sh
+++ b/scripts/find-debuginfo.sh
@@ -357,6 +357,9 @@ do_file()
get_debugfn "$f"
[ -f "${debugfn}" ] && return
+ echo "explicitly decompress any DWARF compressed ELF sections in $f"
+ eu-elfcompress -q -p -t none "$f"
+
echo "extracting debug info from $f"
# See also cpio SOURCEFILE copy. Directories must match up.
debug_base_name="$RPM_BUILD_DIR"
--
2.18.0

View File

@ -0,0 +1,753 @@
From de119ea9797f3ccfa3842e3926b6ea8198607207 Mon Sep 17 00:00:00 2001
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Date: Sat, 1 Aug 2020 10:43:12 +0200
Subject: [PATCH 2/6] [NFC] debugedit: Move code from edit_dwarf2() to
edit_info().
---
tools/debugedit.c | 672 +++++++++++++++++++++++-----------------------
1 file changed, 343 insertions(+), 329 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index a351adec8..cad0cc349 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -1964,6 +1964,106 @@ line_rel_cmp (const void *a, const void *b)
return 0;
}
+static int
+edit_info (DSO *dso, int phase)
+{
+ unsigned char *ptr, *endcu, *endsec;
+ uint32_t value;
+ htab_t abbrev;
+ struct abbrev_tag tag, *t;
+
+ ptr = debug_sections[DEBUG_INFO].data;
+ setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
+ endsec = ptr + debug_sections[DEBUG_INFO].size;
+ while (ptr < endsec)
+ {
+ if (ptr + 11 > endsec)
+ {
+ error (0, 0, "%s: .debug_info CU header too small",
+ dso->filename);
+ return 1;
+ }
+
+ endcu = ptr + 4;
+ endcu += read_32 (ptr);
+ if (endcu == ptr + 0xffffffff)
+ {
+ error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
+ return 1;
+ }
+
+ if (endcu > endsec)
+ {
+ error (0, 0, "%s: .debug_info too small", dso->filename);
+ return 1;
+ }
+
+ cu_version = read_16 (ptr);
+ if (cu_version != 2 && cu_version != 3 && cu_version != 4)
+ {
+ error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
+ cu_version);
+ return 1;
+ }
+
+ value = read_32_relocated (ptr);
+ if (value >= debug_sections[DEBUG_ABBREV].size)
+ {
+ if (debug_sections[DEBUG_ABBREV].data == NULL)
+ error (0, 0, "%s: .debug_abbrev not present", dso->filename);
+ else
+ error (0, 0, "%s: DWARF CU abbrev offset too large",
+ dso->filename);
+ return 1;
+ }
+
+ if (ptr_size == 0)
+ {
+ ptr_size = read_8 (ptr);
+ if (ptr_size != 4 && ptr_size != 8)
+ {
+ error (0, 0, "%s: Invalid DWARF pointer size %d",
+ dso->filename, ptr_size);
+ return 1;
+ }
+ }
+ else if (read_8 (ptr) != ptr_size)
+ {
+ error (0, 0, "%s: DWARF pointer size differs between CUs",
+ dso->filename);
+ return 1;
+ }
+
+ abbrev = read_abbrev (dso,
+ debug_sections[DEBUG_ABBREV].data + value);
+ if (abbrev == NULL)
+ return 1;
+
+ while (ptr < endcu)
+ {
+ tag.entry = read_uleb128 (ptr);
+ if (tag.entry == 0)
+ continue;
+ t = htab_find_with_hash (abbrev, &tag, tag.entry);
+ if (t == NULL)
+ {
+ error (0, 0, "%s: Could not find DWARF abbreviation %d",
+ dso->filename, tag.entry);
+ htab_delete (abbrev);
+ return 1;
+ }
+
+ ptr = edit_attributes (dso, ptr, t, phase);
+ if (ptr == NULL)
+ break;
+ }
+
+ htab_delete (abbrev);
+ }
+
+ return 0;
+}
+
static int
edit_dwarf2 (DSO *dso)
{
@@ -2100,385 +2200,299 @@ edit_dwarf2 (DSO *dso)
return 1;
}
- if (debug_sections[DEBUG_INFO].data != NULL)
+ if (debug_sections[DEBUG_INFO].data == NULL)
+ return 0;
+
+ unsigned char *ptr, *endcu, *endsec;
+ uint32_t value;
+ htab_t abbrev;
+ struct abbrev_tag tag, *t;
+ int phase;
+ bool info_rel_updated = false;
+ bool macro_rel_updated = false;
+
+ for (phase = 0; phase < 2; phase++)
{
- unsigned char *ptr, *endcu, *endsec;
- uint32_t value;
- htab_t abbrev;
- struct abbrev_tag tag, *t;
- int phase;
- bool info_rel_updated = false;
- bool macro_rel_updated = false;
+ /* If we don't need to update anyhing, skip phase 1. */
+ if (phase == 1
+ && !need_strp_update
+ && !need_string_replacement
+ && !need_stmt_update)
+ break;
- for (phase = 0; phase < 2; phase++)
+ rel_updated = false;
+ if (edit_info (dso, phase))
+ return 1;
+
+ /* Remember whether any .debug_info relocations might need
+ to be updated. */
+ info_rel_updated = rel_updated;
+
+ /* We might have to recalculate/rewrite the debug_line
+ section. We need to do that before going into phase one
+ so we have all new offsets. We do this separately from
+ scanning the dirs/file names because the DW_AT_stmt_lists
+ might not be in order or skip some padding we might have
+ to (re)move. */
+ if (phase == 0 && need_stmt_update)
{
- /* If we don't need to update anyhing, skip phase 1. */
- if (phase == 1
- && !need_strp_update
- && !need_string_replacement
- && !need_stmt_update)
- break;
+ edit_dwarf2_line (dso);
- ptr = debug_sections[DEBUG_INFO].data;
- setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
- rel_updated = false;
- endsec = ptr + debug_sections[DEBUG_INFO].size;
- while (ptr < endsec)
+ /* The line table programs will be moved
+ forward/backwards a bit in the new data. Update the
+ debug_line relocations to the new offsets. */
+ int rndx = debug_sections[DEBUG_LINE].relsec;
+ if (rndx != 0)
{
- if (ptr + 11 > endsec)
- {
- error (0, 0, "%s: .debug_info CU header too small",
- dso->filename);
- return 1;
- }
-
- endcu = ptr + 4;
- endcu += read_32 (ptr);
- if (endcu == ptr + 0xffffffff)
- {
- error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
- return 1;
- }
-
- if (endcu > endsec)
- {
- error (0, 0, "%s: .debug_info too small", dso->filename);
- return 1;
- }
-
- cu_version = read_16 (ptr);
- if (cu_version != 2 && cu_version != 3 && cu_version != 4)
- {
- error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
- cu_version);
- return 1;
- }
-
- value = read_32_relocated (ptr);
- if (value >= debug_sections[DEBUG_ABBREV].size)
+ LINE_REL *rbuf;
+ size_t rels;
+ Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL);
+ int rtype = dso->shdr[rndx].sh_type;
+ rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize;
+ rbuf = malloc (rels * sizeof (LINE_REL));
+ if (rbuf == NULL)
+ error (1, errno, "%s: Could not allocate line relocations",
+ dso->filename);
+
+ /* Sort them by offset into section. */
+ for (size_t i = 0; i < rels; i++)
{
- if (debug_sections[DEBUG_ABBREV].data == NULL)
- error (0, 0, "%s: .debug_abbrev not present", dso->filename);
+ if (rtype == SHT_RELA)
+ {
+ GElf_Rela rela;
+ if (gelf_getrela (rdata, i, &rela) == NULL)
+ error (1, 0, "Couldn't get relocation: %s",
+ elf_errmsg (-1));
+ rbuf[i].r_offset = rela.r_offset;
+ rbuf[i].ndx = i;
+ }
else
- error (0, 0, "%s: DWARF CU abbrev offset too large",
- dso->filename);
- return 1;
- }
-
- if (ptr_size == 0)
- {
- ptr_size = read_8 (ptr);
- if (ptr_size != 4 && ptr_size != 8)
{
- error (0, 0, "%s: Invalid DWARF pointer size %d",
- dso->filename, ptr_size);
- return 1;
+ GElf_Rel rel;
+ if (gelf_getrel (rdata, i, &rel) == NULL)
+ error (1, 0, "Couldn't get relocation: %s",
+ elf_errmsg (-1));
+ rbuf[i].r_offset = rel.r_offset;
+ rbuf[i].ndx = i;
}
}
- else if (read_8 (ptr) != ptr_size)
- {
- error (0, 0, "%s: DWARF pointer size differs between CUs",
- dso->filename);
- return 1;
- }
+ qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp);
- abbrev = read_abbrev (dso,
- debug_sections[DEBUG_ABBREV].data + value);
- if (abbrev == NULL)
- return 1;
-
- while (ptr < endcu)
+ size_t lndx = 0;
+ for (size_t i = 0; i < rels; i++)
{
- tag.entry = read_uleb128 (ptr);
- if (tag.entry == 0)
- continue;
- t = htab_find_with_hash (abbrev, &tag, tag.entry);
- if (t == NULL)
+ /* These relocations only happen in ET_REL files
+ and are section offsets. */
+ GElf_Addr r_offset;
+ size_t ndx = rbuf[i].ndx;
+
+ GElf_Rel rel;
+ GElf_Rela rela;
+ if (rtype == SHT_RELA)
{
- error (0, 0, "%s: Could not find DWARF abbreviation %d",
- dso->filename, tag.entry);
- htab_delete (abbrev);
- return 1;
+ if (gelf_getrela (rdata, ndx, &rela) == NULL)
+ error (1, 0, "Couldn't get relocation: %s",
+ elf_errmsg (-1));
+ r_offset = rela.r_offset;
+ }
+ else
+ {
+ if (gelf_getrel (rdata, ndx, &rel) == NULL)
+ error (1, 0, "Couldn't get relocation: %s",
+ elf_errmsg (-1));
+ r_offset = rel.r_offset;
}
- ptr = edit_attributes (dso, ptr, t, phase);
- if (ptr == NULL)
- break;
- }
+ while (lndx < dso->lines.used
+ && r_offset > (dso->lines.table[lndx].old_idx
+ + 4
+ + dso->lines.table[lndx].unit_length))
+ lndx++;
- htab_delete (abbrev);
- }
+ if (lndx >= dso->lines.used)
+ error (1, 0,
+ ".debug_line relocation offset out of range");
- /* Remember whether any .debug_info relocations might need
- to be updated. */
- info_rel_updated = rel_updated;
-
- /* We might have to recalculate/rewrite the debug_line
- section. We need to do that before going into phase one
- so we have all new offsets. We do this separately from
- scanning the dirs/file names because the DW_AT_stmt_lists
- might not be in order or skip some padding we might have
- to (re)move. */
- if (phase == 0 && need_stmt_update)
- {
- edit_dwarf2_line (dso);
+ /* Offset (pointing into the line program) moves
+ from old to new index including the header
+ size diff. */
+ r_offset += (ssize_t)((dso->lines.table[lndx].new_idx
+ - dso->lines.table[lndx].old_idx)
+ + dso->lines.table[lndx].size_diff);
- /* The line table programs will be moved
- forward/backwards a bit in the new data. Update the
- debug_line relocations to the new offsets. */
- int rndx = debug_sections[DEBUG_LINE].relsec;
- if (rndx != 0)
- {
- LINE_REL *rbuf;
- size_t rels;
- Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL);
- int rtype = dso->shdr[rndx].sh_type;
- rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize;
- rbuf = malloc (rels * sizeof (LINE_REL));
- if (rbuf == NULL)
- error (1, errno, "%s: Could not allocate line relocations",
- dso->filename);
-
- /* Sort them by offset into section. */
- for (size_t i = 0; i < rels; i++)
+ if (rtype == SHT_RELA)
{
- if (rtype == SHT_RELA)
- {
- GElf_Rela rela;
- if (gelf_getrela (rdata, i, &rela) == NULL)
- error (1, 0, "Couldn't get relocation: %s",
- elf_errmsg (-1));
- rbuf[i].r_offset = rela.r_offset;
- rbuf[i].ndx = i;
- }
- else
- {
- GElf_Rel rel;
- if (gelf_getrel (rdata, i, &rel) == NULL)
- error (1, 0, "Couldn't get relocation: %s",
- elf_errmsg (-1));
- rbuf[i].r_offset = rel.r_offset;
- rbuf[i].ndx = i;
- }
+ rela.r_offset = r_offset;
+ if (gelf_update_rela (rdata, ndx, &rela) == 0)
+ error (1, 0, "Couldn't update relocation: %s",
+ elf_errmsg (-1));
}
- qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp);
-
- size_t lndx = 0;
- for (size_t i = 0; i < rels; i++)
+ else
{
- /* These relocations only happen in ET_REL files
- and are section offsets. */
- GElf_Addr r_offset;
- size_t ndx = rbuf[i].ndx;
-
- GElf_Rel rel;
- GElf_Rela rela;
- if (rtype == SHT_RELA)
- {
- if (gelf_getrela (rdata, ndx, &rela) == NULL)
- error (1, 0, "Couldn't get relocation: %s",
- elf_errmsg (-1));
- r_offset = rela.r_offset;
- }
- else
- {
- if (gelf_getrel (rdata, ndx, &rel) == NULL)
- error (1, 0, "Couldn't get relocation: %s",
- elf_errmsg (-1));
- r_offset = rel.r_offset;
- }
-
- while (lndx < dso->lines.used
- && r_offset > (dso->lines.table[lndx].old_idx
- + 4
- + dso->lines.table[lndx].unit_length))
- lndx++;
-
- if (lndx >= dso->lines.used)
- error (1, 0,
- ".debug_line relocation offset out of range");
-
- /* Offset (pointing into the line program) moves
- from old to new index including the header
- size diff. */
- r_offset += (ssize_t)((dso->lines.table[lndx].new_idx
- - dso->lines.table[lndx].old_idx)
- + dso->lines.table[lndx].size_diff);
-
- if (rtype == SHT_RELA)
- {
- rela.r_offset = r_offset;
- if (gelf_update_rela (rdata, ndx, &rela) == 0)
- error (1, 0, "Couldn't update relocation: %s",
- elf_errmsg (-1));
- }
- else
- {
- rel.r_offset = r_offset;
- if (gelf_update_rel (rdata, ndx, &rel) == 0)
- error (1, 0, "Couldn't update relocation: %s",
- elf_errmsg (-1));
- }
+ rel.r_offset = r_offset;
+ if (gelf_update_rel (rdata, ndx, &rel) == 0)
+ error (1, 0, "Couldn't update relocation: %s",
+ elf_errmsg (-1));
}
-
- elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY);
- free (rbuf);
}
+
+ elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY);
+ free (rbuf);
}
+ }
- /* The .debug_macro section also contains offsets into the
- .debug_str section and references to the .debug_line
- tables, so we need to update those as well if we update
- the strings or the stmts. */
- if ((need_strp_update || need_stmt_update)
- && debug_sections[DEBUG_MACRO].data)
+ /* The .debug_macro section also contains offsets into the
+ .debug_str section and references to the .debug_line
+ tables, so we need to update those as well if we update
+ the strings or the stmts. */
+ if ((need_strp_update || need_stmt_update)
+ && debug_sections[DEBUG_MACRO].data)
+ {
+ /* There might be multiple (COMDAT) .debug_macro sections. */
+ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
+ while (macro_sec != NULL)
{
- /* There might be multiple (COMDAT) .debug_macro sections. */
- struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
- while (macro_sec != NULL)
- {
- setup_relbuf(dso, macro_sec, &reltype);
- rel_updated = false;
+ setup_relbuf(dso, macro_sec, &reltype);
+ rel_updated = false;
- ptr = macro_sec->data;
- endsec = ptr + macro_sec->size;
- int op = 0, macro_version, macro_flags;
- int offset_len = 4, line_offset = 0;
+ ptr = macro_sec->data;
+ endsec = ptr + macro_sec->size;
+ int op = 0, macro_version, macro_flags;
+ int offset_len = 4, line_offset = 0;
- while (ptr < endsec)
+ while (ptr < endsec)
+ {
+ if (!op)
{
- if (!op)
- {
- macro_version = read_16 (ptr);
- macro_flags = read_8 (ptr);
- if (macro_version < 4 || macro_version > 5)
- error (1, 0, "unhandled .debug_macro version: %d",
- macro_version);
- if ((macro_flags & ~2) != 0)
- error (1, 0, "unhandled .debug_macro flags: 0x%x",
- macro_flags);
-
- offset_len = (macro_flags & 0x01) ? 8 : 4;
- line_offset = (macro_flags & 0x02) ? 1 : 0;
-
- if (offset_len != 4)
- error (0, 1,
- "Cannot handle 8 byte macro offsets: %s",
- dso->filename);
-
- /* Update the line_offset if it is there. */
- if (line_offset)
- {
- if (phase == 0)
- ptr += offset_len;
- else
- {
- size_t idx, new_idx;
- idx = do_read_32_relocated (ptr);
- new_idx = find_new_list_offs (&dso->lines,
- idx);
- write_32_relocated (ptr, new_idx);
- }
- }
- }
+ macro_version = read_16 (ptr);
+ macro_flags = read_8 (ptr);
+ if (macro_version < 4 || macro_version > 5)
+ error (1, 0, "unhandled .debug_macro version: %d",
+ macro_version);
+ if ((macro_flags & ~2) != 0)
+ error (1, 0, "unhandled .debug_macro flags: 0x%x",
+ macro_flags);
+
+ offset_len = (macro_flags & 0x01) ? 8 : 4;
+ line_offset = (macro_flags & 0x02) ? 1 : 0;
+
+ if (offset_len != 4)
+ error (0, 1,
+ "Cannot handle 8 byte macro offsets: %s",
+ dso->filename);
- op = read_8 (ptr);
- if (!op)
- continue;
- switch(op)
+ /* Update the line_offset if it is there. */
+ if (line_offset)
{
- case DW_MACRO_GNU_define:
- case DW_MACRO_GNU_undef:
- read_uleb128 (ptr);
- ptr = ((unsigned char *) strchr ((char *) ptr, '\0')
- + 1);
- break;
- case DW_MACRO_GNU_start_file:
- read_uleb128 (ptr);
- read_uleb128 (ptr);
- break;
- case DW_MACRO_GNU_end_file:
- break;
- case DW_MACRO_GNU_define_indirect:
- case DW_MACRO_GNU_undef_indirect:
- read_uleb128 (ptr);
if (phase == 0)
- {
- size_t idx = read_32_relocated (ptr);
- record_existing_string_entry_idx (&dso->strings,
- idx);
- }
+ ptr += offset_len;
else
{
- struct stridxentry *entry;
size_t idx, new_idx;
idx = do_read_32_relocated (ptr);
- entry = string_find_entry (&dso->strings, idx);
- new_idx = strent_offset (entry->entry);
+ new_idx = find_new_list_offs (&dso->lines,
+ idx);
write_32_relocated (ptr, new_idx);
}
- break;
- case DW_MACRO_GNU_transparent_include:
- ptr += offset_len;
- break;
- default:
- error (1, 0, "Unhandled DW_MACRO op 0x%x", op);
- break;
}
}
- if (rel_updated)
- macro_rel_updated = true;
- macro_sec = macro_sec->next;
+ op = read_8 (ptr);
+ if (!op)
+ continue;
+ switch(op)
+ {
+ case DW_MACRO_GNU_define:
+ case DW_MACRO_GNU_undef:
+ read_uleb128 (ptr);
+ ptr = ((unsigned char *) strchr ((char *) ptr, '\0')
+ + 1);
+ break;
+ case DW_MACRO_GNU_start_file:
+ read_uleb128 (ptr);
+ read_uleb128 (ptr);
+ break;
+ case DW_MACRO_GNU_end_file:
+ break;
+ case DW_MACRO_GNU_define_indirect:
+ case DW_MACRO_GNU_undef_indirect:
+ read_uleb128 (ptr);
+ if (phase == 0)
+ {
+ size_t idx = read_32_relocated (ptr);
+ record_existing_string_entry_idx (&dso->strings,
+ idx);
+ }
+ else
+ {
+ struct stridxentry *entry;
+ size_t idx, new_idx;
+ idx = do_read_32_relocated (ptr);
+ entry = string_find_entry (&dso->strings, idx);
+ new_idx = strent_offset (entry->entry);
+ write_32_relocated (ptr, new_idx);
+ }
+ break;
+ case DW_MACRO_GNU_transparent_include:
+ ptr += offset_len;
+ break;
+ default:
+ error (1, 0, "Unhandled DW_MACRO op 0x%x", op);
+ break;
+ }
}
- }
- /* Same for the debug_str section. Make sure everything is
- in place for phase 1 updating of debug_info
- references. */
- if (phase == 0 && need_strp_update)
- {
- Strtab *strtab = dso->strings.str_tab;
- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
- int strndx = debug_sections[DEBUG_STR].sec;
- Elf_Scn *strscn = dso->scn[strndx];
-
- /* Out with the old. */
- strdata->d_size = 0;
- /* In with the new. */
- strdata = elf_newdata (strscn);
-
- /* We really should check whether we had enough memory,
- but the old ebl version will just abort on out of
- memory... */
- strtab_finalize (strtab, strdata);
- debug_sections[DEBUG_STR].size = strdata->d_size;
- dso->strings.str_buf = strdata->d_buf;
+ if (rel_updated)
+ macro_rel_updated = true;
+ macro_sec = macro_sec->next;
}
+ }
+ /* Same for the debug_str section. Make sure everything is
+ in place for phase 1 updating of debug_info
+ references. */
+ if (phase == 0 && need_strp_update)
+ {
+ Strtab *strtab = dso->strings.str_tab;
+ Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
+ int strndx = debug_sections[DEBUG_STR].sec;
+ Elf_Scn *strscn = dso->scn[strndx];
+
+ /* Out with the old. */
+ strdata->d_size = 0;
+ /* In with the new. */
+ strdata = elf_newdata (strscn);
+
+ /* We really should check whether we had enough memory,
+ but the old ebl version will just abort on out of
+ memory... */
+ strtab_finalize (strtab, strdata);
+ debug_sections[DEBUG_STR].size = strdata->d_size;
+ dso->strings.str_buf = strdata->d_buf;
}
- /* After phase 1 we might have rewritten the debug_info with
- new strp, strings and/or linep offsets. */
- if (need_strp_update || need_string_replacement || need_stmt_update)
- dirty_section (DEBUG_INFO);
- if (need_strp_update || need_stmt_update)
- dirty_section (DEBUG_MACRO);
- if (need_stmt_update)
- dirty_section (DEBUG_LINE);
+ }
+
+ /* After phase 1 we might have rewritten the debug_info with
+ new strp, strings and/or linep offsets. */
+ if (need_strp_update || need_string_replacement || need_stmt_update)
+ dirty_section (DEBUG_INFO);
+ if (need_strp_update || need_stmt_update)
+ dirty_section (DEBUG_MACRO);
+ if (need_stmt_update)
+ dirty_section (DEBUG_LINE);
- /* Update any relocations addends we might have touched. */
- if (info_rel_updated)
- update_rela_data (dso, &debug_sections[DEBUG_INFO]);
+ /* Update any relocations addends we might have touched. */
+ if (info_rel_updated)
+ update_rela_data (dso, &debug_sections[DEBUG_INFO]);
- if (macro_rel_updated)
+ if (macro_rel_updated)
+ {
+ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
+ while (macro_sec != NULL)
{
- struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
- while (macro_sec != NULL)
- {
- update_rela_data (dso, macro_sec);
- macro_sec = macro_sec->next;
- }
+ update_rela_data (dso, macro_sec);
+ macro_sec = macro_sec->next;
}
}
--
2.18.4

View File

@ -0,0 +1,269 @@
From 8cd4d5046d7cb1bc16f01e77a5ff50eca8d9da3d Mon Sep 17 00:00:00 2001
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Date: Sat, 1 Aug 2020 10:45:47 +0200
Subject: [PATCH 3/6] debugedit: Fix missing relocation of .debug_types
section.
---
tools/debugedit.c | 123 ++++++++++++++++++++++++++++++----------------
1 file changed, 80 insertions(+), 43 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index cad0cc349..87c1cd622 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -433,7 +433,8 @@ typedef struct debug_section
int sec, relsec;
REL *relbuf;
REL *relend;
- struct debug_section *next; /* Only happens for COMDAT .debug_macro. */
+ /* Only happens for COMDAT .debug_macro and .debug_types. */
+ struct debug_section *next;
} debug_section;
static debug_section debug_sections[] =
@@ -1269,7 +1270,9 @@ static int dirty_elf;
static void
dirty_section (unsigned int sec)
{
- elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY);
+ for (struct debug_section *secp = &debug_sections[sec]; secp != NULL;
+ secp = secp->next)
+ elf_flagdata (secp->elf_data, ELF_C_SET, ELF_F_DIRTY);
dirty_elf = 1;
}
@@ -1469,12 +1472,7 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
if (get_line_table (dso, off, &table) == false
|| table == NULL)
- {
- if (table != NULL)
- error (0, 0, ".debug_line offset 0x%x referenced multiple times",
- off);
- return false;
- }
+ return false;
/* Skip to the directory table. The rest of the header has already
been read and checked by get_line_table. */
@@ -1965,22 +1963,25 @@ line_rel_cmp (const void *a, const void *b)
}
static int
-edit_info (DSO *dso, int phase)
+edit_info (DSO *dso, int phase, struct debug_section *sec)
{
unsigned char *ptr, *endcu, *endsec;
uint32_t value;
htab_t abbrev;
struct abbrev_tag tag, *t;
- ptr = debug_sections[DEBUG_INFO].data;
- setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
- endsec = ptr + debug_sections[DEBUG_INFO].size;
+ ptr = sec->data;
+ if (ptr == NULL)
+ return 0;
+
+ setup_relbuf(dso, sec, &reltype);
+ endsec = ptr + sec->size;
while (ptr < endsec)
{
- if (ptr + 11 > endsec)
+ if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec)
{
- error (0, 0, "%s: .debug_info CU header too small",
- dso->filename);
+ error (0, 0, "%s: %s CU header too small",
+ dso->filename, sec->name);
return 1;
}
@@ -1994,7 +1995,7 @@ edit_info (DSO *dso, int phase)
if (endcu > endsec)
{
- error (0, 0, "%s: .debug_info too small", dso->filename);
+ error (0, 0, "%s: %s too small", dso->filename, sec->name);
return 1;
}
@@ -2034,6 +2035,9 @@ edit_info (DSO *dso, int phase)
return 1;
}
+ if (sec != &debug_sections[DEBUG_INFO])
+ ptr += 12; /* Skip type_signature and type_offset. */
+
abbrev = read_abbrev (dso,
debug_sections[DEBUG_ABBREV].data + value);
if (abbrev == NULL)
@@ -2095,7 +2099,7 @@ edit_dwarf2 (DSO *dso)
struct debug_section *debug_sec = &debug_sections[j];
if (debug_sections[j].data)
{
- if (j != DEBUG_MACRO)
+ if (j != DEBUG_MACRO && j != DEBUG_TYPES)
{
error (0, 0, "%s: Found two copies of %s section",
dso->filename, name);
@@ -2103,22 +2107,21 @@ edit_dwarf2 (DSO *dso)
}
else
{
- /* In relocatable files .debug_macro might
- appear multiple times as COMDAT
- section. */
+ /* In relocatable files .debug_macro and .debug_types
+ might appear multiple times as COMDAT section. */
struct debug_section *sec;
sec = calloc (sizeof (struct debug_section), 1);
if (sec == NULL)
error (1, errno,
- "%s: Could not allocate more macro sections",
- dso->filename);
- sec->name = ".debug_macro";
+ "%s: Could not allocate more %s sections",
+ dso->filename, name);
+ sec->name = name;
- struct debug_section *macro_sec = debug_sec;
- while (macro_sec->next != NULL)
- macro_sec = macro_sec->next;
+ struct debug_section *multi_sec = debug_sec;
+ while (multi_sec->next != NULL)
+ multi_sec = multi_sec->next;
- macro_sec->next = sec;
+ multi_sec->next = sec;
debug_sec = sec;
}
}
@@ -2155,23 +2158,23 @@ edit_dwarf2 (DSO *dso)
+ (dso->shdr[i].sh_type == SHT_RELA),
debug_sections[j].name) == 0)
{
- if (j == DEBUG_MACRO)
+ if (j == DEBUG_MACRO || j == DEBUG_TYPES)
{
/* Pick the correct one. */
int rel_target = dso->shdr[i].sh_info;
- struct debug_section *macro_sec = &debug_sections[j];
- while (macro_sec != NULL)
+ struct debug_section *multi_sec = &debug_sections[j];
+ while (multi_sec != NULL)
{
- if (macro_sec->sec == rel_target)
+ if (multi_sec->sec == rel_target)
{
- macro_sec->relsec = i;
+ multi_sec->relsec = i;
break;
}
- macro_sec = macro_sec->next;
+ multi_sec = multi_sec->next;
}
- if (macro_sec == NULL)
- error (0, 1, "No .debug_macro reloc section: %s",
- dso->filename);
+ if (multi_sec == NULL)
+ error (0, 1, "No %s reloc section: %s",
+ debug_sections[j].name, dso->filename);
}
else
debug_sections[j].relsec = i;
@@ -2203,12 +2206,10 @@ edit_dwarf2 (DSO *dso)
if (debug_sections[DEBUG_INFO].data == NULL)
return 0;
- unsigned char *ptr, *endcu, *endsec;
- uint32_t value;
- htab_t abbrev;
- struct abbrev_tag tag, *t;
+ unsigned char *ptr, *endsec;
int phase;
bool info_rel_updated = false;
+ bool types_rel_updated = false;
bool macro_rel_updated = false;
for (phase = 0; phase < 2; phase++)
@@ -2221,13 +2222,26 @@ edit_dwarf2 (DSO *dso)
break;
rel_updated = false;
- if (edit_info (dso, phase))
- return 1;
+ if (edit_info (dso, phase, &debug_sections[DEBUG_INFO]))
+ return 1;
/* Remember whether any .debug_info relocations might need
to be updated. */
info_rel_updated = rel_updated;
+ rel_updated = false;
+ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
+ while (types_sec != NULL)
+ {
+ if (edit_info (dso, phase, types_sec))
+ return 1;
+ types_sec = types_sec->next;
+ }
+
+ /* Remember whether any .debug_types relocations might need
+ to be updated. */
+ types_rel_updated = rel_updated;
+
/* We might have to recalculate/rewrite the debug_line
section. We need to do that before going into phase one
so we have all new offsets. We do this separately from
@@ -2475,8 +2489,11 @@ edit_dwarf2 (DSO *dso)
/* After phase 1 we might have rewritten the debug_info with
new strp, strings and/or linep offsets. */
- if (need_strp_update || need_string_replacement || need_stmt_update)
+ if (need_strp_update || need_string_replacement || need_stmt_update) {
dirty_section (DEBUG_INFO);
+ if (debug_sections[DEBUG_TYPES].data != NULL)
+ dirty_section (DEBUG_TYPES);
+ }
if (need_strp_update || need_stmt_update)
dirty_section (DEBUG_MACRO);
if (need_stmt_update)
@@ -2485,6 +2502,15 @@ edit_dwarf2 (DSO *dso)
/* Update any relocations addends we might have touched. */
if (info_rel_updated)
update_rela_data (dso, &debug_sections[DEBUG_INFO]);
+ if (types_rel_updated)
+ {
+ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
+ while (types_sec != NULL)
+ {
+ update_rela_data (dso, types_sec);
+ types_sec = types_sec->next;
+ }
+ }
if (macro_rel_updated)
{
@@ -3037,6 +3063,17 @@ main (int argc, char *argv[])
macro_sec = next;
}
+ /* In case there were multiple (COMDAT) .debug_types sections,
+ free them. */
+ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
+ types_sec = types_sec->next;
+ while (types_sec != NULL)
+ {
+ struct debug_section *next = types_sec->next;
+ free (types_sec);
+ types_sec = next;
+ }
+
poptFreeContext (optCon);
return 0;
--
2.18.4

View File

@ -0,0 +1,455 @@
From bab443ab4f756ef80f814af0353143f41e90e6a6 Mon Sep 17 00:00:00 2001
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Date: Mon, 17 Aug 2020 21:58:19 +0200
Subject: [PATCH 4/6] [NFC] debugedit: Move code to separate functions.
New functions edit_strp, skip_form and edit_attributes_str_comp_dir
called by edit_attributes.
Split part of read_dwarf2_line into a read_dwarf4_line function.
New function edit_dwarf2_any_str called by edit_dwarf2 at the end of
phase 0 to rebuild .debug_str.
---
tools/debugedit.c | 367 ++++++++++++++++++++++++++--------------------
1 file changed, 212 insertions(+), 155 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index 87c1cd622..7464883c5 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -1457,37 +1457,128 @@ edit_dwarf2_line (DSO *dso)
}
}
-/* Called during phase zero for each debug_line table referenced from
- .debug_info. Outputs all source files seen and records any
- adjustments needed in the debug_list data structures. Returns true
- if line_table needs to be rewrite either the dir or file paths. */
+/* Record or adjust (according to phase) DW_FORM_strp. */
+static void
+edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp)
+{
+ unsigned char *ptr_orig = ptr;
+
+ /* In the first pass we collect all strings, in the
+ second we put the new references back (if there are
+ any changes). */
+ if (phase == 0)
+ {
+ /* handled_strp is set for attributes referring to
+ files. If it is set the string is already
+ recorded. */
+ if (! handled_strp)
+ {
+ size_t idx = do_read_32_relocated (ptr);
+ record_existing_string_entry_idx (&dso->strings, idx);
+ }
+ }
+ else if (need_strp_update) /* && phase == 1 */
+ {
+ struct stridxentry *entry;
+ size_t idx, new_idx;
+ idx = do_read_32_relocated (ptr);
+ entry = string_find_entry (&dso->strings, idx);
+ new_idx = strent_offset (entry->entry);
+ do_write_32_relocated (ptr, new_idx);
+ }
+
+ assert (ptr == ptr_orig);
+}
+
+/* Adjust *PTRP after the current *FORMP, update *FORMP for FORM_INDIRECT. */
+static enum { FORM_OK, FORM_ERROR, FORM_INDIRECT }
+skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
+{
+ size_t len = 0;
+
+ switch (*formp)
+ {
+ case DW_FORM_ref_addr:
+ if (cu_version == 2)
+ *ptrp += ptr_size;
+ else
+ *ptrp += 4;
+ break;
+ case DW_FORM_flag_present:
+ break;
+ case DW_FORM_addr:
+ *ptrp += ptr_size;
+ break;
+ case DW_FORM_ref1:
+ case DW_FORM_flag:
+ case DW_FORM_data1:
+ ++*ptrp;
+ break;
+ case DW_FORM_ref2:
+ case DW_FORM_data2:
+ *ptrp += 2;
+ break;
+ case DW_FORM_ref4:
+ case DW_FORM_data4:
+ case DW_FORM_sec_offset:
+ *ptrp += 4;
+ break;
+ case DW_FORM_ref8:
+ case DW_FORM_data8:
+ case DW_FORM_ref_sig8:
+ *ptrp += 8;
+ break;
+ case DW_FORM_sdata:
+ case DW_FORM_ref_udata:
+ case DW_FORM_udata:
+ read_uleb128 (*ptrp);
+ break;
+ case DW_FORM_strp:
+ *ptrp += 4;
+ break;
+ case DW_FORM_string:
+ *ptrp = (unsigned char *) strchr ((char *)*ptrp, '\0') + 1;
+ break;
+ case DW_FORM_indirect:
+ *formp = read_uleb128 (*ptrp);
+ return FORM_INDIRECT;
+ case DW_FORM_block1:
+ len = *(*ptrp)++;
+ break;
+ case DW_FORM_block2:
+ len = read_16 (*ptrp);
+ *formp = DW_FORM_block1;
+ break;
+ case DW_FORM_block4:
+ len = read_32 (*ptrp);
+ *formp = DW_FORM_block1;
+ break;
+ case DW_FORM_block:
+ case DW_FORM_exprloc:
+ len = read_uleb128 (*ptrp);
+ *formp = DW_FORM_block1;
+ assert (len < UINT_MAX);
+ break;
+ default:
+ error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, *formp);
+ return FORM_ERROR;
+ }
+
+ if (*formp == DW_FORM_block1)
+ *ptrp += len;
+
+ return FORM_OK;
+}
+
+/* Part of read_dwarf2_line processing DWARF-4. */
static bool
-read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
+read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
+ struct line_table *table)
{
- unsigned char *ptr, *dir;
unsigned char **dirt;
uint32_t value, dirt_cnt;
size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir);
- struct line_table *table;
-
- if (get_line_table (dso, off, &table) == false
- || table == NULL)
- return false;
-
- /* Skip to the directory table. The rest of the header has already
- been read and checked by get_line_table. */
- ptr = debug_sections[DEBUG_LINE].data + off;
- ptr += (4 /* unit len */
- + 2 /* version */
- + 4 /* header len */
- + 1 /* min instr len */
- + (table->version >= 4) /* max op per instr, if version >= 4 */
- + 1 /* default is stmt */
- + 1 /* line base */
- + 1 /* line range */
- + 1 /* opcode base */
- + table->opcode_base - 1); /* opcode len table */
- dir = ptr;
+ unsigned char *dir = ptr;
/* dir table: */
value = 1;
@@ -1620,6 +1711,40 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
read_uleb128 (ptr);
}
+ return true;
+}
+
+/* Called during phase zero for each debug_line table referenced from
+ .debug_info. Outputs all source files seen and records any
+ adjustments needed in the debug_list data structures. Returns true
+ if line_table needs to be rewrite either the dir or file paths. */
+static bool
+read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
+{
+ unsigned char *ptr;
+ struct line_table *table;
+
+ if (get_line_table (dso, off, &table) == false
+ || table == NULL)
+ return false;
+
+ /* Skip to the directory table. The rest of the header has already
+ been read and checked by get_line_table. */
+ ptr = debug_sections[DEBUG_LINE].data + off;
+ ptr += (4 /* unit len */
+ + 2 /* version */
+ + 4 /* header len */
+ + 1 /* min instr len */
+ + (table->version >= 4) /* max op per instr, if version >= 4 */
+ + 1 /* default is stmt */
+ + 1 /* line base */
+ + 1 /* line range */
+ + 1 /* opcode base */
+ + table->opcode_base - 1); /* opcode len table */
+
+ if (! read_dwarf4_line (dso, ptr, comp_dir, table))
+ return false;
+
dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff;
return table->replace_dirs || table->replace_files;
}
@@ -1637,6 +1762,33 @@ find_new_list_offs (struct debug_lines *lines, size_t idx)
return table->new_idx;
}
+/* Read DW_FORM_strp collecting compilation directory. */
+static void
+edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase,
+ char **comp_dirp, bool *handled_strpp)
+{
+ const char *dir;
+ size_t idx = do_read_32_relocated (*ptrp);
+ /* In phase zero we collect the comp_dir. */
+ if (phase == 0)
+ {
+ if (idx >= debug_sections[DEBUG_STR].size)
+ error (1, 0, "%s: Bad string pointer index %zd for comp_dir",
+ dso->filename, idx);
+ dir = (char *) debug_sections[DEBUG_STR].data + idx;
+
+ free (*comp_dirp);
+ *comp_dirp = strdup (dir);
+ }
+
+ if (dest_dir != NULL && phase == 0)
+ {
+ if (record_file_string_entry_idx (&dso->strings, idx))
+ need_strp_update = true;
+ *handled_strpp = true;
+ }
+}
+
/* This scans the attributes of one DIE described by the given abbrev_tag.
PTR points to the data in the debug_info. It will be advanced till all
abbrev data is consumed. In phase zero data is collected, in phase one
@@ -1655,7 +1807,6 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
for (i = 0; i < t->nattr; ++i)
{
uint32_t form = t->attr[i].form;
- size_t len = 0;
while (1)
{
/* Whether we already handled a string as file for this
@@ -1743,29 +1894,8 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
}
else if (form == DW_FORM_strp &&
debug_sections[DEBUG_STR].data)
- {
- const char *dir;
- size_t idx = do_read_32_relocated (ptr);
- /* In phase zero we collect the comp_dir. */
- if (phase == 0)
- {
- if (idx >= debug_sections[DEBUG_STR].size)
- error (1, 0,
- "%s: Bad string pointer index %zd for comp_dir",
- dso->filename, idx);
- dir = (char *) debug_sections[DEBUG_STR].data + idx;
-
- free (comp_dir);
- comp_dir = strdup (dir);
- }
-
- if (dest_dir != NULL && phase == 0)
- {
- if (record_file_string_entry_idx (&dso->strings, idx))
- need_strp_update = true;
- handled_strp = true;
- }
- }
+ edit_attributes_str_comp_dir (dso, &ptr, phase, &comp_dir,
+ &handled_strp);
}
else if ((t->tag == DW_TAG_compile_unit
|| t->tag == DW_TAG_partial_unit)
@@ -1815,99 +1945,21 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
switch (form)
{
- case DW_FORM_ref_addr:
- if (cu_version == 2)
- ptr += ptr_size;
- else
- ptr += 4;
- break;
- case DW_FORM_flag_present:
- break;
- case DW_FORM_addr:
- ptr += ptr_size;
- break;
- case DW_FORM_ref1:
- case DW_FORM_flag:
- case DW_FORM_data1:
- ++ptr;
- break;
- case DW_FORM_ref2:
- case DW_FORM_data2:
- ptr += 2;
- break;
- case DW_FORM_ref4:
- case DW_FORM_data4:
- case DW_FORM_sec_offset:
- ptr += 4;
- break;
- case DW_FORM_ref8:
- case DW_FORM_data8:
- case DW_FORM_ref_sig8:
- ptr += 8;
- break;
- case DW_FORM_sdata:
- case DW_FORM_ref_udata:
- case DW_FORM_udata:
- read_uleb128 (ptr);
- break;
case DW_FORM_strp:
- /* In the first pass we collect all strings, in the
- second we put the new references back (if there are
- any changes). */
- if (phase == 0)
- {
- /* handled_strp is set for attributes referring to
- files. If it is set the string is already
- recorded. */
- if (! handled_strp)
- {
- size_t idx = do_read_32_relocated (ptr);
- record_existing_string_entry_idx (&dso->strings, idx);
- }
- }
- else if (need_strp_update) /* && phase == 1 */
- {
- struct stridxentry *entry;
- size_t idx, new_idx;
- idx = do_read_32_relocated (ptr);
- entry = string_find_entry (&dso->strings, idx);
- new_idx = strent_offset (entry->entry);
- do_write_32_relocated (ptr, new_idx);
- }
- ptr += 4;
- break;
- case DW_FORM_string:
- ptr = (unsigned char *) strchr ((char *)ptr, '\0') + 1;
- break;
- case DW_FORM_indirect:
- form = read_uleb128 (ptr);
- continue;
- case DW_FORM_block1:
- len = *ptr++;
- break;
- case DW_FORM_block2:
- len = read_16 (ptr);
- form = DW_FORM_block1;
+ edit_strp (dso, ptr, phase, handled_strp);
break;
- case DW_FORM_block4:
- len = read_32 (ptr);
- form = DW_FORM_block1;
- break;
- case DW_FORM_block:
- case DW_FORM_exprloc:
- len = read_uleb128 (ptr);
- form = DW_FORM_block1;
- assert (len < UINT_MAX);
+ }
+
+ switch (skip_form (dso, &form, &ptr))
+ {
+ case FORM_OK:
break;
- default:
- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename,
- form);
+ case FORM_ERROR:
return NULL;
+ case FORM_INDIRECT:
+ continue;
}
- if (form == DW_FORM_block1)
- ptr += len;
-
break;
}
}
@@ -2068,6 +2120,28 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
return 0;
}
+/* Rebuild .debug_str. */
+static void
+edit_dwarf2_any_str (DSO *dso)
+{
+ Strtab *strtab = dso->strings.str_tab;
+ Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
+ int strndx = debug_sections[DEBUG_STR].sec;
+ Elf_Scn *strscn = dso->scn[strndx];
+
+ /* Out with the old. */
+ strdata->d_size = 0;
+ /* In with the new. */
+ strdata = elf_newdata (strscn);
+
+ /* We really should check whether we had enough memory,
+ but the old ebl version will just abort on out of
+ memory... */
+ strtab_finalize (strtab, strdata);
+ debug_sections[DEBUG_STR].size = strdata->d_size;
+ dso->strings.str_buf = strdata->d_buf;
+}
+
static int
edit_dwarf2 (DSO *dso)
{
@@ -2466,24 +2540,7 @@ edit_dwarf2 (DSO *dso)
in place for phase 1 updating of debug_info
references. */
if (phase == 0 && need_strp_update)
- {
- Strtab *strtab = dso->strings.str_tab;
- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
- int strndx = debug_sections[DEBUG_STR].sec;
- Elf_Scn *strscn = dso->scn[strndx];
-
- /* Out with the old. */
- strdata->d_size = 0;
- /* In with the new. */
- strdata = elf_newdata (strscn);
-
- /* We really should check whether we had enough memory,
- but the old ebl version will just abort on out of
- memory... */
- strtab_finalize (strtab, strdata);
- debug_sections[DEBUG_STR].size = strdata->d_size;
- dso->strings.str_buf = strdata->d_buf;
- }
+ edit_dwarf2_any_str (dso);
}
--
2.18.4

View File

@ -0,0 +1,217 @@
From 8b5dcb4c2175ac706a4e1c34ce83301213800689 Mon Sep 17 00:00:00 2001
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Date: Mon, 18 Jan 2021 22:56:53 +0100
Subject: [PATCH 5/6] debugedit: Implement DWARF-5 unit header and new forms
parsing.
Recognize the various new DWARF5 .debug sections.
Parse and skip new DWARF5 forms in read_abbrev and skip_form.
Read DWARF5 unit headers for compile and partial units in edit_info.
This is enough to be able to process gcc -gdwarf-5 produced binaries
without the new DWARF5 .debug_line format (which isn't produced with
binutils < 2.36).
Patches slightly edited/merged by Mark Wielaard <mark@klomp.org>
---
tools/debugedit.c | 88 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 81 insertions(+), 7 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index 7464883c5..be5fee85b 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -453,6 +453,11 @@ static debug_section debug_sections[] =
#define DEBUG_TYPES 11
#define DEBUG_MACRO 12
#define DEBUG_GDB_SCRIPT 13
+#define DEBUG_RNGLISTS 14
+#define DEBUG_LINE_STR 15
+#define DEBUG_ADDR 16
+#define DEBUG_STR_OFFSETS 17
+#define DEBUG_LOCLISTS 18
{ ".debug_info", NULL, NULL, 0, 0, 0 },
{ ".debug_abbrev", NULL, NULL, 0, 0, 0 },
{ ".debug_line", NULL, NULL, 0, 0, 0 },
@@ -467,6 +472,11 @@ static debug_section debug_sections[] =
{ ".debug_types", NULL, NULL, 0, 0, 0 },
{ ".debug_macro", NULL, NULL, 0, 0, 0 },
{ ".debug_gdb_scripts", NULL, NULL, 0, 0, 0 },
+ { ".debug_rnglists", NULL, NULL, 0, 0, 0 },
+ { ".debug_line_str", NULL, NULL, 0, 0, 0 },
+ { ".debug_addr", NULL, NULL, 0, 0, 0 },
+ { ".debug_str_offsets", NULL, NULL, 0, 0, 0 },
+ { ".debug_loclists", NULL, NULL, 0, 0, 0 },
{ NULL, NULL, NULL, 0, 0, 0 }
};
@@ -755,12 +765,28 @@ no_memory:
}
form = read_uleb128 (ptr);
if (form == 2
- || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8))
+ || (form > DW_FORM_flag_present
+ && !(form == DW_FORM_ref_sig8
+ || form == DW_FORM_data16
+ || form == DW_FORM_implicit_const
+ || form == DW_FORM_addrx
+ || form == DW_FORM_loclistx
+ || form == DW_FORM_rnglistx
+ || form == DW_FORM_addrx1
+ || form == DW_FORM_addrx2
+ || form == DW_FORM_addrx3
+ || form == DW_FORM_addrx4)))
{
- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form);
+ error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename,
+ form);
htab_delete (h);
return NULL;
}
+ if (form == DW_FORM_implicit_const)
+ {
+ /* It is SLEB128 but the value is dropped anyway. */
+ read_uleb128 (ptr);
+ }
t->attr[t->nattr].attr = attr;
t->attr[t->nattr++].form = form;
@@ -1505,6 +1531,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
*ptrp += 4;
break;
case DW_FORM_flag_present:
+ case DW_FORM_implicit_const:
break;
case DW_FORM_addr:
*ptrp += ptr_size;
@@ -1512,14 +1539,24 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
case DW_FORM_ref1:
case DW_FORM_flag:
case DW_FORM_data1:
+ case DW_FORM_strx1:
+ case DW_FORM_addrx1:
++*ptrp;
break;
case DW_FORM_ref2:
case DW_FORM_data2:
+ case DW_FORM_strx2:
+ case DW_FORM_addrx2:
*ptrp += 2;
break;
+ case DW_FORM_strx3:
+ case DW_FORM_addrx3:
+ *ptrp += 3;
+ break;
case DW_FORM_ref4:
case DW_FORM_data4:
+ case DW_FORM_strx4:
+ case DW_FORM_addrx4:
case DW_FORM_sec_offset:
*ptrp += 4;
break;
@@ -1528,12 +1565,20 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
case DW_FORM_ref_sig8:
*ptrp += 8;
break;
+ case DW_FORM_data16:
+ *ptrp += 16;
+ break;
case DW_FORM_sdata:
case DW_FORM_ref_udata:
case DW_FORM_udata:
+ case DW_FORM_strx:
+ case DW_FORM_loclistx:
+ case DW_FORM_rnglistx:
+ case DW_FORM_addrx:
read_uleb128 (*ptrp);
break;
case DW_FORM_strp:
+ case DW_FORM_line_strp:
*ptrp += 4;
break;
case DW_FORM_string:
@@ -1560,7 +1605,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
assert (len < UINT_MAX);
break;
default:
- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, *formp);
+ error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename, *formp);
return FORM_ERROR;
}
@@ -2030,7 +2075,10 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
endsec = ptr + sec->size;
while (ptr < endsec)
{
- if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec)
+ unsigned char *cu_start = ptr;
+
+ /* header size, version, unit_type, ptr_size. */
+ if (ptr + 4 + 2 + 1 + 1 > endsec)
{
error (0, 0, "%s: %s CU header too small",
dso->filename, sec->name);
@@ -2052,13 +2100,36 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
}
cu_version = read_16 (ptr);
- if (cu_version != 2 && cu_version != 3 && cu_version != 4)
+ if (cu_version != 2 && cu_version != 3 && cu_version != 4
+ && cu_version != 5)
{
error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
cu_version);
return 1;
}
+ int cu_ptr_size = 0;
+
+ if (cu_version >= 5)
+ {
+ uint8_t unit_type = read_8 (ptr);
+ if (unit_type != DW_UT_compile && unit_type != DW_UT_partial)
+ {
+ error (0, 0, "%s: Unit type %u unhandled", dso->filename,
+ unit_type);
+ return 1;
+ }
+
+ cu_ptr_size = read_8 (ptr);
+ }
+
+ unsigned char *header_end = (cu_start + 23 + (cu_version < 5 ? 0 : 1));
+ if (header_end > endsec)
+ {
+ error (0, 0, "%s: %s CU header too small", dso->filename, sec->name);
+ return 1;
+ }
+
value = read_32_relocated (ptr);
if (value >= debug_sections[DEBUG_ABBREV].size)
{
@@ -2070,9 +2141,12 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
return 1;
}
+ if (cu_version < 5)
+ cu_ptr_size = read_8 (ptr);
+
if (ptr_size == 0)
{
- ptr_size = read_8 (ptr);
+ ptr_size = cu_ptr_size;
if (ptr_size != 4 && ptr_size != 8)
{
error (0, 0, "%s: Invalid DWARF pointer size %d",
@@ -2080,7 +2154,7 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
return 1;
}
}
- else if (read_8 (ptr) != ptr_size)
+ else if (cu_ptr_size != ptr_size)
{
error (0, 0, "%s: DWARF pointer size differs between CUs",
dso->filename);
--
2.18.4

View File

@ -0,0 +1,772 @@
From d9947f2dc0c2cd812f8e64380d5f6f53705a5280 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
Date: Tue, 19 Jan 2021 04:12:33 +0100
Subject: [PATCH 6/6] debugedit: Handle DWARF-5 debug_line and debug_line_str.
Handle the new DWARF5 .debug_line tables and the new DW_FORM_line_strp.
DWARF5 tables are handled separately from the earlier tables. They
will never change size, but they do need updates to the .debug_str
or .debug_line_str references.
Based on a patch from Jan Kratochvil <jan.kratochvil@redhat.com>
---
tools/debugedit.c | 471 ++++++++++++++++++++++++++++++++++++++++------
1 file changed, 410 insertions(+), 61 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index be5fee85b..d6a0058e9 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -103,6 +103,8 @@ static bool need_string_replacement = false;
/* Whether we need to do any updates of the string indexes (DW_FORM_strp)
in debug_info for string indexes. */
static bool need_strp_update = false;
+/* Likewise for DW_FORM_line_strp. */
+static bool need_line_strp_update = false;
/* If the debug_line changes size we will need to update the
DW_AT_stmt_list attributes indexes in the debug_info. */
static bool need_stmt_update = false;
@@ -192,7 +194,7 @@ typedef struct
const char *filename;
int lastscn;
size_t phnum;
- struct strings strings;
+ struct strings debug_str, debug_line_str;
struct debug_lines lines;
GElf_Shdr shdr[0];
} DSO;
@@ -553,10 +555,11 @@ setup_relbuf (DSO *dso, debug_section *sec, int *reltype)
/* Relocations against section symbols are uninteresting in REL. */
if (dso->shdr[i].sh_type == SHT_REL && sym.st_value == 0)
continue;
- /* Only consider relocations against .debug_str, .debug_line
- and .debug_abbrev. */
+ /* Only consider relocations against .debug_str, .debug_line,
+ .debug_line_str, and .debug_abbrev. */
if (sym.st_shndx != debug_sections[DEBUG_STR].sec
&& sym.st_shndx != debug_sections[DEBUG_LINE].sec
+ && sym.st_shndx != debug_sections[DEBUG_LINE_STR].sec
&& sym.st_shndx != debug_sections[DEBUG_ABBREV].sec)
continue;
rela.r_addend += sym.st_value;
@@ -768,6 +771,7 @@ no_memory:
|| (form > DW_FORM_flag_present
&& !(form == DW_FORM_ref_sig8
|| form == DW_FORM_data16
+ || form == DW_FORM_line_strp
|| form == DW_FORM_implicit_const
|| form == DW_FORM_addrx
|| form == DW_FORM_loclistx
@@ -1049,17 +1053,20 @@ string_find_entry (struct strings *strings, size_t old_idx)
a replacement file string has been recorded for it, otherwise
returns false. */
static bool
-record_file_string_entry_idx (struct strings *strings, size_t old_idx)
+record_file_string_entry_idx (bool line_strp, DSO *dso, size_t old_idx)
{
+ struct strings *strings = line_strp ? &dso->debug_line_str : &dso->debug_str;
bool ret = false;
struct stridxentry *entry = string_find_new_entry (strings, old_idx);
if (entry != NULL)
{
- if (old_idx >= debug_sections[DEBUG_STR].size)
- error (1, 0, "Bad string pointer index %zd", old_idx);
+ debug_section *sec = &debug_sections[line_strp
+ ? DEBUG_LINE_STR : DEBUG_STR];
+ if (old_idx >= sec->size)
+ error (1, 0, "Bad string pointer index %zd (%s)", old_idx, sec->name);
Strent *strent;
- const char *old_str = (char *)debug_sections[DEBUG_STR].data + old_idx;
+ const char *old_str = (char *)sec->data + old_idx;
const char *file = skip_dir_prefix (old_str, base_dir);
if (file == NULL)
{
@@ -1103,15 +1110,18 @@ record_file_string_entry_idx (struct strings *strings, size_t old_idx)
base_dir with dest_dir, just records the existing string associated
with the index. */
static void
-record_existing_string_entry_idx (struct strings *strings, size_t old_idx)
+record_existing_string_entry_idx (bool line_strp, DSO *dso, size_t old_idx)
{
+ struct strings *strings = line_strp ? &dso->debug_line_str : &dso->debug_str;
struct stridxentry *entry = string_find_new_entry (strings, old_idx);
if (entry != NULL)
{
- if (old_idx >= debug_sections[DEBUG_STR].size)
- error (1, 0, "Bad string pointer index %zd", old_idx);
+ debug_section *sec = &debug_sections[line_strp
+ ? DEBUG_LINE_STR : DEBUG_STR];
+ if (old_idx >= sec->size)
+ error (1, 0, "Bad string pointer index %zd (%s)", old_idx, sec->name);
- const char *str = (char *)debug_sections[DEBUG_STR].data + old_idx;
+ const char *str = (char *)sec->data + old_idx;
Strent *strent = strtab_add_len (strings->str_tab,
str, strlen (str) + 1);
if (strent == NULL)
@@ -1244,13 +1254,28 @@ get_line_table (DSO *dso, size_t off, struct line_table **table)
/* version */
t->version = read_16 (ptr);
- if (t->version != 2 && t->version != 3 && t->version != 4)
+ if (t->version != 2 && t->version != 3 && t->version != 4 && t->version != 5)
{
error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
t->version);
return false;
}
+ if (t->version >= 5)
+ {
+ /* address_size */
+ assert (ptr_size != 0);
+ if (ptr_size != read_8 (ptr))
+ {
+ error (0, 0, "%s: .debug_line address size differs from .debug_info",
+ dso->filename);
+ return false;
+ }
+
+ /* segment_selector_size */
+ (void) read_8 (ptr);
+ }
+
/* header_length */
unsigned char *endprol = ptr + 4;
t->header_length = read_32 (ptr);
@@ -1343,7 +1368,9 @@ edit_dwarf2_line (DSO *dso)
linedata->d_size = dso->lines.debug_lines_len;
linedata->d_buf = dso->lines.line_buf;
+ debug_sections[DEBUG_LINE].data = linedata->d_buf;
debug_sections[DEBUG_LINE].size = linedata->d_size;
+ debug_sections[DEBUG_LINE].elf_data = linedata;
/* Make sure the line tables are sorted on the old index. */
qsort (dso->lines.table, dso->lines.used, sizeof (struct line_table),
@@ -1483,9 +1510,10 @@ edit_dwarf2_line (DSO *dso)
}
}
-/* Record or adjust (according to phase) DW_FORM_strp. */
+/* Record or adjust (according to phase) DW_FORM_strp or DW_FORM_line_strp. */
static void
-edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp)
+edit_strp (DSO *dso, bool line_strp, unsigned char *ptr, int phase,
+ bool handled_strp)
{
unsigned char *ptr_orig = ptr;
@@ -1500,15 +1528,18 @@ edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp)
if (! handled_strp)
{
size_t idx = do_read_32_relocated (ptr);
- record_existing_string_entry_idx (&dso->strings, idx);
+ record_existing_string_entry_idx (line_strp, dso, idx);
}
}
- else if (need_strp_update) /* && phase == 1 */
+ else if (line_strp
+ ? need_line_strp_update : need_strp_update) /* && phase == 1 */
{
struct stridxentry *entry;
size_t idx, new_idx;
+ struct strings *strings = (line_strp
+ ? &dso->debug_line_str : &dso->debug_str);
idx = do_read_32_relocated (ptr);
- entry = string_find_entry (&dso->strings, idx);
+ entry = string_find_entry (strings, idx);
new_idx = strent_offset (entry->entry);
do_write_32_relocated (ptr, new_idx);
}
@@ -1759,6 +1790,254 @@ read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
return true;
}
+/* Called by read_dwarf5_line first for directories and then file
+ names as they both have the same format. */
+static bool
+read_dwarf5_line_entries (DSO *dso, unsigned char **ptrp,
+ struct line_table *table, int phase,
+ char ***dirs, int *ndir,
+ const char *entry_name)
+{
+ /* directory_entry_format_count */
+ /* file_name_entry_format_count */
+ unsigned format_count = read_8 (*ptrp);
+
+ unsigned char *formats = *ptrp;
+
+ /* directory_entry_format */
+ /* file_name_entry_format */
+ for (unsigned formati = 0; formati < format_count; ++formati)
+ {
+ read_uleb128 (*ptrp);
+ read_uleb128 (*ptrp);
+ }
+
+ /* directories_count */
+ /* file_names_count */
+ unsigned entry_count = read_uleb128 (*ptrp);
+
+ bool collecting_dirs = dest_dir && phase == 0 && *dirs == NULL;
+ bool writing_files = dest_dir && phase == 0 && *dirs != NULL;
+ if (collecting_dirs)
+ {
+ *ndir = entry_count;
+ *dirs = malloc (entry_count * sizeof (char *));
+ if (*dirs == NULL)
+ error (1, errno, "%s: Could not allocate debug_line dirs",
+ dso->filename);
+ }
+
+ /* directories */
+ /* file_names */
+ for (unsigned entryi = 0; entryi < entry_count; ++entryi)
+ {
+ char *dir = NULL;
+ char *file = NULL;;
+ unsigned char *format_ptr = formats;
+ for (unsigned formati = 0; formati < format_count; ++formati)
+ {
+ unsigned lnct = read_uleb128 (format_ptr);
+ unsigned form = read_uleb128 (format_ptr);
+ bool handled_form = false;
+ bool handled_strp = false;
+ bool line_strp = form == DW_FORM_line_strp;
+ if (lnct == DW_LNCT_path)
+ {
+ switch (form)
+ {
+ case DW_FORM_strp:
+ case DW_FORM_line_strp:
+ if (dest_dir && phase == 0)
+ {
+ size_t idx = do_read_32_relocated (*ptrp);
+ if (record_file_string_entry_idx (line_strp, dso, idx))
+ {
+ if (line_strp)
+ need_line_strp_update = true;
+ else
+ need_strp_update = true;
+ }
+ handled_strp = true;
+ if (collecting_dirs || writing_files)
+ {
+ debug_section *sec = &debug_sections[line_strp
+ ? DEBUG_LINE_STR : DEBUG_STR];
+ if (collecting_dirs)
+ dir = (char *)sec->data + idx;
+ if (writing_files)
+ file = (char *)sec->data + idx;
+ }
+ }
+ break;
+ default:
+ error (0, 0, "%s: Unsupported "
+ ".debug_line %s %u path DW_FORM_0x%x",
+ dso->filename, entry_name, entryi, form);
+ return false;
+ }
+ }
+ if (writing_files && lnct == DW_LNCT_directory_index)
+ {
+ int dirndx;
+ switch (form)
+ {
+ case DW_FORM_udata:
+ handled_form = true;
+ dirndx = read_uleb128 (*ptrp);
+ break;
+ case DW_FORM_data1:
+ dirndx = **ptrp;
+ break;
+ case DW_FORM_data2:
+ dirndx = do_read_16 (*ptrp);
+ break;
+ case DW_FORM_data4:
+ dirndx = do_read_32 (*ptrp);
+ break;
+ default:
+ error (0, 0, "%s: Unsupported "
+ ".debug_line %s %u dirndx DW_FORM_0x%x",
+ dso->filename, entry_name, entryi, form);
+ return false;
+ }
+
+ if (dirndx > *ndir)
+ {
+ error (0, 0, "%s: Bad dir number %u in .debug_line %s",
+ dso->filename, entryi, entry_name);
+ return false;
+ }
+ dir = (*dirs)[dirndx];
+ }
+
+ switch (form)
+ {
+ case DW_FORM_strp:
+ case DW_FORM_line_strp:
+ edit_strp (dso, line_strp, *ptrp, phase, handled_strp);
+ break;
+ }
+
+ if (!handled_form)
+ {
+ switch (skip_form (dso, &form, ptrp))
+ {
+ case FORM_OK:
+ break;
+ case FORM_ERROR:
+ return false;
+ case FORM_INDIRECT:
+ error (0, 0, "%s: Unsupported "
+ ".debug_line %s %u DW_FORM_indirect",
+ dso->filename, entry_name, entryi);
+ return false;
+ }
+ }
+ }
+
+ if (collecting_dirs)
+ (*dirs)[entryi] = dir;
+
+ if (writing_files)
+ {
+ char *comp_dir = (*dirs)[0];
+ size_t comp_dir_len = strlen(comp_dir);
+ size_t file_len = strlen (file);
+ size_t dir_len = strlen (dir);
+
+ char *s = malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1);
+ if (s == NULL)
+ {
+ error (0, ENOMEM, "%s: Reading file table", dso->filename);
+ return false;
+ }
+ if (file[0] == '/')
+ {
+ memcpy (s, file, file_len + 1);
+ }
+ else if (dir[0] == '/')
+ {
+ memcpy (s, dir, dir_len);
+ s[dir_len] = '/';
+ memcpy (s + dir_len + 1, file, file_len + 1);
+ }
+ else
+ {
+ char *p = s;
+ if (comp_dir_len != 0)
+ {
+ memcpy (s, comp_dir, comp_dir_len);
+ s[comp_dir_len] = '/';
+ p += comp_dir_len + 1;
+ }
+ memcpy (p, dir, dir_len);
+ p[dir_len] = '/';
+ memcpy (p + dir_len + 1, file, file_len + 1);
+ }
+ canonicalize_path (s, s);
+ if (list_file_fd != -1)
+ {
+ const char *p = NULL;
+ if (base_dir == NULL)
+ p = s;
+ else
+ {
+ p = skip_dir_prefix (s, base_dir);
+ if (p == NULL && dest_dir != NULL)
+ p = skip_dir_prefix (s, dest_dir);
+ }
+
+ if (p)
+ {
+ size_t size = strlen (p) + 1;
+ while (size > 0)
+ {
+ ssize_t ret = write (list_file_fd, p, size);
+ if (ret == -1)
+ break;
+ size -= ret;
+ p += ret;
+ }
+ }
+ }
+
+ free (s);
+ }
+ }
+
+ return true;
+}
+
+/* Part of read_dwarf2_line processing DWARF-5. */
+static bool
+read_dwarf5_line (DSO *dso, unsigned char *ptr, struct line_table *table,
+ int phase)
+{
+ char **dirs = NULL;
+ int ndir;
+ /* Skip header. */
+ ptr += (4 /* unit len */
+ + 2 /* version */
+ + (table->version < 5 ? 0 : 0
+ + 1 /* address_size */
+ + 1 /* segment_selector*/)
+ + 4 /* header len */
+ + 1 /* min instr len */
+ + (table->version >= 4) /* max op per instr, if version >= 4 */
+ + 1 /* default is stmt */
+ + 1 /* line base */
+ + 1 /* line range */
+ + 1 /* opcode base */
+ + table->opcode_base - 1); /* opcode len table */
+
+ bool retval = (read_dwarf5_line_entries (dso, &ptr, table, phase,
+ &dirs, &ndir, "directory")
+ && read_dwarf5_line_entries (dso, &ptr, table, phase,
+ &dirs, &ndir, "file name"));
+ free (dirs);
+ return retval;
+}
+
/* Called during phase zero for each debug_line table referenced from
.debug_info. Outputs all source files seen and records any
adjustments needed in the debug_list data structures. Returns true
@@ -1778,6 +2057,9 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
ptr = debug_sections[DEBUG_LINE].data + off;
ptr += (4 /* unit len */
+ 2 /* version */
+ + (table->version < 5 ? 0 : 0
+ + 1 /* address_size */
+ + 1 /* segment_selector*/)
+ 4 /* header len */
+ 1 /* min instr len */
+ (table->version >= 4) /* max op per instr, if version >= 4 */
@@ -1787,8 +2069,13 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
+ 1 /* opcode base */
+ table->opcode_base - 1); /* opcode len table */
- if (! read_dwarf4_line (dso, ptr, comp_dir, table))
- return false;
+ /* DWARF version 5 line tables won't change size. But they might need
+ [line]strp recording/updates. Handle that part later. */
+ if (table->version < 5)
+ {
+ if (! read_dwarf4_line (dso, ptr, comp_dir, table))
+ return false;
+ }
dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff;
return table->replace_dirs || table->replace_files;
@@ -1807,20 +2094,22 @@ find_new_list_offs (struct debug_lines *lines, size_t idx)
return table->new_idx;
}
-/* Read DW_FORM_strp collecting compilation directory. */
+/* Read DW_FORM_strp or DW_FORM_line_strp collecting compilation directory. */
static void
-edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase,
- char **comp_dirp, bool *handled_strpp)
+edit_attributes_str_comp_dir (bool line_strp, DSO *dso, unsigned char **ptrp,
+ int phase, char **comp_dirp, bool *handled_strpp)
{
const char *dir;
size_t idx = do_read_32_relocated (*ptrp);
/* In phase zero we collect the comp_dir. */
if (phase == 0)
{
- if (idx >= debug_sections[DEBUG_STR].size)
- error (1, 0, "%s: Bad string pointer index %zd for comp_dir",
- dso->filename, idx);
- dir = (char *) debug_sections[DEBUG_STR].data + idx;
+ debug_section *sec = &debug_sections[line_strp
+ ? DEBUG_LINE_STR : DEBUG_STR];
+ if (sec->data == NULL || idx >= sec->size)
+ error (1, 0, "%s: Bad string pointer index %zd for comp_dir (%s)",
+ dso->filename, idx, sec->name);
+ dir = (char *) sec->data + idx;
free (*comp_dirp);
*comp_dirp = strdup (dir);
@@ -1828,8 +2117,13 @@ edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase,
if (dest_dir != NULL && phase == 0)
{
- if (record_file_string_entry_idx (&dso->strings, idx))
- need_strp_update = true;
+ if (record_file_string_entry_idx (line_strp, dso, idx))
+ {
+ if (line_strp)
+ need_line_strp_update = true;
+ else
+ need_strp_update = true;
+ }
*handled_strpp = true;
}
}
@@ -1937,17 +2231,24 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
}
}
}
- else if (form == DW_FORM_strp &&
- debug_sections[DEBUG_STR].data)
- edit_attributes_str_comp_dir (dso, &ptr, phase, &comp_dir,
+ else if (form == DW_FORM_strp)
+ edit_attributes_str_comp_dir (false /* line_strp */, dso,
+ &ptr, phase, &comp_dir,
&handled_strp);
+ else if (form == DW_FORM_line_strp)
+ edit_attributes_str_comp_dir (true /* line_strp */, dso, &ptr,
+ phase, &comp_dir, &handled_strp);
}
else if ((t->tag == DW_TAG_compile_unit
|| t->tag == DW_TAG_partial_unit)
- && t->attr[i].attr == DW_AT_name
- && form == DW_FORM_strp
- && debug_sections[DEBUG_STR].data)
+ && ((form == DW_FORM_strp
+ && debug_sections[DEBUG_STR].data)
+ || (form == DW_FORM_line_strp
+ && debug_sections[DEBUG_LINE_STR].data))
+ && t->attr[i].attr == DW_AT_name)
{
+ bool line_strp = form == DW_FORM_line_strp;
+
/* DW_AT_name is the primary file for this compile
unit. If starting with / it is a full path name.
Note that we don't handle DW_FORM_string in this
@@ -1957,11 +2258,14 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
/* In phase zero we will look for a comp_dir to use. */
if (phase == 0)
{
- if (idx >= debug_sections[DEBUG_STR].size)
+ debug_section *sec = &debug_sections[line_strp
+ ? DEBUG_LINE_STR
+ : DEBUG_STR];
+ if (idx >= sec->size)
error (1, 0,
- "%s: Bad string pointer index %zd for unit name",
- dso->filename, idx);
- char *name = (char *) debug_sections[DEBUG_STR].data + idx;
+ "%s: Bad string pointer index %zd for unit name (%s)",
+ dso->filename, idx, sec->name);
+ char *name = (char *) sec->data + idx;
if (*name == '/' && comp_dir == NULL)
{
char *enddir = strrchr (name, '/');
@@ -1982,8 +2286,13 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
pass (1) stores it (the new index). */
if (dest_dir && phase == 0)
{
- if (record_file_string_entry_idx (&dso->strings, idx))
- need_strp_update = true;
+ if (record_file_string_entry_idx (line_strp, dso, idx))
+ {
+ if (line_strp)
+ need_line_strp_update = true;
+ else
+ need_strp_update = true;
+ }
handled_strp = true;
}
}
@@ -1991,7 +2300,10 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
switch (form)
{
case DW_FORM_strp:
- edit_strp (dso, ptr, phase, handled_strp);
+ edit_strp (dso, false /* line_strp */, ptr, phase, handled_strp);
+ break;
+ case DW_FORM_line_strp:
+ edit_strp (dso, true /* line_strp */, ptr, phase, handled_strp);
break;
}
@@ -2196,11 +2508,11 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
/* Rebuild .debug_str. */
static void
-edit_dwarf2_any_str (DSO *dso)
+edit_dwarf2_any_str (DSO *dso, struct strings *strings, debug_section *secp)
{
- Strtab *strtab = dso->strings.str_tab;
- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
- int strndx = debug_sections[DEBUG_STR].sec;
+ Strtab *strtab = strings->str_tab;
+ Elf_Data *strdata = secp->elf_data;
+ int strndx = secp->sec;
Elf_Scn *strscn = dso->scn[strndx];
/* Out with the old. */
@@ -2212,8 +2524,8 @@ edit_dwarf2_any_str (DSO *dso)
but the old ebl version will just abort on out of
memory... */
strtab_finalize (strtab, strdata);
- debug_sections[DEBUG_STR].size = strdata->d_size;
- dso->strings.str_buf = strdata->d_buf;
+ secp->size = strdata->d_size;
+ strings->str_buf = strdata->d_buf;
}
static int
@@ -2359,12 +2671,14 @@ edit_dwarf2 (DSO *dso)
bool info_rel_updated = false;
bool types_rel_updated = false;
bool macro_rel_updated = false;
+ bool line_rel_updated = false;
for (phase = 0; phase < 2; phase++)
{
/* If we don't need to update anyhing, skip phase 1. */
if (phase == 1
&& !need_strp_update
+ && !need_line_strp_update
&& !need_string_replacement
&& !need_stmt_update)
break;
@@ -2582,15 +2896,14 @@ edit_dwarf2 (DSO *dso)
if (phase == 0)
{
size_t idx = read_32_relocated (ptr);
- record_existing_string_entry_idx (&dso->strings,
- idx);
+ record_existing_string_entry_idx (false, dso, idx);
}
else
{
struct stridxentry *entry;
size_t idx, new_idx;
idx = do_read_32_relocated (ptr);
- entry = string_find_entry (&dso->strings, idx);
+ entry = string_find_entry (&dso->debug_str, idx);
new_idx = strent_offset (entry->entry);
write_32_relocated (ptr, new_idx);
}
@@ -2610,24 +2923,50 @@ edit_dwarf2 (DSO *dso)
}
}
- /* Same for the debug_str section. Make sure everything is
- in place for phase 1 updating of debug_info
+
+ /* Now handle all the DWARF5 line tables, they contain strp
+ and/or line_strp entries that need to be registered/rewritten. */
+ setup_relbuf(dso, &debug_sections[DEBUG_LINE], &reltype);
+ rel_updated = false;
+
+ /* edit_dwarf2_line will have set this up, unless there are no
+ moved/resized (DWARF4) lines. In which case we can just use
+ the original section data. new_idx will have been setup
+ correctly, even if it is the same as old_idx. */
+ unsigned char *line_buf = (unsigned char *)dso->lines.line_buf;
+ if (line_buf == NULL)
+ line_buf = debug_sections[DEBUG_LINE].data;
+ for (int ldx = 0; ldx < dso->lines.used; ldx++)
+ {
+ struct line_table *t = &dso->lines.table[ldx];
+ if (t->version >= 5)
+ read_dwarf5_line (dso, line_buf + t->new_idx, t, phase);
+ }
+ if (rel_updated)
+ line_rel_updated = true;
+
+ /* Same for the debug_str and debug_line_str sections.
+ Make sure everything is in place for phase 1 updating of debug_info
references. */
if (phase == 0 && need_strp_update)
- edit_dwarf2_any_str (dso);
-
+ edit_dwarf2_any_str (dso, &dso->debug_str,
+ &debug_sections[DEBUG_STR]);
+ if (phase == 0 && need_line_strp_update)
+ edit_dwarf2_any_str (dso, &dso->debug_line_str,
+ &debug_sections[DEBUG_LINE_STR]);
}
/* After phase 1 we might have rewritten the debug_info with
new strp, strings and/or linep offsets. */
- if (need_strp_update || need_string_replacement || need_stmt_update) {
+ if (need_strp_update || need_line_strp_update
+ || need_string_replacement || need_stmt_update) {
dirty_section (DEBUG_INFO);
if (debug_sections[DEBUG_TYPES].data != NULL)
dirty_section (DEBUG_TYPES);
}
if (need_strp_update || need_stmt_update)
dirty_section (DEBUG_MACRO);
- if (need_stmt_update)
+ if (need_stmt_update || need_line_strp_update)
dirty_section (DEBUG_LINE);
/* Update any relocations addends we might have touched. */
@@ -2653,6 +2992,9 @@ edit_dwarf2 (DSO *dso)
}
}
+ if (line_rel_updated)
+ update_rela_data (dso, &debug_sections[DEBUG_LINE]);
+
return 0;
}
@@ -2745,7 +3087,8 @@ fdopen_dso (int fd, const char *name)
}
dso->filename = (const char *) strdup (name);
- setup_strings (&dso->strings);
+ setup_strings (&dso->debug_str);
+ setup_strings (&dso->debug_line_str);
setup_lines (&dso->lines);
return dso;
@@ -2753,7 +3096,8 @@ error_out:
if (dso)
{
free ((char *) dso->filename);
- destroy_strings (&dso->strings);
+ destroy_strings (&dso->debug_str);
+ destroy_strings (&dso->debug_line_str);
destroy_lines (&dso->lines);
free (dso);
}
@@ -3034,7 +3378,9 @@ main (int argc, char *argv[])
in elfutils before 0.169 we will have to update and write out all
section data if any data has changed (when ELF_F_LAYOUT was
set). https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */
- bool need_update = need_strp_update || need_stmt_update;
+ bool need_update = (need_strp_update
+ || need_line_strp_update
+ || need_stmt_update);
#if !_ELFUTILS_PREREQ (0, 169)
/* string replacements or build_id updates don't change section size. */
@@ -3106,10 +3452,12 @@ main (int argc, char *argv[])
GElf_Xword sec_size = shdr->sh_size;
/* We might have changed the size (and content) of the
- debug_str or debug_line section. */
+ debug_str, debug_line_str or debug_line section. */
size_t secnum = elf_ndxscn (scn);
if (secnum == debug_sections[DEBUG_STR].sec)
sec_size = debug_sections[DEBUG_STR].size;
+ if (secnum == debug_sections[DEBUG_LINE_STR].sec)
+ sec_size = debug_sections[DEBUG_LINE_STR].size;
if (secnum == debug_sections[DEBUG_LINE].sec)
sec_size = debug_sections[DEBUG_LINE].size;
@@ -3179,7 +3527,8 @@ main (int argc, char *argv[])
chmod (file, stat_buf.st_mode);
free ((char *) dso->filename);
- destroy_strings (&dso->strings);
+ destroy_strings (&dso->debug_str);
+ destroy_strings (&dso->debug_line_str);
destroy_lines (&dso->lines);
free (dso);
--
2.18.4

View File

@ -0,0 +1,18 @@
diff --git a/rpm2cpio.c b/rpm2cpio.c
index 89ebdfa..ae999ff 100644
--- a/rpm2cpio.c
+++ b/rpm2cpio.c
@@ -84,7 +84,12 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
- rc = (ufdCopy(gzdi, fdo) == payload_size) ? EXIT_SUCCESS : EXIT_FAILURE;
+ /*
+ * XXX HACK for #1142949: should be equality test, but archive size
+ * short by cpio trailer size in packages built with rpm 4.12.0
+ * and its pre-releases.
+ */
+ rc = (ufdCopy(gzdi, fdo) >= payload_size) ? EXIT_SUCCESS : EXIT_FAILURE;
Fclose(fdo);

View File

@ -0,0 +1,15 @@
diff -up rpm-4.9.1.1/macros.in.jx rpm-4.9.1.1/macros.in
--- rpm-4.9.1.1/macros.in.jx 2011-08-03 16:19:05.000000000 -0400
+++ rpm-4.9.1.1/macros.in 2011-08-08 09:41:52.981064316 -0400
@@ -674,9 +674,10 @@ print (t)\
RPM_BUILD_DIR=\"%{u2p:%{_builddir}}\"\
RPM_OPT_FLAGS=\"%{optflags}\"\
+ RPM_LD_FLAGS=\"%{?build_ldflags}\"\
RPM_ARCH=\"%{_arch}\"\
RPM_OS=\"%{_os}\"\
RPM_BUILD_NCPUS=\"%{_smp_build_ncpus}\"\
- export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS\
+ export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_LD_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS RPM_LD_FLAGS\
RPM_DOC_DIR=\"%{_docdir}\"\
export RPM_DOC_DIR\
RPM_PACKAGE_NAME=\"%{NAME}\"\

View File

@ -0,0 +1,12 @@
diff -up rpm-4.11.1-rc1/macros.in.siteconfig rpm-4.11.1-rc1/macros.in
--- rpm-4.11.1-rc1/macros.in.siteconfig 2013-06-07 13:19:21.000000000 +0300
+++ rpm-4.11.1-rc1/macros.in 2013-06-11 15:06:59.525747503 +0300
@@ -647,6 +647,8 @@ package or when debugging this package.\
export CLASSPATH}\
PKG_CONFIG_PATH=\"${PKG_CONFIG_PATH}:%{_libdir}/pkgconfig:%{_datadir}/pkgconfig\"\
export PKG_CONFIG_PATH\
+ CONFIG_SITE=${CONFIG_SITE:-NONE}\
+ export CONFIG_SITE\
\
%{verbose:set -x}\
umask 022\

View File

@ -0,0 +1,334 @@
commit 39595ccee321497dc3b08c7cab8a10304345429c
Author: Radovan Sroka <rsroka@redhat.com>
Date: Tue Oct 27 16:18:04 2020 +0100
Added fapolicyd rpm plugin
Fapolicyd (File Access Policy Daemon) implements application whitelisting
to decide file access rights. Applications that are known via a reputation
source are allowed access while unknown applications are not.
The rpm plugin allows us to use rpm database as a source of trust.
We used dnf plugin since the beggining but it only provides notification
when transaction ends. With "integrity checking" requirement we need
a continual addition of files which are installed during the system
update. With fapolicyd rpm plugin we can allow using of recently
added/updated files in scriptlets during rpm transaction.
The fapolicyd plugin gathers metadata of currently installed files.
It sends the information about files and about ongoing rpm transaction
to the fapolicyd daemon. The information is written to Linux pipe which
is placed in /var/run/fapolicyd/fapolicyd.fifo.
The data format is "%s %lu %64s\n". [path, size, sha256]
The fapolicyd rpm plugin can be enabled with "--with-fapolicyd"
configure option.
Related PRs:
https://github.com/linux-application-whitelisting/fapolicyd/pull/105
https://github.com/linux-application-whitelisting/fapolicyd/pull/106
Signed-off-by: Radovan Sroka <rsroka@redhat.com>
Backported into 4.16.1.3, together with commit
6d61b7118adcc14631b7ee5163a481472af940b8 (covscan fix)
diff -up rpm-4.16.1.3/configure.ac.orig rpm-4.16.1.3/configure.ac
--- rpm-4.16.1.3/configure.ac.orig 2021-03-22 11:05:07.311635968 +0100
+++ rpm-4.16.1.3/configure.ac 2021-07-22 16:18:29.352006782 +0200
@@ -891,6 +891,14 @@ AS_IF([test "$enable_plugins" != no],[
AM_CONDITIONAL(IMA, [test "x$ac_cv_func_lsetxattr" = xyes])
#=================
+# Check for fapolicyd support
+AC_ARG_WITH(fapolicyd,
+AS_HELP_STRING([--with-fapolicyd],[build with File Access Policy Daemon support]),
+with_fapolicyd=$withval,
+with_fapolicyd=auto)
+AM_CONDITIONAL(FAPOLICYD,[test "$with_fapolicyd" = yes])
+
+#=================
# Check for audit library.
AC_ARG_WITH(audit,
AS_HELP_STRING([--with-audit],[Linux audit plugin]),
diff -up rpm-4.16.1.3/doc/Makefile.am.orig rpm-4.16.1.3/doc/Makefile.am
--- rpm-4.16.1.3/doc/Makefile.am.orig 2020-06-23 14:13:01.895628382 +0200
+++ rpm-4.16.1.3/doc/Makefile.am 2021-07-22 16:18:29.352006782 +0200
@@ -25,6 +25,9 @@ endif
if IMA
man_man8_DATA += rpm-plugin-ima.8
endif
+if FAPOLICYD
+man_man8_DATA += rpm-plugin-fapolicyd.8
+endif
if SELINUX
man_man8_DATA += rpm-plugin-selinux.8
endif
@@ -37,6 +40,8 @@ endif
EXTRA_DIST += rpm-plugins.8 rpm-plugin-prioreset.8 rpm-plugin-syslog.8
EXTRA_DIST += rpm-plugin-audit.8 rpm-plugin-systemd-inhibit.8
EXTRA_DIST += rpm-plugin-ima.8 rpm-plugin-selinux.8 rpm2archive.8
+EXTRA_DIST += rpm-plugin-fapolicyd.8
+
man_fr_man8dir = $(mandir)/fr/man8
man_fr_man8_DATA = fr/rpm.8
diff -up rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8.orig rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8
--- rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8.orig 2021-07-22 16:18:29.353006800 +0200
+++ rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8 2021-07-22 16:18:29.353006800 +0200
@@ -0,0 +1,21 @@
+'\" t
+.TH "RPM-FAPOLICYD" "8" "28 Jan 2021" "Red Hat, Inc."
+.SH NAME
+rpm-plugin-fapolicyd \- Fapolicyd plugin for the RPM Package Manager
+
+.SH Description
+
+The plugin gathers metadata of currently installed files. It sends the
+information about files and about ongoing rpm transaction to the fapolicyd daemon.
+The information is written to Linux pipe which is placed in
+/var/run/fapolicyd/fapolicyd.fifo.
+
+.SH Configuration
+
+There are currently no options for this plugin in particular. See
+.BR rpm-plugins (8)
+on how to control plugins in general.
+
+.SH SEE ALSO
+.IR fapolicyd (8)
+.IR rpm-plugins (8)
diff -up rpm-4.16.1.3/macros.in.orig rpm-4.16.1.3/macros.in
--- rpm-4.16.1.3/macros.in.orig 2021-07-22 16:18:20.525844141 +0200
+++ rpm-4.16.1.3/macros.in 2021-07-22 16:19:36.196238525 +0200
@@ -1208,6 +1208,7 @@ package or when debugging this package.\
%__transaction_selinux %{__plugindir}/selinux.so
%__transaction_syslog %{__plugindir}/syslog.so
%__transaction_ima %{__plugindir}/ima.so
+%__transaction_fapolicyd %{__plugindir}/fapolicyd.so
%__transaction_prioreset %{__plugindir}/prioreset.so
%__transaction_audit %{__plugindir}/audit.so
diff -up rpm-4.16.1.3/Makefile.am.orig rpm-4.16.1.3/Makefile.am
--- rpm-4.16.1.3/Makefile.am.orig 2021-07-22 16:18:29.350006745 +0200
+++ rpm-4.16.1.3/Makefile.am 2021-07-22 16:19:18.223907346 +0200
@@ -14,6 +14,7 @@ DISTCHECK_CONFIGURE_FLAGS = \
--with-audit \
--with-selinux \
--with-imaevm \
+ --with-fapolicyd \
--disable-dependency-tracking
include $(top_srcdir)/rpm.am
diff -up rpm-4.16.1.3/plugins/fapolicyd.c.orig rpm-4.16.1.3/plugins/fapolicyd.c
--- rpm-4.16.1.3/plugins/fapolicyd.c.orig 2021-07-22 16:18:29.356006855 +0200
+++ rpm-4.16.1.3/plugins/fapolicyd.c 2021-07-22 16:18:35.380117862 +0200
@@ -0,0 +1,191 @@
+#include "system.h"
+
+#include <rpm/rpmts.h>
+#include <rpm/rpmlog.h>
+#include "lib/rpmplugin.h"
+
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+struct fapolicyd_data {
+ int fd;
+ long changed_files;
+ const char * fifo_path;
+};
+
+static struct fapolicyd_data fapolicyd_state = {
+ .fd = -1,
+ .changed_files = 0,
+ .fifo_path = "/run/fapolicyd/fapolicyd.fifo",
+};
+
+static rpmRC open_fifo(struct fapolicyd_data* state)
+{
+ int fd = -1;
+ struct stat s;
+
+ fd = open(state->fifo_path, O_RDWR);
+ if (fd == -1) {
+ rpmlog(RPMLOG_DEBUG, "Open: %s -> %s\n", state->fifo_path, strerror(errno));
+ goto bad;
+ }
+
+ if (stat(state->fifo_path, &s) == -1) {
+ rpmlog(RPMLOG_DEBUG, "Stat: %s -> %s\n", state->fifo_path, strerror(errno));
+ goto bad;
+ }
+
+ if (!S_ISFIFO(s.st_mode)) {
+ rpmlog(RPMLOG_DEBUG, "File: %s exists but it is not a pipe!\n", state->fifo_path);
+ goto bad;
+ }
+
+ /* keep only file's permition bits */
+ mode_t mode = s.st_mode & ~S_IFMT;
+
+ /* we require pipe to have 0660 permission */
+ if (mode != 0660) {
+ rpmlog(RPMLOG_ERR, "File: %s has %o instead of 0660 \n",
+ state->fifo_path,
+ mode );
+ goto bad;
+ }
+
+ state->fd = fd;
+ /* considering success */
+ return RPMRC_OK;
+
+ bad:
+ if (fd >= 0)
+ close(fd);
+ return RPMRC_FAIL;
+}
+
+static rpmRC write_fifo(struct fapolicyd_data* state, const char * str)
+{
+ ssize_t len = strlen(str);
+ ssize_t written = 0;
+ ssize_t n = 0;
+
+ while (written < len) {
+ if ((n = write(state->fd, str + written, len - written)) < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ rpmlog(RPMLOG_DEBUG, "Write: %s -> %s\n", state->fifo_path, strerror(errno));
+ goto bad;
+ }
+ written += n;
+ }
+
+ return RPMRC_OK;
+
+ bad:
+ return RPMRC_FAIL;
+}
+
+static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts)
+{
+ if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
+ goto end;
+
+ if (!rstreq(rpmtsRootDir(ts), "/"))
+ goto end;
+
+ (void) open_fifo(&fapolicyd_state);
+
+ end:
+ return RPMRC_OK;
+}
+
+static void fapolicyd_cleanup(rpmPlugin plugin)
+{
+ if (fapolicyd_state.fd > 0)
+ (void) close(fapolicyd_state.fd);
+
+ fapolicyd_state.fd = -1;
+}
+
+static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res)
+{
+ if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
+ goto end;
+
+ /* we are ready */
+ if (fapolicyd_state.fd > 0) {
+ /* send a signal that transaction is over */
+ (void) write_fifo(&fapolicyd_state, "1\n");
+ /* flush cache */
+ (void) write_fifo(&fapolicyd_state, "2\n");
+ }
+
+ end:
+ return RPMRC_OK;
+}
+
+static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name,
+ int type)
+{
+ if (fapolicyd_state.fd == -1)
+ goto end;
+
+ if (fapolicyd_state.changed_files > 0) {
+ /* send signal to flush cache */
+ (void) write_fifo(&fapolicyd_state, "2\n");
+
+ /* optimize flushing */
+ /* flush only when there was an actual change */
+ fapolicyd_state.changed_files = 0;
+ }
+
+ end:
+ return RPMRC_OK;
+}
+
+static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
+ const char *path, const char *dest,
+ mode_t file_mode, rpmFsmOp op)
+{
+ /* not ready */
+ if (fapolicyd_state.fd == -1)
+ goto end;
+
+ rpmFileAction action = XFO_ACTION(op);
+
+ /* Ignore skipped files and unowned directories */
+ if (XFA_SKIPPING(action) || (op & FAF_UNOWNED)) {
+ rpmlog(RPMLOG_DEBUG, "fapolicyd skipping early: path %s dest %s\n",
+ path, dest);
+ goto end;
+ }
+
+ if (!S_ISREG(rpmfiFMode(fi))) {
+ rpmlog(RPMLOG_DEBUG, "fapolicyd skipping non regular: path %s dest %s\n",
+ path, dest);
+ goto end;
+ }
+
+ fapolicyd_state.changed_files++;
+
+ char buffer[4096];
+
+ rpm_loff_t size = rpmfiFSize(fi);
+ char * sha = rpmfiFDigestHex(fi, NULL);
+
+ snprintf(buffer, 4096, "%s %lu %64s\n", dest, size, sha);
+ (void) write_fifo(&fapolicyd_state, buffer);
+
+ free(sha);
+
+ end:
+ return RPMRC_OK;
+}
+
+struct rpmPluginHooks_s fapolicyd_hooks = {
+ .init = fapolicyd_init,
+ .cleanup = fapolicyd_cleanup,
+ .scriptlet_pre = fapolicyd_scriptlet_pre,
+ .tsm_post = fapolicyd_tsm_post,
+ .fsm_file_prepare = fapolicyd_fsm_file_prepare,
+};
diff -up rpm-4.16.1.3/plugins/Makefile.am.orig rpm-4.16.1.3/plugins/Makefile.am
--- rpm-4.16.1.3/plugins/Makefile.am.orig 2021-07-22 16:18:23.022890155 +0200
+++ rpm-4.16.1.3/plugins/Makefile.am 2021-07-22 16:18:55.797494098 +0200
@@ -43,6 +43,12 @@ ima_la_LIBADD = $(top_builddir)/lib/libr
plugins_LTLIBRARIES += ima.la
endif
+if FAPOLICYD
+fapolicyd_la_sources = fapolicyd.c
+fapolicyd_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
+plugins_LTLIBRARIES += fapolicyd.la
+endif
+
if AUDIT
audit_la_sources = audit.c
audit_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la @WITH_AUDIT_LIB@

View File

@ -0,0 +1,13 @@
diff -up rpm-4.16.1.3/tools/hashtab.c.orig rpm-4.16.1.3/tools/hashtab.c
--- rpm-4.16.1.3/tools/hashtab.c.orig 2021-07-01 14:51:24.576237269 +0200
+++ rpm-4.16.1.3/tools/hashtab.c 2021-07-01 15:02:42.005754968 +0200
@@ -292,7 +292,8 @@ htab_expand (htab)
}
while (p < olimit);
- free (oentries);
+ if (oentries != htab->entries)
+ free(oentries);
return 1;
}

View File

@ -0,0 +1,286 @@
commit c7d7c5acd0c14d0450016887cba1d86483086794
Author: Michal Domonkos <mdomonko@redhat.com>
Date: Mon Jun 21 10:05:10 2021 +0200
Add quoting to literal curly brackets
These curly brackets are already treated as literals by the shell, so
let's make that explicit for clarity, and silence a ShellCheck warning
at the same time.
More info: https://github.com/koalaman/shellcheck/wiki/SC1083
Found by ShellCheck.
Adjusted for 4.16.1.3
diff -up rpm-4.16.1.3/scripts/check-rpaths-worker.orig rpm-4.16.1.3/scripts/check-rpaths-worker
--- rpm-4.16.1.3/scripts/check-rpaths-worker.orig 2021-06-29 15:34:31.671003589 +0200
+++ rpm-4.16.1.3/scripts/check-rpaths-worker 2021-06-29 15:34:51.993414093 +0200
@@ -120,13 +120,13 @@ for i; do
(/lib64/*|/usr/lib64/*|/usr/X11R6/lib64/*|/usr/local/lib64/*)
badness=0;;
- (\$ORIGIN|\${ORIGINX}|\$ORIGIN/*|\${ORIGINX}/*)
+ (\$ORIGIN|\$\{ORIGINX\}|\$ORIGIN/*|\$\{ORIGINX\}/*)
test $allow_ORIGIN -eq 0 && badness=8 || {
badness=0
new_allow_ORIGIN=1
}
;;
- (/*\$PLATFORM*|/*\${PLATFORM}*|/*\$LIB*|/*\${LIB}*)
+ (/*\$PLATFORM*|/*\$\{PLATFORM\}*|/*\$LIB*|/*\$\{LIB\}*)
badness=0;;
(/lib|/usr/lib|/usr/X11R6/lib)
From d8dc4fd37b1d90cd97de7fcf484d449ec132c9b3 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Wed, 9 Jun 2021 21:31:40 +0200
Subject: [PATCH 1/7] Fix memory leak in sqlexec()
Callers are supposed to free the error strings themselves:
https://www.sqlite.org/capi3ref.html#sqlite3_exec
Found by Coverity.
---
lib/backend/sqlite.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/backend/sqlite.c b/lib/backend/sqlite.c
index 7c2de45aa..dbefeb163 100644
--- a/lib/backend/sqlite.c
+++ b/lib/backend/sqlite.c
@@ -233,6 +233,7 @@ static int sqlexec(sqlite3 *sdb, const char *fmt, ...)
rpmlog(RPMLOG_DEBUG, "%s: %d\n", cmd, rc);
sqlite3_free(cmd);
+ sqlite3_free(err);
return rc ? RPMRC_FAIL : RPMRC_OK;
}
--
2.31.1
From 5baf73feb4951cc3b3f553a4b18d3b3599cbf87c Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Fri, 25 Jun 2021 11:21:46 +0200
Subject: [PATCH 2/7] Always free the arg list passed to rpmGlob()
Even though the actual implementation of rpmGlob() does not allocate the
passed arg list (av) if the return code (rc) is non-zero or arg count
(ac) is 0, it's the responsibility of the caller (rpmInstall() here) to
free that memory, so make sure we do that irrespectively of the above
conditions.
Found by Coverity.
---
lib/rpminstall.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/rpminstall.c b/lib/rpminstall.c
index 724126e94..302ec0ba1 100644
--- a/lib/rpminstall.c
+++ b/lib/rpminstall.c
@@ -461,6 +461,7 @@ int rpmInstall(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_t fileArgv)
rpmlog(RPMLOG_ERR, _("File not found by glob: %s\n"), *eiu->fnp);
}
eiu->numFailed++;
+ argvFree(av);
continue;
}
--
2.31.1
From 3c8b01b67ec907afaaffe71691fa41b878578527 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Mon, 14 Jun 2021 10:21:25 +0200
Subject: [PATCH 3/7] Fix resource leak in Fts_children()
This function is not used anywhere within our codebase (and neither is
it part of the public API) so it's basically a no-op... Still, rather
than yanking it completely, let's just silence the Coverity error here.
Found by Coverity.
---
misc/fts.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/misc/fts.c b/misc/fts.c
index d3ebb2946..caf27495d 100644
--- a/misc/fts.c
+++ b/misc/fts.c
@@ -585,8 +585,10 @@ Fts_children(FTS * sp, int instr)
if ((fd = __open(".", O_RDONLY, 0)) < 0)
return (NULL);
sp->fts_child = fts_build(sp, instr);
- if (__fchdir(fd))
+ if (__fchdir(fd)) {
+ (void)__close(fd);
return (NULL);
+ }
(void)__close(fd);
return (sp->fts_child);
}
--
2.31.1
From 39b7bf8579e0522cf16347b3a7e332d3b6d742c6 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Mon, 14 Jun 2021 12:34:23 +0200
Subject: [PATCH 4/7] Fix memory leak in fts_build()
Turns out this leak is already fixed in glibc's current version of fts.c
(where our copy originates from), so let's just backport that.
Original commit in glibc:
https://sourceware.org/git/?p=glibc.git;\
a=commit;h=db67c2c98b89a5723af44df54f38b779de8d4a65
Found by Coverity.
---
misc/fts.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/misc/fts.c b/misc/fts.c
index caf27495d..f7fce0eaa 100644
--- a/misc/fts.c
+++ b/misc/fts.c
@@ -855,6 +855,7 @@ mem1: saved_errno = errno;
fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
cur->fts_info = FTS_ERR;
SET(FTS_STOP);
+ fts_lfree(head);
return (NULL);
}
@@ -862,6 +863,7 @@ mem1: saved_errno = errno;
if (!nitems) {
if (type == BREAD)
cur->fts_info = FTS_DP;
+ fts_lfree(head);
return (NULL);
}
--
2.31.1
From 9c093c4f092dd6bd1e0c8d2b852a72b74db076c2 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Tue, 15 Jun 2021 13:34:21 +0200
Subject: [PATCH 5/7] Fix memory leak in decodePkts()
Found by Coverity.
---
rpmio/rpmpgp.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
index c59185dce..ee5c81e24 100644
--- a/rpmio/rpmpgp.c
+++ b/rpmio/rpmpgp.c
@@ -1371,9 +1371,13 @@ static pgpArmor decodePkts(uint8_t *b, uint8_t **pkt, size_t *pktlen)
crc = pgpCRC(dec, declen);
if (crcpkt != crc) {
ec = PGPARMOR_ERR_CRC_CHECK;
+ _free(dec);
goto exit;
}
- if (pkt) *pkt = dec;
+ if (pkt)
+ *pkt = dec;
+ else
+ _free(dec);
if (pktlen) *pktlen = declen;
ec = PGPARMOR_PUBKEY; /* XXX ASCII Pubkeys only, please. */
goto exit;
--
2.31.1
From 590b2fc06252567eb7d57197dc361a8b459d62a3 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Mon, 21 Jun 2021 17:51:14 +0200
Subject: [PATCH 6/7] Fix memory leak with multiple %lang-s in one line
We permit two equivalent forms of specifying a list of languages per
file:
%lang(xx,yy,zz) /path/to/file
%lang(xx) %lang(yy) %lang(zz) /path/to/file
The leak was when parsing the second form.
Found by Coverity.
---
build/files.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/build/files.c b/build/files.c
index f8153ad2b..0c8859f6c 100644
--- a/build/files.c
+++ b/build/files.c
@@ -777,6 +777,8 @@ static rpmRC parseForLang(char * buf, FileEntry cur)
if (*pe == ',') pe++; /* skip , if present */
}
+
+ q = _free(q);
}
rc = RPMRC_OK;
--
2.31.1
From b7a1e996326ee29a163d67ceb1e6127fdc251c14 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Fri, 25 Jun 2021 15:15:08 +0200
Subject: [PATCH 7/7] Fix memory leaks in Lua rex extension
This covers the following usage:
expr = rex.newPOSIX(<regex>)
expr:match(<string>) # A leak occurred here
expr:gmatch(<string>, <func>) # A leak occurred here
Found by Coverity.
---
luaext/lrexlib.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/luaext/lrexlib.c b/luaext/lrexlib.c
index 09c5a6454..0f29b6371 100644
--- a/luaext/lrexlib.c
+++ b/luaext/lrexlib.c
@@ -80,6 +80,7 @@ static void rex_push_matches(lua_State *L, const char *text, regmatch_t *match,
static int rex_match(lua_State *L)
{
+ int rc = 0;
int res;
#ifdef REG_BASIC
size_t len;
@@ -109,9 +110,10 @@ static int rex_match(lua_State *L)
lua_pushstring(L, "n");
lua_pushnumber(L, ncapt);
lua_rawset(L, -3);
- return 3;
- } else
- return 0;
+ rc = 3;
+ }
+ free(match);
+ return rc;
}
static int rex_gmatch(lua_State *L)
@@ -158,6 +160,7 @@ static int rex_gmatch(lua_State *L)
break;
}
lua_pushnumber(L, nmatch);
+ free(match);
return 1;
}
--
2.31.1

View File

@ -0,0 +1,20 @@
commit 23770e1a4f28c56a31fe600cae332c77333b60b6
Author: Demi Marie Obenour <athena@invisiblethingslab.com>
Date: Sat Mar 6 03:23:41 2021 -0500
rpmsign: support EdDSA signatures
They were previously rejected
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
index 28cd91576..d8c84e937 100644
--- a/sign/rpmgensig.c
+++ b/sign/rpmgensig.c
@@ -155,6 +155,7 @@ static rpmtd makeSigTag(Header sigh, int ishdr, uint8_t *pkt, size_t pktlen)
pubkey_algo = pgpDigParamsAlgo(sigp, PGPVAL_PUBKEYALGO);
switch (pubkey_algo) {
case PGPPUBKEYALGO_DSA:
+ case PGPPUBKEYALGO_EDDSA:
sigtag = ishdr ? RPMSIGTAG_DSA : RPMSIGTAG_GPG;
break;
case PGPPUBKEYALGO_RSA:

View File

@ -0,0 +1,32 @@
commit cb6aa82dbc10d554f8d234e934ae7c77e39a3ce2
Author: Panu Matilainen <pmatilai@redhat.com>
Date: Tue Jan 12 13:35:23 2021 +0200
Unblock signals in forked scriptlets
Since commit c5f82d3f6223ebd0c5cc0a07ea60393ae7284929 we've blocked
most signals during transactions, which makes sense to rpm itself but
the signal mask is inherited to childs and carried even across exec(),
so all scriptlets are executing with those signals blocked as well.
Which in turn does not make sense, the scriptlets could run stuff that
actually depends on signal delivery (such as SIGALARM in RhBug:1913765).
Unblock all signals for forked scriptlet execution (Lua scriptlets are
totally different as they execute in-process for now)
diff --git a/lib/rpmscript.c b/lib/rpmscript.c
index 2ae3378f7..c69d29554 100644
--- a/lib/rpmscript.c
+++ b/lib/rpmscript.c
@@ -152,6 +152,11 @@ static void doScriptExec(ARGV_const_t argv, ARGV_const_t prefixes,
FD_t scriptFd, FD_t out)
{
int xx;
+ sigset_t set;
+
+ /* Unmask all signals, the scripts may need them */
+ sigfillset(&set);
+ sigprocmask(SIG_UNBLOCK, &set, NULL);
/* SIGPIPE is ignored in rpm, reset to default for the scriptlet */
(void) signal(SIGPIPE, SIG_DFL);

View File

@ -0,0 +1,14 @@
diff --git a/rpmrc.in b/rpmrc.in
index 4a6cca9..d62ddaf 100644
--- a/rpmrc.in
+++ b/rpmrc.in
@@ -281,7 +281,7 @@ arch_compat: alphaev5: alpha
arch_compat: alpha: axp noarch
arch_compat: athlon: i686
-arch_compat: geode: i586
+arch_compat: geode: i686
arch_compat: pentium4: pentium3
arch_compat: pentium3: i686
arch_compat: i686: i586

View File

@ -0,0 +1,12 @@
diff -up rpm-4.9.90.git11486/scripts/find-lang.sh.no-man-dirs rpm-4.9.90.git11486/scripts/find-lang.sh
--- rpm-4.9.90.git11486/scripts/find-lang.sh.no-man-dirs 2012-03-07 11:31:10.000000000 +0200
+++ rpm-4.9.90.git11486/scripts/find-lang.sh 2012-03-07 15:11:57.465801075 +0200
@@ -181,7 +181,7 @@ s:%lang(C) ::
find "$TOP_DIR" -type d|sed '
s:'"$TOP_DIR"'::
'"$ALL_NAME$MAN"'s:\(.*/man/\([^/_]\+\).*/man[a-z0-9]\+/\)::
-'"$ALL_NAME$MAN"'s:\(.*/man/\([^/_]\+\).*/man[a-z0-9]\+$\):%lang(\2) \1*:
+'"$ALL_NAME$MAN"'s:\(.*/man/\([^/_]\+\).*/man[a-z0-9]\+$\):%lang(\2) \1/*:
s:^\([^%].*\)::
s:%lang(C) ::
/^$/d' >> $MO_NAME

View File

@ -0,0 +1,19 @@
[Unit]
Description=RPM database rebuild
ConditionPathExists=/var/lib/rpm/.rebuilddb
# This should run before any daemons that may open the rpmdb
DefaultDependencies=no
After=sysinit.target
Before=basic.target shutdown.target
Conflicts=shutdown.target
# In case /var is remote-mounted
RequiresMountsFor=/var
[Service]
Type=oneshot
ExecStart=/usr/bin/rpmdb --rebuilddb
ExecStartPost=rm -f /var/lib/rpm/.rebuilddb
[Install]
WantedBy=basic.target

1075
SPECS/rpm.spec Normal file

File diff suppressed because it is too large Load Diff