else if (strcmp (arg, "pubnames") == 0)
print_debug_sections |= section_pubnames;
else if (strcmp (arg, "str") == 0)
- print_debug_sections |= section_str;
+ {
+ print_debug_sections |= section_str;
+ /* For mapping string offset tables to CUs. */
+ implicit_debug_sections |= section_info;
+ }
else if (strcmp (arg, "macinfo") == 0)
print_debug_sections |= section_macinfo;
else if (strcmp (arg, "macro") == 0)
static struct listptr_table known_rangelistptr;
static struct listptr_table known_rnglistptr;
static struct listptr_table known_addrbases;
+static struct listptr_table known_stroffbases;
static void
reset_listptr (struct listptr_table *table)
}
return DWARF_CB_OK;
+ case DW_AT_str_offsets_base:
+ {
+ bool stroffbase = notice_listptr (section_str, &known_stroffbases,
+ cbargs->addrsize,
+ cbargs->offset_size,
+ cbargs->cu, num, attr);
+ if (!cbargs->silent)
+ printf (" %*s%-20s (%s) str offsets base [%6"
+ PRIxMAX "]%s\n",
+ (int) (level * 2), "", dwarf_attr_name (attr),
+ dwarf_form_name (form), (uintmax_t) num,
+ stroffbase ? "" : " <WARNING offset too big>");
+ }
+ return DWARF_CB_OK;
+
case DW_AT_language:
valuestr = dwarf_lang_name (num);
break;
}
}
+static void
+print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+ Ebl *ebl, GElf_Ehdr *ehdr,
+ Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+ printf (gettext ("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+ elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ (uint64_t) shdr->sh_offset);
+
+ if (shdr->sh_size == 0)
+ return;
+
+ /* We like to get the section from libdw to make sure they are relocated. */
+ Elf_Data *data = (dbg->sectiondata[IDX_debug_str_offsets]
+ ?: elf_rawdata (scn, NULL));
+ if (unlikely (data == NULL))
+ {
+ error (0, 0, gettext ("cannot get .debug_str_offsets section data: %s"),
+ elf_errmsg (-1));
+ return;
+ }
+
+ size_t idx = 0;
+ sort_listptr (&known_stroffbases, "str_offsets");
+
+ const unsigned char *start = (const unsigned char *) data->d_buf;
+ const unsigned char *readp = start;
+ const unsigned char *readendp = ((const unsigned char *) data->d_buf
+ + data->d_size);
+
+ while (readp < readendp)
+ {
+ /* Most string offset tables will have a header. For split
+ dwarf unit GNU DebugFission didn't add one. But they were
+ also only defined for split units (main or skeleton units
+ didn't have indirect strings). So if we don't have a
+ DW_AT_str_offsets_base at all and this is offset zero, then
+ just start printing offsets immediately, if this is a .dwo
+ section. */
+ Dwarf_Off off = (Dwarf_Off) (readp
+ - (const unsigned char *) data->d_buf);
+
+ printf ("Table at offset %" PRIx64 " ", off);
+
+ struct listptr *listptr = get_listptr (&known_stroffbases, idx++);
+ const unsigned char *next_unitp = readendp;
+ uint8_t offset_size;
+ bool has_header;
+ if (listptr == NULL)
+ {
+ /* This can happen for .dwo files. There is only an header
+ in the case this is a version 5 split DWARF file. */
+ Dwarf_CU *cu;
+ uint8_t unit_type;
+ if (dwarf_get_units (dbg, NULL, &cu, NULL, &unit_type,
+ NULL, NULL) != 0)
+ {
+ error (0, 0, "Warning: Cannot find any DWARF unit.");
+ /* Just guess some values. */
+ has_header = false;
+ offset_size = 4;
+ }
+ else if (off == 0
+ && (unit_type == DW_UT_split_type
+ || unit_type == DW_UT_split_compile))
+ {
+ has_header = cu->version > 4;
+ offset_size = cu->offset_size;
+ }
+ else
+ {
+ error (0, 0,
+ "Warning: No CU references .debug_str_offsets after %"
+ PRIx64, off);
+ has_header = cu->version > 4;
+ offset_size = cu->offset_size;
+ }
+ printf ("\n");
+ }
+ else
+ {
+ /* This must be DWARF5, since GNU DebugFission didn't define
+ DW_AT_str_offsets_base. */
+ has_header = true;
+
+ Dwarf_Die cudie;
+ if (dwarf_cu_die (listptr->cu, &cudie,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL) == NULL)
+ printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
+ else
+ printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
+ }
+
+ if (has_header)
+ {
+ uint64_t unit_length;
+ uint16_t version;
+ uint16_t padding;
+
+ unit_length = read_4ubyte_unaligned_inc (dbg, readp);
+ if (unlikely (unit_length == 0xffffffff))
+ {
+ if (unlikely (readp > readendp - 8))
+ {
+ invalid_data:
+ error (0, 0, "Invalid data");
+ return;
+ }
+ unit_length = read_8ubyte_unaligned_inc (dbg, readp);
+ offset_size = 8;
+ }
+ else
+ offset_size = 4;
+
+ printf ("\n");
+ printf (gettext (" Length: %8" PRIu64 "\n"),
+ unit_length);
+ printf (gettext (" Offset size: %8" PRIu8 "\n"),
+ offset_size);
+
+ /* We need at least 2-bytes (version) + 2-bytes (padding) =
+ 4 bytes to complete the header. And this unit cannot go
+ beyond the section data. */
+ if (readp > readendp - 4
+ || unit_length < 4
+ || unit_length > (uint64_t) (readendp - readp))
+ goto invalid_data;
+
+ next_unitp = readp + unit_length;
+
+ version = read_2ubyte_unaligned_inc (dbg, readp);
+ printf (gettext (" DWARF version: %8" PRIu16 "\n"), version);
+
+ if (version != 5)
+ {
+ error (0, 0, gettext ("Unknown version"));
+ goto next_unit;
+ }
+
+ padding = read_2ubyte_unaligned_inc (dbg, readp);
+ printf (gettext (" Padding: %8" PRIx16 "\n"), padding);
+
+ if (listptr != NULL
+ && listptr->offset != (Dwarf_Off) (readp - start))
+ {
+ error (0, 0, "String offsets index doesn't start after header");
+ goto next_unit;
+ }
+
+ printf ("\n");
+ }
+
+ int digits = 1;
+ size_t offsets = (next_unitp - readp) / offset_size;
+ while (offsets >= 10)
+ {
+ ++digits;
+ offsets /= 10;
+ }
+
+ unsigned int index = 0;
+ size_t index_offset = readp - (const unsigned char *) data->d_buf;
+ printf (" Offsets start at 0x%zx:\n", index_offset);
+ while (readp <= next_unitp - offset_size)
+ {
+ Dwarf_Word offset;
+ if (offset_size == 4)
+ offset = read_4ubyte_unaligned_inc (dbg, readp);
+ else
+ offset = read_8ubyte_unaligned_inc (dbg, readp);
+ const char *str = dwarf_getstring (dbg, offset, NULL);
+ printf (" [%*u] [%*" PRIx64 "] \"%s\"\n",
+ digits, index++, (int) offset_size * 2, offset, str ?: "???");
+ }
+ printf ("\n");
+
+ if (readp != next_unitp)
+ error (0, 0, "extra %zd bytes at end of unit",
+ (size_t) (next_unitp - readp));
+
+ next_unit:
+ readp = next_unitp;
+ }
+}
+
/* Print the content of the call frame search table section
'.eh_frame_hdr'. */
/* A DWARF5 specialised debug string section. */
{ ".debug_line_str", section_str,
print_debug_str_section },
+ /* DWARF5 string offsets table. */
+ { ".debug_str_offsets", section_str,
+ print_debug_str_offsets_section },
NEW_SECTION (macinfo),
NEW_SECTION (macro),
NEW_SECTION (ranges),
reset_listptr (&known_rangelistptr);
reset_listptr (&known_rnglistptr);
reset_listptr (&known_addrbases);
+ reset_listptr (&known_stroffbases);
}
--- /dev/null
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See tests/testfile-dwarf-45.source
+testfiles testfile-splitdwarf-4 testfile-splitdwarf-5
+testfiles testfile-hello4.dwo testfile-hello5.dwo
+testfiles testfile-world4.dwo testfile-world5.dwo
+
+# DWARF4 GNU DebugFission No real table header.
+# We don't really need the skeleton, but we don't want any Warnings.
+testrun_compare ${abs_top_builddir}/src/readelf --dwarf-skeleton testfile-splitdwarf-4 --debug-dump=str testfile-hello4.dwo testfile-world4.dwo<<\EOF
+
+testfile-hello4.dwo:
+
+
+DWARF section [ 5] '.debug_str_offsets.dwo' at offset 0x335:
+Table at offset 0
+ Offsets start at 0x0:
+ [ 0] [ 0] "long long int"
+ [ 1] [ e] "frob"
+ [ 2] [ 13] "long unsigned int"
+ [ 3] [ 25] "/home/mark/src/elfutils/tests"
+ [ 4] [ 43] "wchar_t"
+ [ 5] [ 4b] "main"
+ [ 6] [ 50] "long int"
+ [ 7] [ 59] "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-4 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [ 8] [ e9] "long double"
+ [ 9] [ f5] "hello.c"
+
+
+DWARF section [ 6] '.debug_str.dwo' at offset 0x35d:
+ Offset String
+ [ 0] "long long int"
+ [ e] "frob"
+ [ 13] "long unsigned int"
+ [ 25] "/home/mark/src/elfutils/tests"
+ [ 43] "wchar_t"
+ [ 4b] "main"
+ [ 50] "long int"
+ [ 59] "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-4 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [ e9] "long double"
+ [ f5] "hello.c"
+
+testfile-world4.dwo:
+
+
+DWARF section [ 5] '.debug_str_offsets.dwo' at offset 0x2e7:
+Table at offset 0
+ Offsets start at 0x0:
+ [ 0] [ 0] "long long unsigned int"
+ [ 1] [ 17] "/home/mark/src/elfutils/tests"
+ [ 2] [ 35] "long long int"
+ [ 3] [ 43] "signed char"
+ [ 4] [ 4f] "long int"
+ [ 5] [ 58] "world.c"
+ [ 6] [ 60] "unsigned int"
+ [ 7] [ 6d] "long unsigned int"
+ [ 8] [ 7f] "short unsigned int"
+ [ 9] [ 92] "frob"
+ [10] [ 97] "calc"
+ [11] [ 9c] "unsigned char"
+ [12] [ aa] "short int"
+ [13] [ b4] "exit"
+ [14] [ b9] "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-4 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [15] [ 149] "char"
+ [16] [ 14e] "word"
+ [17] [ 153] "argv"
+ [18] [ 158] "argc"
+ [19] [ 15d] "main"
+
+
+DWARF section [ 6] '.debug_str.dwo' at offset 0x337:
+ Offset String
+ [ 0] "long long unsigned int"
+ [ 17] "/home/mark/src/elfutils/tests"
+ [ 35] "long long int"
+ [ 43] "signed char"
+ [ 4f] "long int"
+ [ 58] "world.c"
+ [ 60] "unsigned int"
+ [ 6d] "long unsigned int"
+ [ 7f] "short unsigned int"
+ [ 92] "frob"
+ [ 97] "calc"
+ [ 9c] "unsigned char"
+ [ aa] "short int"
+ [ b4] "exit"
+ [ b9] "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-4 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [ 149] "char"
+ [ 14e] "word"
+ [ 153] "argv"
+ [ 158] "argc"
+ [ 15d] "main"
+EOF
+
+# DWARF5 Real table header.
+# We don't really need the skeleton, but we don't want any Warnings.
+testrun_compare ${abs_top_builddir}/src/readelf --dwarf-skeleton testfile-splitdwarf-5 --debug-dump=str testfile-hello5.dwo testfile-world5.dwo<<\EOF
+
+testfile-hello5.dwo:
+
+
+DWARF section [ 5] '.debug_str_offsets.dwo' at offset 0x353:
+Table at offset 0
+
+ Length: 44
+ Offset size: 4
+ DWARF version: 5
+ Padding: 0
+
+ Offsets start at 0x8:
+ [ 0] [ 0] "long long int"
+ [ 1] [ e] "frob"
+ [ 2] [ 13] "long unsigned int"
+ [ 3] [ 25] "/home/mark/src/elfutils/tests"
+ [ 4] [ 43] "wchar_t"
+ [ 5] [ 4b] "main"
+ [ 6] [ 50] "long int"
+ [ 7] [ 59] "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-5 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [ 8] [ e9] "long double"
+ [ 9] [ f5] "hello.c"
+
+
+DWARF section [ 6] '.debug_str.dwo' at offset 0x383:
+ Offset String
+ [ 0] "long long int"
+ [ e] "frob"
+ [ 13] "long unsigned int"
+ [ 25] "/home/mark/src/elfutils/tests"
+ [ 43] "wchar_t"
+ [ 4b] "main"
+ [ 50] "long int"
+ [ 59] "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-5 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [ e9] "long double"
+ [ f5] "hello.c"
+
+testfile-world5.dwo:
+
+
+DWARF section [ 5] '.debug_str_offsets.dwo' at offset 0x313:
+Table at offset 0
+
+ Length: 84
+ Offset size: 4
+ DWARF version: 5
+ Padding: 0
+
+ Offsets start at 0x8:
+ [ 0] [ 0] "long long unsigned int"
+ [ 1] [ 17] "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-5 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [ 2] [ a7] "/home/mark/src/elfutils/tests"
+ [ 3] [ c5] "long long int"
+ [ 4] [ d3] "signed char"
+ [ 5] [ df] "long int"
+ [ 6] [ e8] "world.c"
+ [ 7] [ f0] "unsigned int"
+ [ 8] [ fd] "long unsigned int"
+ [ 9] [ 10f] "short unsigned int"
+ [10] [ 122] "frob"
+ [11] [ 127] "calc"
+ [12] [ 12c] "unsigned char"
+ [13] [ 13a] "short int"
+ [14] [ 144] "exit"
+ [15] [ 149] "char"
+ [16] [ 14e] "word"
+ [17] [ 153] "argv"
+ [18] [ 158] "argc"
+ [19] [ 15d] "main"
+
+
+DWARF section [ 6] '.debug_str.dwo' at offset 0x36b:
+ Offset String
+ [ 0] "long long unsigned int"
+ [ 17] "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-5 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [ a7] "/home/mark/src/elfutils/tests"
+ [ c5] "long long int"
+ [ d3] "signed char"
+ [ df] "long int"
+ [ e8] "world.c"
+ [ f0] "unsigned int"
+ [ fd] "long unsigned int"
+ [ 10f] "short unsigned int"
+ [ 122] "frob"
+ [ 127] "calc"
+ [ 12c] "unsigned char"
+ [ 13a] "short int"
+ [ 144] "exit"
+ [ 149] "char"
+ [ 14e] "word"
+ [ 153] "argv"
+ [ 158] "argc"
+ [ 15d] "main"
+EOF
+
+exit 0