summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2024-08-01 14:29:38 +0000
committerCoprDistGit <infra@openeuler.org>2024-08-01 14:29:38 +0000
commitf839e58f71e0deb90d6f486a674a6c931c9b625e (patch)
treefbf6ac981444e15e420b23c620de5b67e834cac1
parent5d42a8bd72cdd45ba41fe93ed8cb1de89af1fec0 (diff)
automatic import of debugeditopeneuler24.03_LTSopeneuler23.09
-rw-r--r--.gitignore3
-rw-r--r--0001-debugedit-Add-support-for-.debug_str_offsets-DW_FORM.patch432
-rw-r--r--0001-tests-Handle-zero-directory-entry-in-.debug_line-DWA.patch130
-rw-r--r--0002-scripts-find-debuginfo.in-Add-q-quiet.patch116
-rw-r--r--debugedit.spec122
-rw-r--r--sources3
6 files changed, 806 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..2180551 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1,3 @@
+/debugedit-5.0.tar.xz
+/debugedit-5.0.tar.xz.sig
+/gpgkey-5C1D1AA44BE649DE760A.gpg
diff --git a/0001-debugedit-Add-support-for-.debug_str_offsets-DW_FORM.patch b/0001-debugedit-Add-support-for-.debug_str_offsets-DW_FORM.patch
new file mode 100644
index 0000000..ce45c4f
--- /dev/null
+++ b/0001-debugedit-Add-support-for-.debug_str_offsets-DW_FORM.patch
@@ -0,0 +1,432 @@
+From 3e7aeeab4f744ad15108775685db68d3a35b0735 Mon Sep 17 00:00:00 2001
+From: Mark Wielaard <mark@klomp.org>
+Date: Thu, 23 Mar 2023 18:07:40 +0100
+Subject: [PATCH] debugedit: Add support for .debug_str_offsets (DW_FORM_strx)
+
+In theory supporting strx .debug_str_offsets is easy, the strings in
+.debug_str are just read through an indirection table. When the
+strings are updated in .debug_str we just need to rewrite the
+indirection table.
+
+The tricky part is the ET_REL (object files or kernel modules)
+support. Relocation reading is "global" per section and we expect to
+read a relocation only once. But we need to read the
+DW_AT_str_offsets_base before reading any strx form attributes. So we
+read that first, then reset the relptr. And when we read from the
+.debug_str_offsets section we need to save and restore the .debug_info
+relptr.
+
+ * tools/debugedit.c (do_read_24): New function.
+ (str_offsets_base): New static variable.
+ (buf_read_ule24): New function.
+ (buf_read_ube24): Likewise.
+ (setup_relbuf): Handle .debug_str_offsets.
+ (do_read_uleb128): New function.
+ (do_read_str_form_relocated): Likewise.
+ (read_abbrev): Handle DW_FORM_strx[1234].
+ (edit_strp): Take the actual string form as argument.
+ Use do_read_str_form_relocated.
+ (read_dwarf5_line_entries): Pass form to edit_strp.
+ (edit_attributes_str_comp_dir): Take the actual string
+ form as argument. Use do_read_str_form_relocated.
+ (edit_attributes): Handle DW_FORM_strx[1234].
+ (edit_info): Read DW_AT_str_offsets_base first.
+ (update_str_offsets): New function.
+ (edit_dwarf2): Setup do_read_24. Call update_str_offsets.
+
+https://sourceware.org/bugzilla/show_bug.cgi?id=28728
+
+Signed-off-by: Mark Wielaard <mark@klomp.org>
+---
+ tools/debugedit.c | 216 ++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 192 insertions(+), 24 deletions(-)
+
+diff --git a/tools/debugedit.c b/tools/debugedit.c
+index e654981..7802f9f 100644
+--- a/tools/debugedit.c
++++ b/tools/debugedit.c
+@@ -1,4 +1,5 @@
+ /* Copyright (C) 2001-2003, 2005, 2007, 2009-2011, 2016, 2017 Red Hat, Inc.
++ Copyright (C) 2022, 2023 Mark J. Wielaard <mark@klomp.org>
+ Written by Alexander Larsson <alexl@redhat.com>, 2002
+ Based on code by Jakub Jelinek <jakub@redhat.com>, 2001.
+ String/Line table rewriting by Mark Wielaard <mjw@redhat.com>, 2017.
+@@ -264,6 +264,7 @@ typedef struct
+ })
+
+ static uint16_t (*do_read_16) (unsigned char *ptr);
++static uint32_t (*do_read_24) (unsigned char *ptr);
+ static uint32_t (*do_read_32) (unsigned char *ptr);
+ static void (*do_write_16) (unsigned char *ptr, uint16_t val);
+ static void (*do_write_32) (unsigned char *ptr, uint32_t val);
+@@ -271,6 +272,9 @@ static void (*do_write_32) (unsigned char *ptr, uint32_t val);
+ static int ptr_size;
+ static int cu_version;
+
++/* The offset into the .debug_str_offsets section for the current CU. */
++static uint32_t str_offsets_base;
++
+ static inline uint16_t
+ buf_read_ule16 (unsigned char *data)
+ {
+@@ -283,6 +287,18 @@ buf_read_ube16 (unsigned char *data)
+ return data[1] | (data[0] << 8);
+ }
+
++static inline uint32_t
++buf_read_ule24 (unsigned char *data)
++{
++ return data[0] | (data[1] << 8) | (data[2] << 16);
++}
++
++static inline uint32_t
++buf_read_ube24 (unsigned char *data)
++{
++ return data[2] | (data[1] << 8) | (data[0] << 16);
++}
++
+ static inline uint32_t
+ buf_read_ule32 (unsigned char *data)
+ {
+@@ -544,10 +560,12 @@ 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,
+- .debug_line_str, and .debug_abbrev. */
++ /* Only consider relocations against .debug_str,
++ .debug_str_offsets, .debug_line, .debug_line_str, and
++ .debug_abbrev. */
+ if (sym.st_shndx == 0 ||
+ (sym.st_shndx != debug_sections[DEBUG_STR].sec
++ && sym.st_shndx != debug_sections[DEBUG_STR_OFFSETS].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))
+@@ -684,6 +702,59 @@ update_rela_data (DSO *dso, struct debug_section *sec)
+ free (sec->relbuf);
+ }
+
++static inline uint32_t
++do_read_uleb128 (unsigned char *ptr)
++{
++ unsigned char *uleb_ptr = ptr;
++ return read_uleb128 (uleb_ptr);
++}
++
++static inline uint32_t
++do_read_str_form_relocated (DSO *dso, uint32_t form, unsigned char *ptr)
++{
++ uint32_t idx;
++ switch (form)
++ {
++ case DW_FORM_strp:
++ case DW_FORM_line_strp:
++ return do_read_32_relocated (ptr);
++
++ case DW_FORM_strx1:
++ idx = *ptr;
++ break;
++ case DW_FORM_strx2:
++ idx = do_read_16 (ptr);
++ break;
++ case DW_FORM_strx3:
++ idx = do_read_24 (ptr);
++ break;
++ case DW_FORM_strx4:
++ idx = do_read_32 (ptr);
++ break;
++ case DW_FORM_strx:
++ idx = do_read_uleb128 (ptr);
++ break;
++ default:
++ error (1, 0, "Unhandled string form DW_FORM_0x%x", form);
++ return -1;
++ }
++
++ unsigned char *str_off_ptr = debug_sections[DEBUG_STR_OFFSETS].data;
++ str_off_ptr += str_offsets_base;
++ str_off_ptr += idx * 4;
++
++ /* Switch rel reading... */
++ REL *old_relptr = relptr;
++ REL *old_relend = relend;
++ setup_relbuf(dso, &debug_sections[DEBUG_STR_OFFSETS], &reltype);
++
++ uint32_t str_off = do_read_32_relocated (str_off_ptr);
++
++ relptr = old_relptr;
++ relend = old_relend;
++ return str_off;
++}
++
+ struct abbrev_attr
+ {
+ unsigned int attr;
+@@ -789,7 +860,12 @@ no_memory:
+ || form == DW_FORM_addrx1
+ || form == DW_FORM_addrx2
+ || form == DW_FORM_addrx3
+- || form == DW_FORM_addrx4)))
++ || form == DW_FORM_addrx4
++ || form == DW_FORM_strx
++ || form == DW_FORM_strx1
++ || form == DW_FORM_strx2
++ || form == DW_FORM_strx3
++ || form == DW_FORM_strx4)))
+ {
+ error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename,
+ form);
+@@ -1520,9 +1596,10 @@ edit_dwarf2_line (DSO *dso)
+ }
+ }
+
+-/* Record or adjust (according to phase) DW_FORM_strp or DW_FORM_line_strp. */
++/* Record or adjust (according to phase) DW_FORM_strp or DW_FORM_line_strp.
++ Also handles DW_FORM_strx, but just for recording the (indexed) string. */
+ static void
+-edit_strp (DSO *dso, bool line_strp, unsigned char *ptr, int phase,
++edit_strp (DSO *dso, uint32_t form, unsigned char *ptr, int phase,
+ bool handled_strp)
+ {
+ unsigned char *ptr_orig = ptr;
+@@ -1537,16 +1614,19 @@ edit_strp (DSO *dso, bool line_strp, unsigned char *ptr, int phase,
+ recorded. */
+ if (! handled_strp)
+ {
+- size_t idx = do_read_32_relocated (ptr);
+- record_existing_string_entry_idx (line_strp, dso, idx);
++ size_t idx = do_read_str_form_relocated (dso, form, ptr);
++ record_existing_string_entry_idx (form == DW_FORM_line_strp,
++ dso, idx);
+ }
+ }
+- else if (line_strp
+- ? need_line_strp_update : need_strp_update) /* && phase == 1 */
++ else if ((form == DW_FORM_strp
++ || form == DW_FORM_line_strp) /* DW_FORM_strx stays the same. */
++ && (form == DW_FORM_line_strp
++ ? need_line_strp_update : need_strp_update)) /* && phase == 1 */
+ {
+ struct stridxentry *entry;
+ size_t idx, new_idx;
+- struct strings *strings = (line_strp
++ struct strings *strings = (form == DW_FORM_line_strp
+ ? &dso->debug_line_str : &dso->debug_str);
+ idx = do_read_32_relocated (ptr);
+ entry = string_find_entry (strings, idx);
+@@ -1926,9 +2006,10 @@ read_dwarf5_line_entries (DSO *dso, unsigned char **ptrp,
+
+ switch (form)
+ {
++ /* Note we don't expect DW_FORM_strx in the line table. */
+ case DW_FORM_strp:
+ case DW_FORM_line_strp:
+- edit_strp (dso, line_strp, *ptrp, phase, handled_strp);
++ edit_strp (dso, form, *ptrp, phase, handled_strp);
+ break;
+ }
+
+@@ -2110,11 +2191,12 @@ find_new_list_offs (struct debug_lines *lines, size_t idx)
+
+ /* Read DW_FORM_strp or DW_FORM_line_strp collecting compilation directory. */
+ static void
+-edit_attributes_str_comp_dir (bool line_strp, DSO *dso, unsigned char **ptrp,
++edit_attributes_str_comp_dir (uint32_t form, DSO *dso, unsigned char **ptrp,
+ int phase, char **comp_dirp, bool *handled_strpp)
+ {
+ const char *dir;
+- size_t idx = do_read_32_relocated (*ptrp);
++ size_t idx = do_read_str_form_relocated (dso, form, *ptrp);
++ bool line_strp = form == DW_FORM_line_strp;
+ /* In phase zero we collect the comp_dir. */
+ if (phase == 0)
+ {
+@@ -2245,20 +2327,29 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
+ }
+ }
+ }
+- else if (form == DW_FORM_strp)
+- edit_attributes_str_comp_dir (false /* line_strp */, dso,
++ else if (form == DW_FORM_strp
++ || form == DW_FORM_line_strp
++ || form == DW_FORM_strx
++ || form == DW_FORM_strx1
++ || form == DW_FORM_strx2
++ || form == DW_FORM_strx3
++ || form == DW_FORM_strx4)
++ edit_attributes_str_comp_dir (form, 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)
+ && ((form == DW_FORM_strp
+ && debug_sections[DEBUG_STR].data)
+ || (form == DW_FORM_line_strp
+- && debug_sections[DEBUG_LINE_STR].data))
++ && debug_sections[DEBUG_LINE_STR].data)
++ || ((form == DW_FORM_strx
++ || form == DW_FORM_strx1
++ || form == DW_FORM_strx2
++ || form == DW_FORM_strx3
++ || form == DW_FORM_strx4)
++ && debug_sections[DEBUG_STR_OFFSETS].data))
+ && t->attr[i].attr == DW_AT_name)
+ {
+ bool line_strp = form == DW_FORM_line_strp;
+@@ -2267,7 +2358,7 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
+ unit. If starting with / it is a full path name.
+ Note that we don't handle DW_FORM_string in this
+ case. */
+- size_t idx = do_read_32_relocated (ptr);
++ size_t idx = do_read_str_form_relocated (dso, form, ptr);
+
+ /* In phase zero we will look for a comp_dir to use. */
+ if (phase == 0)
+@@ -2314,10 +2405,13 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
+ switch (form)
+ {
+ case DW_FORM_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);
++ case DW_FORM_strx:
++ case DW_FORM_strx1:
++ case DW_FORM_strx2:
++ case DW_FORM_strx3:
++ case DW_FORM_strx4:
++ edit_strp (dso, form, ptr, phase, handled_strp);
+ break;
+ }
+
+@@ -2404,6 +2498,8 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
+ uint32_t value;
+ htab_t abbrev;
+ struct abbrev_tag tag, *t;
++ int i;
++ bool first;
+
+ ptr = sec->data;
+ if (ptr == NULL)
+@@ -2507,6 +2603,8 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
+ if (abbrev == NULL)
+ return 1;
+
++ first = true;
++ str_offsets_base = 0;
+ while (ptr < endcu)
+ {
+ tag.entry = read_uleb128 (ptr);
+@@ -2521,6 +2619,30 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
+ return 1;
+ }
+
++ /* We need str_offsets_base before processing the CU. */
++ if (first)
++ {
++ first = false;
++ if (cu_version >= 5)
++ {
++ uint32_t form;
++ unsigned char *fptr = ptr;
++ // We will read this DIE again, save and reset rel reading
++ REL *old_relptr = relptr;
++ for (i = 0; i < t->nattr; ++i)
++ {
++ form = t->attr[i].form;
++ if (t->attr[i].attr == DW_AT_str_offsets_base)
++ {
++ str_offsets_base = do_read_32_relocated (fptr);
++ break;
++ }
++ skip_form (dso, &form, &fptr);
++ }
++ // Reset the rel reading...
++ relptr = old_relptr;
++ }
++ }
+ ptr = edit_attributes (dso, ptr, t, phase);
+ if (ptr == NULL)
+ break;
+@@ -2554,6 +2676,41 @@ edit_dwarf2_any_str (DSO *dso, struct strings *strings, debug_section *secp)
+ strings->str_buf = strdata->d_buf;
+ }
+
++/* Rebuild .debug_str_offsets. */
++static void
++update_str_offsets (DSO *dso)
++{
++ unsigned char *ptr = debug_sections[DEBUG_STR_OFFSETS].data;
++ unsigned char *endp = ptr + debug_sections[DEBUG_STR_OFFSETS].size;
++
++ while (ptr < endp)
++ {
++ /* Read header, unit_length, version and padding. */
++ if (endp - ptr < 3 * 4)
++ break;
++ uint32_t unit_length = read_32 (ptr);
++ if (unit_length == 0xffffffff || endp - ptr < unit_length)
++ break;
++ unsigned char *endidxp = ptr + unit_length;
++ uint32_t version = read_32 (ptr);
++ if (version != 5)
++ break;
++ uint32_t padding = read_32 (ptr);
++ if (padding != 0)
++ break;
++
++ while (ptr < endidxp)
++ {
++ struct stridxentry *entry;
++ size_t idx, new_idx;
++ idx = do_read_32_relocated (ptr);
++ entry = string_find_entry (&dso->debug_str, idx);
++ new_idx = strent_offset (entry->entry);
++ write_32_relocated (ptr, new_idx);
++ }
++ }
++}
++
+ static int
+ edit_dwarf2 (DSO *dso)
+ {
+@@ -2675,6 +2832,7 @@ edit_dwarf2 (DSO *dso)
+ if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+ {
+ do_read_16 = buf_read_ule16;
++ do_read_24 = buf_read_ule24;
+ do_read_32 = buf_read_ule32;
+ do_write_16 = dwarf2_write_le16;
+ do_write_32 = dwarf2_write_le32;
+@@ -2682,6 +2840,7 @@ edit_dwarf2 (DSO *dso)
+ else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
+ {
+ do_read_16 = buf_read_ube16;
++ do_read_24 = buf_read_ube24;
+ do_read_32 = buf_read_ube32;
+ do_write_16 = dwarf2_write_be16;
+ do_write_32 = dwarf2_write_be32;
+@@ -2997,6 +3156,15 @@ edit_dwarf2 (DSO *dso)
+ dirty_section (DEBUG_MACRO);
+ if (need_stmt_update || need_line_strp_update)
+ dirty_section (DEBUG_LINE);
++ if (need_strp_update && debug_sections[DEBUG_STR_OFFSETS].data != NULL)
++ {
++ setup_relbuf(dso, &debug_sections[DEBUG_STR_OFFSETS], &reltype);
++ rel_updated = false;
++ update_str_offsets (dso);
++ dirty_section (DEBUG_STR_OFFSETS);
++ if (rel_updated)
++ update_rela_data (dso, &debug_sections[DEBUG_STR_OFFSETS]);
++ }
+
+ /* Update any relocations addends we might have touched. */
+ if (info_rel_updated)
+--
+2.42.0
+
diff --git a/0001-tests-Handle-zero-directory-entry-in-.debug_line-DWA.patch b/0001-tests-Handle-zero-directory-entry-in-.debug_line-DWA.patch
new file mode 100644
index 0000000..2cadab2
--- /dev/null
+++ b/0001-tests-Handle-zero-directory-entry-in-.debug_line-DWA.patch
@@ -0,0 +1,130 @@
+From ae27211cbbfb63a0ad3c141cd1310d7f583ec40e Mon Sep 17 00:00:00 2001
+From: Mark Wielaard <mark@klomp.org>
+Date: Fri, 30 Jul 2021 18:09:46 +0200
+Subject: [PATCH] tests: Handle zero directory entry in .debug_line DWARF5
+ debugedit.at
+
+We were skipping the zero directory entry, because it was always
+the same as the directory entry at position one. But that isn't
+true anymore with gcc 11.2.1. There the zero dir entry is unique.
+Fix the debugedit.at .debug_line testcases using DWARF5 to also
+include dir entry zero.
+
+Signed-off-by: Mark Wielaard <mark@klomp.org>
+---
+ configure.ac | 14 ++++++++++++++
+ tests/atlocal.in | 1 +
+ tests/debugedit.at | 18 ++++++++++++------
+ 3 files changed, 27 insertions(+), 6 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index e5c9230..6a53365 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -87,6 +87,20 @@ CFLAGS="$save_CFLAGS"
+ GDWARF_5_FLAG=$ac_cv_gdwarf_5
+ AC_SUBST([GDWARF_5_FLAG])
+
++AC_CACHE_CHECK([whether -gdwarf-5 produced DWARF5 .debug_line], ac_cv_dwarf_5_debugline, [dnl
++save_CFLAGS="$CFLAGS"
++CFLAGS="-gdwarf-5"
++AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int i=0;]],[[/* empty main */]])],
++ [if readelf --debug-dump=line conftest.o 2>&1 | \
++ grep "DWARF Version:" 2>&1 | grep "5" > /dev/null 2>&1; \
++ then ac_cv_dwarf_5_debugline=yes; \
++ else ac_cv_dwarf_5_debugline=no; fi],
++ ac_cv_dwarf_5_debugline=no)
++CFLAGS="$save_CFLAGS"
++])
++DWARF_5_DEBUGLINE=$ac_cv_dwarf_5_debugline
++AC_SUBST([DWARF_5_DEBUGLINE])
++
+ AC_CACHE_CHECK([whether gcc supports -gz=none], ac_cv_gz_none, [dnl
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="-gz=none"
+diff --git a/tests/atlocal.in b/tests/atlocal.in
+index 8399f8d..d916301 100644
+--- a/tests/atlocal.in
++++ b/tests/atlocal.in
+@@ -13,3 +13,4 @@ READELF="@READELF@"
+
+ GDWARF_5_FLAG=@GDWARF_5_FLAG@
+ GZ_NONE_FLAG=@GZ_NONE_FLAG@
++DWARF_5_DEBUGLINE=@DWARF_5_DEBUGLINE@
+diff --git a/tests/debugedit.at b/tests/debugedit.at
+index 0311d26..725e68e 100644
+--- a/tests/debugedit.at
++++ b/tests/debugedit.at
+@@ -488,10 +488,12 @@ AT_CLEANUP
+ AT_SETUP([debugedit .debug_line objects DWARF5])
+ AT_KEYWORDS([debuginfo] [debugedit])
+ AT_SKIP_IF([test "$GDWARF_5_FLAG" = "no"])
++AT_SKIP_IF([test "$DWARF_5_DEBUGLINE" = "no"])
+ DEBUGEDIT_SETUP([-gdwarf-5])
+
+ AT_DATA([expout],
+ [foo/bar/baz
++foo/bar/baz/subdir_bar
+ foo/bar/baz/subdir_headers
+ ])
+
+@@ -500,8 +502,8 @@ AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./subdir_bar/bar.o]])
+ AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./baz.o]])
+ AT_CHECK([[
+ readelf --debug-dump=line foo.o subdir_bar/bar.o baz.o \
+- | grep -A5 "The Directory Table" | grep "^ [123]" \
+- | cut -f2- -d/ | grep ^foo/ | sort
++ | grep -A5 "The Directory Table" | grep "^ [0123]" \
++ | cut -f2- -d/ | grep ^foo/ | sort -u
+ ]],[0],[expout])
+
+ AT_CLEANUP
+@@ -535,18 +537,20 @@ AT_CLEANUP
+ AT_SETUP([debugedit .debug_line partial DWARF5])
+ AT_KEYWORDS([debuginfo] [debugedit])
+ AT_SKIP_IF([test "$GDWARF_5_FLAG" = "no"])
++AT_SKIP_IF([test "$DWARF_5_DEBUGLINE" = "no"])
+ DEBUGEDIT_SETUP([-gdwarf-5])
+
+ AT_DATA([expout],
+ [foo/bar/baz
++foo/bar/baz/subdir_bar
+ foo/bar/baz/subdir_headers
+ ])
+
+ AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./foobarbaz.part.o]])
+ AT_CHECK([[
+ readelf --debug-dump=line ./foobarbaz.part.o \
+- | grep -A5 "The Directory Table" | grep "^ [123]" \
+- | cut -f2- -d/ | grep ^foo/ | sort
++ | grep -A5 "The Directory Table" | grep "^ [0123]" \
++ | cut -f2- -d/ | grep ^foo/ | sort -u
+ ]],[0],[expout])
+
+ AT_CLEANUP
+@@ -580,18 +584,20 @@ AT_CLEANUP
+ AT_SETUP([debugedit .debug_line exe DWARF5])
+ AT_KEYWORDS([debuginfo] [debugedit])
+ AT_SKIP_IF([test "$GDWARF_5_FLAG" = "no"])
++AT_SKIP_IF([test "$DWARF_5_DEBUGLINE" = "no"])
+ DEBUGEDIT_SETUP([-gdwarf-5])
+
+ AT_DATA([expout],
+ [foo/bar/baz
++foo/bar/baz/subdir_bar
+ foo/bar/baz/subdir_headers
+ ])
+
+ AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./foobarbaz.exe]])
+ AT_CHECK([[
+ readelf --debug-dump=line ./foobarbaz.exe \
+- | grep -A5 "The Directory Table" | grep "^ [123]" \
+- | cut -f2- -d/ | grep ^foo/ | sort
++ | grep -A5 "The Directory Table" | grep "^ [0123]" \
++ | cut -f2- -d/ | grep ^foo/ | sort -u
+ ]],[0],[expout])
+
+ AT_CLEANUP
+--
+2.27.0
+
diff --git a/0002-scripts-find-debuginfo.in-Add-q-quiet.patch b/0002-scripts-find-debuginfo.in-Add-q-quiet.patch
new file mode 100644
index 0000000..e2b0552
--- /dev/null
+++ b/0002-scripts-find-debuginfo.in-Add-q-quiet.patch
@@ -0,0 +1,116 @@
+From b8ac71d9f88202f00a32c5a8b3b4b93bb2fa110a Mon Sep 17 00:00:00 2001
+From: Prarit Bhargava <prarit@redhat.com>
+Date: Thu, 26 Jan 2023 16:08:57 -0500
+Subject: [PATCH] scripts/find-debuginfo.in: Add -q|--quiet
+
+Projects with a large number of compiled files end up with a large number
+of 'extracting debug info from' messages in the build log. In the case of
+the Fedora kernel these messages account for 8504 lines in the log, or 61%
+of the entire log [1].
+
+Removing these lines make the log easier to view and comprehend for some
+projects, however, not all projects will want to silence these messages so
+suppressing them must be optional.
+
+Add a -q|--quiet which allows users to silence the non-error output from
+the script.
+
+[1] https://kojipkgs.fedoraproject.org//packages/kernel/6.2.0/0.rc5.20230123git2475bf0250de.38.fc38/data/logs/x86_64/build.log
+
+Signed-off-by: Prarit Bhargava <prarit@redhat.com>
+---
+ scripts/find-debuginfo.in | 22 +++++++++++++++-------
+ 1 file changed, 15 insertions(+), 7 deletions(-)
+
+diff --git a/scripts/find-debuginfo.in b/scripts/find-debuginfo.in
+index 8090c84..7dec3c3 100755
+--- a/scripts/find-debuginfo.in
++++ b/scripts/find-debuginfo.in
+@@ -26,7 +26,7 @@ Usage: find-debuginfo [OPTION]... [builddir]
+ automagically generates debug info and file lists
+
+ Options:
+-[--strict-build-id] [-g] [-r] [-m] [-i] [-n]
++[--strict-build-id] [-g] [-r] [-m] [-i] [-n] [-q]
+ [--keep-section SECTION] [--remove-section SECTION]
+ [--g-libs]
+ [-j N] [--jobs N]
+@@ -94,6 +94,8 @@ will be called /usr/debug/src/<BASE>. This makes sure the debug source
+ dirs are unique between package version, release and achitecture (Use
+ --unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}")
+
++The -q or --quiet flag silences non-error output from the script.
++
+ All file names in switches are relative to builddir ('.' if not given).
+ EOF
+ }
+@@ -146,6 +148,9 @@ n_jobs=1
+ # exit early on --version or --help
+ done=false
+
++# silence non-error output
++quiet=false
++
+ BUILDDIR=.
+ out=debugfiles.list
+ srcout=
+@@ -239,6 +244,9 @@ while [ $# -gt 0 ]; do
+ srcout=$2
+ shift
+ ;;
++ -q|--quiet)
++ quiet=true
++ ;;
+ --version)
+ echo "find-debuginfo @VERSION@"
+ done=true;
+@@ -437,7 +445,7 @@ do_file()
+ get_debugfn "$f"
+ [ -f "${debugfn}" ] && return
+
+- echo "extracting debug info from $f"
++ $quiet || echo "extracting debug info from $f"
+ # See also cpio SOURCEFILE copy. Directories must match up.
+ debug_base_name="$RPM_BUILD_DIR"
+ debug_dest_name="/usr/src/debug"
+@@ -513,7 +521,7 @@ do_file()
+ grep "^$inum " "$temp/linked" | while read inum linked; do
+ link=$debugfn
+ get_debugfn "$linked"
+- echo "hard linked $link to $debugfn"
++ $quiet || echo "hard linked $link to $debugfn"
+ mkdir -p "$(dirname "$debugfn")" && ln -nf "$link" "$debugfn"
+ done
+ fi
+@@ -576,7 +584,7 @@ if $run_dwz \
+ && [ -d "${RPM_BUILD_ROOT}/usr/lib/debug" ]; then
+ readarray dwz_files < <(cd "${RPM_BUILD_ROOT}/usr/lib/debug"; find -type f -name \*.debug | LC_ALL=C sort)
+ if [ ${#dwz_files[@]} -gt 0 ]; then
+- size_before=$(du -sk ${RPM_BUILD_ROOT}/usr/lib/debug | cut -f1)
++ $quiet || size_before=$(du -sk ${RPM_BUILD_ROOT}/usr/lib/debug | cut -f1)
+ dwz_multifile_name="${RPM_PACKAGE_NAME}-${RPM_PACKAGE_VERSION}-${RPM_PACKAGE_RELEASE}.${RPM_ARCH}"
+ dwz_multifile_suffix=
+ dwz_multifile_idx=0
+@@ -600,8 +608,8 @@ if $run_dwz \
+ echo >&2 "*** ERROR: DWARF compression requested, but no dwz installed"
+ exit 2
+ fi
+- size_after=$(du -sk ${RPM_BUILD_ROOT}/usr/lib/debug | cut -f1)
+- echo "original debug info size: ${size_before}kB, size after compression: ${size_after}kB"
++ $quiet || size_after=$(du -sk ${RPM_BUILD_ROOT}/usr/lib/debug | cut -f1)
++ $quiet || echo "original debug info size: ${size_before}kB, size after compression: ${size_after}kB"
+ # Remove .dwz directory if empty
+ rmdir "${RPM_BUILD_ROOT}/usr/lib/debug/.dwz" 2>/dev/null
+
+@@ -621,7 +629,7 @@ do
+ f=${f#$RPM_BUILD_ROOT}
+ t=${t#$RPM_BUILD_ROOT}
+ if [ -f "$debugdir$t" ]; then
+- echo "symlinked /usr/lib/debug$t to /usr/lib/debug${f}.debug"
++ $quiet || echo "symlinked /usr/lib/debug$t to /usr/lib/debug${f}.debug"
+ debug_link "/usr/lib/debug$t" "${f}.debug"
+ fi
+ done
+--
+2.39.1
+
diff --git a/debugedit.spec b/debugedit.spec
new file mode 100644
index 0000000..c6b26a1
--- /dev/null
+++ b/debugedit.spec
@@ -0,0 +1,122 @@
+Name: debugedit
+Version: 5.0
+Release: 5%{?dist}
+Summary: Tools for debuginfo creation
+License: GPLv3+ and GPLv2+ and LGPLv2+
+URL: https://sourceware.org/debugedit/
+Source0: https://sourceware.org/pub/debugedit/%{version}/%{name}-%{version}.tar.xz
+Source1: https://sourceware.org/pub/debugedit/%{version}/%{name}-%{version}.tar.xz.sig
+Source2: gpgkey-5C1D1AA44BE649DE760A.gpg
+
+BuildRequires: make gcc
+BuildRequires: pkgconfig(libelf)
+BuildRequires: pkgconfig(libdw)
+BuildRequires: help2man
+BuildRequires: gnupg2
+
+# For the testsuite.
+BuildRequires: autoconf
+BuildRequires: automake
+
+# The find-debuginfo.sh script has a couple of tools it needs at runtime.
+# For strip_to_debug, eu-strip
+Requires: elfutils
+# For add_minidebug, readelf, awk, nm, sort, comm, objcopy, xz
+Requires: binutils, gawk, coreutils, xz
+# For find and xargs
+Requires: findutils
+# For do_file, gdb_add_index
+# We only need gdb-add-index, so suggest gdb-minimal (full gdb is also ok)
+Requires: /usr/bin/gdb-add-index
+Suggests: gdb-minimal
+# For run_job, sed
+Requires: sed
+# For dwz
+Requires: dwz
+# For append_uniq, grep
+Requires: grep
+
+%global _hardened_build 1
+
+Patch1: 0001-tests-Handle-zero-directory-entry-in-.debug_line-DWA.patch
+Patch2: 0002-scripts-find-debuginfo.in-Add-q-quiet.patch
+Patch3: 0001-debugedit-Add-support-for-.debug_str_offsets-DW_FORM.patch
+
+%description
+The debugedit project provides programs and scripts for creating
+debuginfo and source file distributions, collect build-ids and rewrite
+source paths in DWARF data for debugging, tracing and profiling.
+
+It is based on code originally from the rpm project plus libiberty and
+binutils. It depends on the elfutils libelf and libdw libraries to
+read and write ELF files, DWARF data and build-ids.
+
+%prep
+%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}'
+%autosetup -p1
+
+%build
+autoreconf -f -v -i
+%configure
+%make_build
+
+%install
+%make_install
+# Temp symlink to make sure things don't break.
+cd %{buildroot}%{_bindir}
+ln -s find-debuginfo find-debuginfo.sh
+
+%check
+# The testsuite should be zero fail.
+# It uses its own CFLAGS and LDFLAGS settings.
+sed -i 's/^\(C\|LD\)FLAGS=.*/\1FLAGS=""/' tests/atlocal
+make check %{?_smp_mflags}
+
+%files
+%license COPYING COPYING3 COPYING.LIB
+%doc README
+%{_bindir}/debugedit
+%{_bindir}/sepdebugcrcfix
+%{_bindir}/find-debuginfo
+%{_bindir}/find-debuginfo.sh
+%{_mandir}/man1/debugedit.1*
+%{_mandir}/man1/sepdebugcrcfix.1*
+%{_mandir}/man1/find-debuginfo.1*
+
+%changelog
+* Mon Dec 4 2023 Mark Wielaard <mjw@redhat.com> - 5.0-5
+- Add 0001-debugedit-Add-support-for-.debug_str_offsets-DW_FORM.patch
+
+* Tue Mar 28 2023 Mark Wielaard <mjw@redhat.com> - 5.0-4
+- Add 0002-scripts-find-debuginfo.in-Add-q-quiet.patch
+
+* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 5.0-3
+- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
+ Related: rhbz#1991688
+
+* Tue Aug 3 2021 Mark Wielaard <mjw@redhat.com> - 5.0-2
+- Add testsuite fix for GCC 11.2.1
+
+* Mon Jul 26 2021 Mark Wielaard <mjw@redhat.com> - 5.0-1
+- Upgrade to upstream 5.0 release.
+ - Removes find-debuginfo .sh suffix.
+ - This release still has a find-debuginfo.sh -> find-debuginfo symlink.
+
+* Wed May 5 2021 Mark Wielaard <mjw@fedoraproject.org> - 0.2-1
+- Update to upstream 0.2 pre-release. Adds documentation.
+
+* Wed Apr 28 2021 Mark Wielaard <mjw@fedoraproject.org> - 0.1-5
+- Add dist to Release. Use file dependency for /usr/bin/gdb-add-index.
+
+* Tue Apr 27 2021 Mark Wielaard <mjw@fedoraproject.org> - 0.1-4
+- Use numbered Sources and https.
+
+* Mon Apr 26 2021 Mark Wielaard <mjw@fedoraproject.org> - 0.1-3
+- Fix some rpmlint issues, add comments, add license and doc,
+ gpg verification, use pkgconfig BuildRequires, enable _hardened_build
+
+* Mon Mar 29 2021 Panu Matilainen <pmatilai@redhat.com>
+- Add pile of missing runtime utility dependencies
+
+* Tue Mar 23 2021 Panu Matilainen <pmatilai@redhat.com>
+- Initial packaging
diff --git a/sources b/sources
new file mode 100644
index 0000000..7c968c3
--- /dev/null
+++ b/sources
@@ -0,0 +1,3 @@
+9961a1ae59b6417d27e3a646dc4078b7 debugedit-5.0.tar.xz
+ee1b9dbb7e2f498a0f741d86cf4adc03 debugedit-5.0.tar.xz.sig
+bc2b09bf0ae220273d72e2d96039c347 gpgkey-5C1D1AA44BE649DE760A.gpg