/* Create descriptor from ELF descriptor for processing file.
- Copyright (C) 2002-2010 Red Hat, Inc.
+ Copyright (C) 2002-2011 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
#include "libdwP.h"
+#if USE_ZLIB
+# include <endian.h>
+# define crc32 loser_crc32
+# include <zlib.h>
+# undef crc32
+#endif
+
/* Section names. */
static const char dwarf_scnnames[IDX_last][17] =
{
/* The section name must be valid. Otherwise is the ELF file
invalid. */
+ __libdw_free_zdata (result);
__libdw_seterrno (DWARF_E_INVALID_ELF);
free (result);
return NULL;
break;
}
+#if USE_ZLIB
+ else if (scnname[0] == '.' && scnname[1] == 'z'
+ && strcmp (&scnname[2], &dwarf_scnnames[cnt][1]) == 0)
+ {
+ /* A compressed section. */
+
+ if (unlikely (result->sectiondata[cnt] != NULL))
+ /* A section appears twice. That's bad. We ignore the section. */
+ break;
+
+ /* Get the section data. */
+ Elf_Data *data = elf_getdata (scn, NULL);
+ if (data != NULL && data->d_size != 0)
+ {
+ /* There is a 12-byte header of "ZLIB" followed by
+ an 8-byte big-endian size. */
+
+ if (unlikely (data->d_size < 4 + 8)
+ || unlikely (memcmp (data->d_buf, "ZLIB", 4) != 0))
+ break;
+
+ uint64_t size;
+ memcpy (&size, data->d_buf + 4, sizeof size);
+ size = be64toh (size);
+
+ Elf_Data *zdata = malloc (sizeof (Elf_Data) + size);
+ if (unlikely (zdata == NULL))
+ break;
+
+ zdata->d_buf = &zdata[1];
+ zdata->d_type = ELF_T_BYTE;
+ zdata->d_version = EV_CURRENT;
+ zdata->d_size = size;
+ zdata->d_off = 0;
+ zdata->d_align = 1;
+
+ z_stream z =
+ {
+ .next_in = data->d_buf + 4 + 8,
+ .avail_in = data->d_size - 4 - 8,
+ .next_out = zdata->d_buf,
+ .avail_out = zdata->d_size
+ };
+ int zrc = inflateInit (&z);
+ while (z.avail_in > 0 && likely (zrc == Z_OK))
+ {
+ z.next_out = zdata->d_buf + (zdata->d_size - z.avail_out);
+ zrc = inflate (&z, Z_FINISH);
+ if (unlikely (zrc != Z_STREAM_END))
+ {
+ zrc = Z_DATA_ERROR;
+ break;
+ }
+ zrc = inflateReset (&z);
+ }
+ if (likely (zrc == Z_OK))
+ zrc = inflateEnd (&z);
+
+ if (unlikely (zrc != Z_OK) || unlikely (z.avail_out != 0))
+ free (zdata);
+ else
+ {
+ result->sectiondata[cnt] = zdata;
+ result->sectiondata_gzip_mask |= 1U << cnt;
+ }
+ }
+
+ break;
+ }
+#endif
return result;
}
if (likely (result != NULL)
&& unlikely (result->sectiondata[IDX_debug_info] == NULL))
{
+ __libdw_free_zdata (result);
__libdw_seterrno (DWARF_E_NO_DWARF);
free (result);
result = NULL;
if (data == NULL)
{
/* We cannot read the section content. Fail! */
+ __libdw_free_zdata (result);
free (result);
return NULL;
}
{
/* A section group refers to a non-existing section. Should
never happen. */
+ __libdw_free_zdata (result);
__libdw_seterrno (DWARF_E_INVALID_ELF);
free (result);
return NULL;
}
+static const char *
+section_name (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr)
+{
+ return elf_strptr (ebl->elf, ehdr->e_shstrndx, shdr->sh_name) ?: "???";
+}
+
+
static void
handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
{
static void
print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
- Ebl *ebl __attribute__ ((unused)),
- GElf_Ehdr *ehdr __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"
" [ Code]\n"),
- elf_ndxscn (scn), ".debug_abbrev", (uint64_t) shdr->sh_offset);
+ elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ (uint64_t) shdr->sh_offset);
Dwarf_Off offset = 0;
- while (offset < shdr->sh_size)
+ while (offset < dbg->sectiondata[IDX_debug_abbrev]->d_size)
{
printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
offset);
takes care of it. */
static void
print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
- Ebl *ebl __attribute__ ((unused)),
- GElf_Ehdr *ehdr, Elf_Scn *scn,
+ Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
GElf_Shdr *shdr, Dwarf *dbg)
{
Dwarf_Aranges *aranges;
"\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
cnt),
- elf_ndxscn (scn), ".debug_aranges", (uint64_t) shdr->sh_offset, cnt);
+ elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ (uint64_t) shdr->sh_offset, cnt);
/* Compute floor(log16(cnt)). */
size_t tmp = cnt;
/* Print content of DWARF .debug_ranges section. */
static void
print_debug_ranges_section (Dwfl_Module *dwflmod,
- Ebl *ebl __attribute__ ((unused)),
- GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr,
+ Ebl *ebl, GElf_Ehdr *ehdr,
+ Elf_Scn *scn, GElf_Shdr *shdr,
Dwarf *dbg)
{
Elf_Data *data = elf_rawdata (scn, NULL);
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), ".debug_ranges", (uint64_t) shdr->sh_offset);
+ elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ (uint64_t) shdr->sh_offset);
sort_listptr (&known_rangelistptr, "rangelistptr");
size_t listptr_idx = 0;
static void
print_debug_units (Dwfl_Module *dwflmod,
- Ebl *ebl __attribute__ ((unused)),
- GElf_Ehdr *ehdr __attribute__ ((unused)),
- Elf_Scn *scn,
- GElf_Shdr *shdr, Dwarf *dbg,
- bool debug_types)
+ Ebl *ebl, GElf_Ehdr *ehdr,
+ Elf_Scn *scn, GElf_Shdr *shdr,
+ Dwarf *dbg, bool debug_types)
{
const bool silent = !(print_debug_sections & section_info);
- const char *secname = debug_types ? ".debug_types" : ".debug_info";
+ const char *secname = section_name (ebl, ehdr, shdr);
if (!silent)
printf (gettext ("\
static void
-print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
- GElf_Ehdr *ehdr __attribute__ ((unused)),
+print_debug_line_section (Dwfl_Module *dwflmod, 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), ".debug_line", (uint64_t) shdr->sh_offset);
+ elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ (uint64_t) shdr->sh_offset);
if (shdr->sh_size == 0)
return;
{
invalid_data:
error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
- elf_ndxscn (scn), ".debug_line");
+ elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
return;
}
unit_length = read_8ubyte_unaligned_inc (dbg, linep);
error (0, 0,
gettext ("invalid data at offset %tu in section [%zu] '%s'"),
linep - (const unsigned char *) data->d_buf,
- elf_ndxscn (scn), ".debug_line");
+ elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
linep = lineendp;
continue;
}
static void
print_debug_loc_section (Dwfl_Module *dwflmod,
- Ebl *ebl __attribute__ ((unused)), GElf_Ehdr *ehdr,
+ Ebl *ebl, GElf_Ehdr *ehdr,
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
Elf_Data *data = elf_rawdata (scn, NULL);
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), ".debug_loc", (uint64_t) shdr->sh_offset);
+ elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ (uint64_t) shdr->sh_offset);
sort_listptr (&known_loclistptr, "loclistptr");
size_t listptr_idx = 0;
static void
print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
- Ebl *ebl __attribute__ ((unused)),
- GElf_Ehdr *ehdr __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), ".debug_macinfo", (uint64_t) shdr->sh_offset);
+ elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ (uint64_t) shdr->sh_offset);
putc_unlocked ('\n', stdout);
/* There is no function in libdw to iterate over the raw content of
/* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
static void
print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
- Ebl *ebl __attribute__ ((unused)),
- GElf_Ehdr *ehdr __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), ".debug_pubnames", (uint64_t) shdr->sh_offset);
+ elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ (uint64_t) shdr->sh_offset);
int n = 0;
(void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
/* Print the content of the DWARF string section '.debug_str'. */
static void
print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
- Ebl *ebl __attribute__ ((unused)),
- GElf_Ehdr *ehdr __attribute__ ((unused)),
+ Ebl *ebl, GElf_Ehdr *ehdr,
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
+ const size_t sh_size = dbg->sectiondata[IDX_debug_str]->d_size;
+
/* Compute floor(log16(shdr->sh_size)). */
- GElf_Addr tmp = shdr->sh_size;
+ GElf_Addr tmp = sh_size;
int digits = 1;
while (tmp >= 16)
{
printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
" %*s String\n"),
elf_ndxscn (scn),
- ".debug_str", (uint64_t) shdr->sh_offset,
+ section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset,
/* TRANS: the debugstr| prefix makes the string unique. */
digits + 2, sgettext ("debugstr|Offset"));
Dwarf_Off offset = 0;
- while (offset < shdr->sh_size)
+ while (offset < sh_size)
{
size_t len;
const char *str = dwarf_getstring (dbg, offset, &len);
int n;
for (n = 0; n < ndebug_sections; ++n)
- if (strcmp (name, debug_sections[n].name) == 0)
+ if (strcmp (name, debug_sections[n].name) == 0
+#if USE_ZLIB
+ || (name[0] == '.' && name[1] == 'z'
+ && debug_sections[n].name[1] == 'd'
+ && strcmp (&name[2], &debug_sections[n].name[1]) == 0)
+#endif
+ )
{
if ((print_debug_sections | implicit_debug_sections)
& debug_sections[n].bitmask)