@@ -1,3 +1,12 @@
+2021-11-08 Mark Wielaard <mark@klomp.org>
+
+ * dwarf_begin_elf.c (scn_dwarf_type): New function.
+ (check_section): Check result->type.
+ (global_read): First check type.
+ (scngrp_read): Likewise.
+ * libdw/libdwP.h (enum dwarf_type): New enumeration.
+ (struct Dwarf): New field type.
+
2021-10-18 Mark Wielaard <mark@klomp.org>
* dwarf_aggregate_size.c (get_type): Don't pass NULL to
@@ -72,6 +72,31 @@ static const char dwarf_scnnames[IDX_last][19] =
};
#define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
+static enum dwarf_type
+scn_dwarf_type (Dwarf *result, size_t shstrndx, Elf_Scn *scn)
+{
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr == NULL)
+ return TYPE_UNKNOWN;
+
+ const char *scnname = elf_strptr (result->elf, shstrndx,
+ shdr->sh_name);
+ if (scnname != NULL)
+ {
+ if (startswith (scnname, ".gnu.debuglto_.debug"))
+ return TYPE_GNU_LTO;
+ else if (startswith (scnname, ".debug_") || startswith (scnname, ".zdebug_"))
+ {
+ size_t len = strlen (scnname);
+ if (strcmp (scnname + len - 4, ".dwo") == 0)
+ return TYPE_DWO;
+ else
+ return TYPE_PLAIN;
+ }
+ }
+ return TYPE_UNKNOWN;
+}
static Dwarf *
check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
{
@@ -116,7 +141,11 @@ check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
return NULL;
}
- /* Recognize the various sections. Most names start with .debug_. */
+ /* Recognize the various sections. Most names start with .debug_.
+ They might be compressed (and start with .z). Or end with .dwo
+ for split dwarf sections. Or start with .gnu.debuglto_ for
+ LTO debug sections. We should only use one consistent set at
+ a time. We prefer PLAIN over DWO over LTO. */
size_t cnt;
bool gnu_compressed = false;
for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
@@ -127,7 +156,15 @@ check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
&& (dbglen == scnlen
|| (scnlen == dbglen + 4
&& strstr (scnname, ".dwo") == scnname + dbglen)))
- break;
+ {
+ if (dbglen == scnlen)
+ {
+ if (result->type == TYPE_PLAIN)
+ break;
+ }
+ else if (result->type == TYPE_DWO)
+ break;
+ }
else if (scnname[0] == '.' && scnname[1] == 'z'
&& (strncmp (&scnname[2], &dwarf_scnnames[cnt][1],
dbglen - 1) == 0
@@ -136,13 +173,27 @@ check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
&& strstr (scnname,
".dwo") == scnname + dbglen + 1))))
{
- gnu_compressed = true;
- break;
+ if (scnlen == dbglen + 1)
+ {
+ if (result->type == TYPE_PLAIN)
+ {
+ gnu_compressed = true;
+ break;
+ }
+ }
+ else if (result->type <= TYPE_DWO)
+ {
+ gnu_compressed = true;
+ break;
+ }
}
else if (scnlen > 14 /* .gnu.debuglto_ prefix. */
&& startswith (scnname, ".gnu.debuglto_")
&& strcmp (&scnname[14], dwarf_scnnames[cnt]) == 0)
- break;
+ {
+ if (result->type == TYPE_GNU_LTO)
+ break;
+ }
}
if (cnt >= ndwarf_scnnames)
@@ -344,6 +395,16 @@ global_read (Dwarf *result, Elf *elf, size_t shstrndx)
{
Elf_Scn *scn = NULL;
+ /* First check the type (PLAIN, DWO, LTO) we are looking for. We
+ prefer PLAIN if available over DWO, over LTO. */
+ while ((scn = elf_nextscn (elf, scn)) != NULL && result->type != TYPE_PLAIN)
+ {
+ enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn);
+ if (type > result->type)
+ result->type = type;
+ }
+
+ scn = NULL;
while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
result = check_section (result, shstrndx, scn, false);
@@ -388,6 +449,9 @@ scngrp_read (Dwarf *result, Elf *elf, size_t shstrndx, Elf_Scn *scngrp)
represent section indices. The first word is a flag word. */
Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
size_t cnt;
+
+ /* First check the type (PLAIN, DWO, LTO) we are looking for. We
+ prefer PLAIN if available over DWO, over LTO. */
for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
{
Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
@@ -401,6 +465,15 @@ scngrp_read (Dwarf *result, Elf *elf, size_t shstrndx, Elf_Scn *scngrp)
return NULL;
}
+ enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn);
+ if (type > result->type)
+ result->type = type;
+ }
+
+ for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size && result != NULL; ++cnt)
+ {
+ Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
+ assert (scn != NULL); // checked above
result = check_section (result, shstrndx, scn, true);
if (result == NULL)
break;
@@ -145,6 +145,16 @@ enum
#include "dwarf_sig8_hash.h"
+/* The type of Dwarf object, sorted by preference
+ (if there is a higher order type, we pick that one over the others). */
+enum dwarf_type
+ {
+ TYPE_UNKNOWN = 0,
+ TYPE_GNU_LTO = 16,
+ TYPE_DWO = 32,
+ TYPE_PLAIN = 64,
+ };
+
/* This is the structure representing the debugging state. */
struct Dwarf
{
@@ -216,6 +226,8 @@ struct Dwarf
/* Similar for addrx/constx, which will come from .debug_addr section. */
struct Dwarf_CU *fake_addr_cu;
+ enum dwarf_type type;
+
/* Supporting lock for internal memory handling. Ensures threads that have
an entry in the mem_tails array are not disturbed by new threads doing
allocations for this Dwarf. */
@@ -1,3 +1,11 @@
+2021-11-08 Mark Wielaard <mark@klomp.org>
+
+ * Makefile.am (TESTS): Add run-readelf-fat-lto.sh.
+ (EXTRA_DIST): Add run-readelf-fat-lto.sh and
+ testfile-dwarf5-fat-lto.o.bz2.
+ * run-readelf-fat-lto.sh: New test.
+ * testfile-dwarf5-fat-lto.o.bz2: New test file.
+
2021-11-04 Frank Ch. Eigler <fche@redhat.com>
PR28514
@@ -139,7 +139,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \
run-low_high_pc.sh run-macro-test.sh run-elf_cntl_gelf_getshdr.sh \
run-test-archive64.sh run-readelf-vmcoreinfo.sh \
run-readelf-mixed-corenote.sh run-dwfllines.sh \
- run-readelf-variant.sh \
+ run-readelf-variant.sh run-readelf-fat-lto.sh \
run-dwfl-report-elf-align.sh run-addr2line-test.sh \
run-addr2line-i-test.sh run-addr2line-i-lex-test.sh \
run-addr2line-i-demangle-test.sh run-addr2line-alt-debugpath.sh \
@@ -379,6 +379,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
testfilebazminppc64.bz2 testfilebazminppc64_pl.bz2 \
testfilebazminppc64_plr.bz2 testfilebaztabppc64.bz2 \
run-readelf-variant.sh testfile-ada-variant.bz2 \
+ run-readelf-fat-lto.sh testfile-dwarf5-fat-lto.o.bz2 \
run-dwflsyms.sh \
run-unstrip-n.sh testcore-rtlib.bz2 testcore-rtlib-ppc.bz2 \
run-low_high_pc.sh testfile_low_high_pc.bz2 \
new file mode 100755
@@ -0,0 +1,53 @@
+. $srcdir/test-subr.sh
+
+# - s.c
+# int main_argc_remaining;
+#
+# int main_argc() {
+# int result = 0;
+# if (main_argc_remaining)
+# result = 0;
+#
+# return 0;
+# }
+#
+# gcc -gdwarf-5 -c -o testfile-dwarf5-fat-lto.o -flto -O s.c -g -ffat-lto-objects
+
+testfiles testfile-dwarf5-fat-lto.o
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc --debug-dump=ranges -N -U testfile-dwarf5-fat-lto.o << EOF
+
+DWARF section [26] '.debug_loclists' at offset 0x7db:
+Table at Offset 0x0:
+
+ Length: 24
+ DWARF version: 5
+ Address size: 8
+ Segment size: 0
+ Offset entries: 0
+ CU [ c] base: 000000000000000000
+
+ Offset: c, Index: 0
+ view pair 2, 3
+
+ Offset: e, Index: 2
+ start_length 0x0, 0
+ [ 0] lit0
+ [ 1] stack_value
+ end_of_list
+
+
+DWARF section [30] '.debug_rnglists' at offset 0x827:
+Table at Offset 0x0:
+
+ Length: 19
+ DWARF version: 5
+ Address size: 8
+ Segment size: 0
+ Offset entries: 0
+ CU [ c] base: 000000000000000000
+
+ Offset: c, Index: 0
+ start_length 0x0, 8
+ end_of_list
+
+EOF
new file mode 100644