From: Mark Wielaard <mark@klomp.org>
To: elfutils-devel@sourceware.org
Cc: "Martin Liška" <mliska@suse.cz>, "Mark Wielaard" <mark@klomp.org>
Subject: [PATCH] readelf: Check compression status of .debug section data
Date: Tue, 10 Jan 2023 18:44:57 +0100 [thread overview]
Message-ID: <20230110174457.524148-1-mark@klomp.org> (raw)
In-Reply-To: <d689ae1b-8cd2-c8d2-3756-4de593bb1e55@suse.cz>
The various print_debug_*_section functions didn't get the section
data in the same way. Add a new get_debug_elf_data function that
gets the (possibly relocated) section data and that checks (and
warns) if the data might still be compressed in a way that we
cannot decompress.
Signed-off-by: Mark Wielaard <mark@klomp.org>
---
src/ChangeLog | 19 +++++
src/readelf.c | 213 ++++++++++++++++++++++++++------------------------
2 files changed, 130 insertions(+), 102 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index db8a81ee..0490088e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,22 @@
+2023-01-10 Mark Wielaard <mark@klomp.org>
+
+ * readelf.c (get_debug_elf_data): New function.
+ (print_debug_abbrev_section): Use get_debug_elf_data.
+ (print_debug_addr_section): Likewise.
+ (print_debug_aranges_section): Likewise.
+ (print_debug_rnglists_section): Likewise.
+ (print_debug_ranges_section): Likewise.
+ (print_debug_frame_section): Likewise.
+ (print_debug_units): Likewise.
+ (print_debug_line_section): Likewise.
+ (print_debug_loclists_section): Likewise.
+ (print_debug_loc_section): Likewise.
+ (print_debug_macinfo_section): Likewise.
+ (print_debug_macro_section): Likewise.
+ (print_debug_str_section): Likewise.
+ (print_debug_str_offsets_section): Likewise.
+ (print_debug_pubnames_section): Likewise.
+
2022-12-21 Shahab Vahedi <shahab@synopsys.email>
* elflint.c (valid_e_machine): Add EM_ARCV2.
diff --git a/src/readelf.c b/src/readelf.c
index 451f8400..51b0e8b9 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3857,6 +3857,39 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
}
}
+/* Returns either the (relocated) data from the Dwarf, or tries to get
+ the "raw" (uncompressed) data from the Elf section. Produces a
+ warning if the data cannot be found (or decompressed). */
+static Elf_Data *
+get_debug_elf_data (Dwarf *dbg, Ebl *ebl, int idx, Elf_Scn *scn)
+{
+ /* We prefer to get the section data from the Dwarf because that
+ might have been relocated already. Note this is subtly wrong if
+ there are multiple sections with the same .debug name. */
+ if (dbg->sectiondata[idx] != NULL)
+ return dbg->sectiondata[idx];
+
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr != NULL && (shdr->sh_flags & SHF_COMPRESSED) != 0)
+ {
+ if (elf_compress (scn, 0, 0) < 0)
+ {
+ error (0, 0, "%s [%zd] '%s'\n",
+ _("Couldn't uncompress section"),
+ elf_ndxscn (scn), section_name (ebl, shdr));
+ return NULL;
+ }
+ }
+
+ Elf_Data *data = elf_getdata (scn, NULL);
+ if (data == NULL)
+ error (0, 0, "%s [%zd] '%s': %s\n",
+ _("Couldn't get data from section"),
+ elf_ndxscn (scn), section_name (ebl, shdr), elf_errmsg (-1));
+
+ return elf_getdata (scn, NULL);
+}
void
print_dwarf_addr (Dwfl_Module *dwflmod,
@@ -5271,8 +5304,11 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
- const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ?
- dbg->sectiondata[IDX_debug_abbrev]->d_size : 0);
+ Elf_Data *elf_data = get_debug_elf_data (dbg, ebl, IDX_debug_abbrev, scn);
+ if (elf_data == NULL)
+ return;
+
+ const size_t sh_size = elf_data->d_size;
printf (_("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
" [ Code]\n"),
@@ -5344,6 +5380,10 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Ebl *ebl, GElf_Ehdr *ehdr,
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
+ Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_addr, scn);
+ if (data == NULL)
+ return;
+
printf (_("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
elf_ndxscn (scn), section_name (ebl, shdr),
@@ -5352,16 +5392,6 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
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_addr]
- ?: elf_rawdata (scn, NULL));
- if (unlikely (data == NULL))
- {
- error (0, 0, _("cannot get .debug_addr section data: %s"),
- elf_errmsg (-1));
- return;
- }
-
size_t idx = 0;
sort_listptr (&known_addrbases, "addr_base");
@@ -5643,15 +5673,9 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
return;
}
- Elf_Data *data = (dbg->sectiondata[IDX_debug_aranges]
- ?: elf_rawdata (scn, NULL));
-
- if (unlikely (data == NULL))
- {
- error (0, 0, _("cannot get .debug_aranges content: %s"),
- elf_errmsg (-1));
- return;
- }
+ Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_aranges, scn);
+ if (data == NULL)
+ return;
printf (_("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
@@ -5820,20 +5844,15 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
Elf_Scn *scn, GElf_Shdr *shdr,
Dwarf *dbg __attribute__((unused)))
{
+ Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_rnglists, scn);
+ if (data == NULL)
+ return;
+
printf (_("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
- Elf_Data *data =(dbg->sectiondata[IDX_debug_rnglists]
- ?: elf_rawdata (scn, NULL));
- if (unlikely (data == NULL))
- {
- error (0, 0, _("cannot get .debug_rnglists content: %s"),
- elf_errmsg (-1));
- return;
- }
-
/* For the listptr to get the base address/CU. */
sort_listptr (&known_rnglistptr, "rnglistptr");
size_t listptr_idx = 0;
@@ -6196,14 +6215,9 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
Elf_Scn *scn, GElf_Shdr *shdr,
Dwarf *dbg)
{
- Elf_Data *data = (dbg->sectiondata[IDX_debug_ranges]
- ?: elf_rawdata (scn, NULL));
- if (unlikely (data == NULL))
- {
- error (0, 0, _("cannot get .debug_ranges content: %s"),
- elf_errmsg (-1));
- return;
- }
+ Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_ranges, scn);
+ if (data == NULL)
+ return;
printf (_("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
@@ -6804,16 +6818,22 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
}
bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
- Elf_Data *data = (is_eh_frame
- ? elf_rawdata (scn, NULL)
- : (dbg->sectiondata[IDX_debug_frame]
- ?: elf_rawdata (scn, NULL)));
-
- if (unlikely (data == NULL))
+ Elf_Data *data;
+ if (is_eh_frame)
{
- error (0, 0, _("cannot get %s content: %s"),
- scnname, elf_errmsg (-1));
- return;
+ data = elf_rawdata (scn, NULL);
+ if (data == NULL)
+ {
+ error (0, 0, _("cannot get %s content: %s"),
+ scnname, elf_errmsg (-1));
+ return;
+ }
+ }
+ else
+ {
+ data = get_debug_elf_data (dbg, ebl, IDX_debug_frame, scn);
+ if (data == NULL)
+ return;
}
if (is_eh_frame)
@@ -7912,6 +7932,13 @@ print_debug_units (Dwfl_Module *dwflmod,
const bool silent = !(print_debug_sections & section_info) && !debug_types;
const char *secname = section_name (ebl, shdr);
+ /* Check section actually exists. */
+ if (!silent)
+ if (get_debug_elf_data (dbg, ebl,
+ debug_types ? IDX_debug_types : IDX_debug_info,
+ scn) == NULL)
+ return;
+
if (!silent)
printf (_("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
@@ -8576,6 +8603,10 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
return;
}
+ Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_line, scn);
+ if (data == NULL)
+ return;
+
printf (_("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
elf_ndxscn (scn), section_name (ebl, shdr),
@@ -8586,14 +8617,6 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
/* There is no functionality in libdw to read the information in the
way it is represented here. Hardcode the decoder. */
- Elf_Data *data = (dbg->sectiondata[IDX_debug_line]
- ?: elf_rawdata (scn, NULL));
- if (unlikely (data == NULL))
- {
- error (0, 0, _("cannot get line data section data: %s"),
- elf_errmsg (-1));
- return;
- }
const unsigned char *linep = (const unsigned char *) data->d_buf;
const unsigned char *lineendp;
@@ -9322,20 +9345,15 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
Elf_Scn *scn, GElf_Shdr *shdr,
Dwarf *dbg)
{
+ Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_loclists, scn);
+ if (data == NULL)
+ return;
+
printf (_("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
- Elf_Data *data = (dbg->sectiondata[IDX_debug_loclists]
- ?: elf_rawdata (scn, NULL));
- if (unlikely (data == NULL))
- {
- error (0, 0, _("cannot get .debug_loclists content: %s"),
- elf_errmsg (-1));
- return;
- }
-
/* For the listptr to get the base address/CU. */
sort_listptr (&known_loclistsptr, "loclistsptr");
size_t listptr_idx = 0;
@@ -9795,15 +9813,9 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
Ebl *ebl, GElf_Ehdr *ehdr,
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
- Elf_Data *data = (dbg->sectiondata[IDX_debug_loc]
- ?: elf_rawdata (scn, NULL));
-
- if (unlikely (data == NULL))
- {
- error (0, 0, _("cannot get .debug_loc content: %s"),
- elf_errmsg (-1));
- return;
- }
+ Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_loc, scn);
+ if (data == NULL)
+ return;
printf (_("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
@@ -10056,6 +10068,10 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
+ Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_macinfo, scn);
+ if (data == NULL)
+ return;
+
printf (_("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
elf_ndxscn (scn), section_name (ebl, shdr),
@@ -10064,14 +10080,6 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
/* There is no function in libdw to iterate over the raw content of
the section but it is easy enough to do. */
- Elf_Data *data = (dbg->sectiondata[IDX_debug_macinfo]
- ?: elf_rawdata (scn, NULL));
- if (unlikely (data == NULL))
- {
- error (0, 0, _("cannot get macro information section data: %s"),
- elf_errmsg (-1));
- return;
- }
/* Get the source file information for all CUs. */
Dwarf_Off offset;
@@ -10222,20 +10230,16 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
+ Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_macro, scn);
+ if (data == NULL)
+ return;
+
printf (_("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
putc_unlocked ('\n', stdout);
- Elf_Data *data = elf_getdata (scn, NULL);
- if (unlikely (data == NULL))
- {
- error (0, 0, _("cannot get macro information section data: %s"),
- elf_errmsg (-1));
- return;
- }
-
/* Get the source file information for all CUs. Uses same
datastructure as macinfo. But uses offset field to directly
match .debug_line offset. And just stored in a list. */
@@ -10609,6 +10613,10 @@ print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
+ /* Check section actually exists. */
+ if (get_debug_elf_data (dbg, ebl, IDX_debug_pubnames, scn) == NULL)
+ return;
+
printf (_("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
@@ -10617,7 +10625,8 @@ print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
(void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
}
-/* Print the content of the DWARF string section '.debug_str'. */
+/* Print the content of the DWARF string section '.debug_str'
+ or 'debug_line_str'. */
static void
print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Ebl *ebl,
@@ -10625,8 +10634,14 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr,
Dwarf *dbg __attribute__ ((unused)))
{
- Elf_Data *data = elf_rawdata (scn, NULL);
- const size_t sh_size = data ? data->d_size : 0;
+ const char *name = section_name (ebl, shdr);
+ int idx = ((name != NULL && strstr (name, "debug_line_str") != NULL)
+ ? IDX_debug_line_str : IDX_debug_str);
+ Elf_Data *data = get_debug_elf_data (dbg, ebl, idx, scn);
+ if (data == NULL)
+ return;
+
+ const size_t sh_size = data->d_size;
/* Compute floor(log16(shdr->sh_size)). */
GElf_Addr tmp = sh_size;
@@ -10669,6 +10684,10 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
+ Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_str_offsets, scn);
+ if (data == NULL)
+ return;
+
printf (_("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
elf_ndxscn (scn), section_name (ebl, shdr),
@@ -10677,16 +10696,6 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
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, _("cannot get .debug_str_offsets section data: %s"),
- elf_errmsg (-1));
- return;
- }
-
size_t idx = 0;
sort_listptr (&known_stroffbases, "str_offsets");
--
2.39.0
next prev parent reply other threads:[~2023-01-10 17:45 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-24 11:09 [PATCH][RFC] readelf: partial support of ZSTD compression Martin Liška
2022-10-24 11:41 ` Dmitry V. Levin
2022-10-24 12:17 ` Martin Liška
2022-10-24 16:48 ` Dmitry V. Levin
2022-10-24 18:16 ` Martin Liška
2022-10-28 22:21 ` Mark Wielaard
2022-11-28 13:16 ` Martin Liška
2022-11-28 22:29 ` Mark Wielaard
2022-11-29 9:34 ` Martin Liška
2022-11-29 12:05 ` [PATCHv2] support ZSTD compression algorithm Martin Liška
2022-12-09 10:17 ` Martin Liška
2022-12-15 13:17 ` Mark Wielaard
2022-12-19 14:19 ` Martin Liška
2022-12-19 15:09 ` Mark Wielaard
2022-12-21 11:13 ` Martin Liška
2023-01-10 17:44 ` Mark Wielaard [this message]
2023-01-16 19:39 ` [PATCH] readelf: Check compression status of .debug section data Mark Wielaard
2022-12-16 0:32 ` [PATCHv2] support ZSTD compression algorithm Mark Wielaard
2022-12-19 14:21 ` Martin Liška
2022-12-19 15:16 ` Mark Wielaard
2022-12-21 11:09 ` Martin Liška
2022-12-21 23:14 ` Mark Wielaard
2022-12-22 9:17 ` Martin Liška
2022-12-22 18:36 ` Mark Wielaard
2022-12-23 8:44 ` Martin Liška
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230110174457.524148-1-mark@klomp.org \
--to=mark@klomp.org \
--cc=elfutils-devel@sourceware.org \
--cc=mliska@suse.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).