summaryrefslogtreecommitdiff
path: root/libdwfl/dwfl_module_getdwarf.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdwfl/dwfl_module_getdwarf.c')
-rw-r--r--libdwfl/dwfl_module_getdwarf.c99
1 files changed, 92 insertions, 7 deletions
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index e9589b3f..0e8810b1 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -1130,10 +1130,39 @@ find_symtab (Dwfl_Module *mod)
goto aux_cleanup; /* This cleans up some more and tries find_dynsym. */
}
- /* Cache the data; MOD->syments and MOD->first_global were set above. */
+ /* Cache the data; MOD->syments and MOD->first_global were set
+ above. If any of the sections is compressed, uncompress it
+ first. Only the string data setion could theoretically be
+ compressed GNU style (as .zdebug_str). Everything else only ELF
+ gabi style (SHF_COMPRESSED). */
+
+ Elf_Scn *symstrscn = elf_getscn (mod->symfile->elf, strshndx);
+ if (symstrscn == NULL)
+ goto elferr;
+
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (symstrscn, &shdr_mem);
+ if (shdr == NULL)
+ goto elferr;
+
+ size_t shstrndx;
+ if (elf_getshdrstrndx (mod->symfile->elf, &shstrndx) < 0)
+ goto elferr;
+
+ const char *sname = elf_strptr (mod->symfile->elf, shstrndx, shdr->sh_name);
+ if (sname == NULL)
+ goto elferr;
+
+ if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0)
+ /* Try to uncompress, but it might already have been, an error
+ might just indicate, already uncompressed. */
+ elf_compress_gnu (symstrscn, 0, 0);
- mod->symstrdata = elf_getdata (elf_getscn (mod->symfile->elf, strshndx),
- NULL);
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ if (elf_compress (symstrscn, 0, 0) < 0)
+ goto elferr;
+
+ mod->symstrdata = elf_getdata (symstrscn, NULL);
if (mod->symstrdata == NULL || mod->symstrdata->d_buf == NULL)
goto elferr;
@@ -1141,17 +1170,33 @@ find_symtab (Dwfl_Module *mod)
mod->symxndxdata = NULL;
else
{
+ shdr = gelf_getshdr (xndxscn, &shdr_mem);
+ if (shdr == NULL)
+ goto elferr;
+
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ if (elf_compress (xndxscn, 0, 0) < 0)
+ goto elferr;
+
mod->symxndxdata = elf_getdata (xndxscn, NULL);
if (mod->symxndxdata == NULL || mod->symxndxdata->d_buf == NULL)
goto elferr;
}
+ shdr = gelf_getshdr (symscn, &shdr_mem);
+ if (shdr == NULL)
+ goto elferr;
+
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ if (elf_compress (symscn, 0, 0) < 0)
+ goto elferr;
+
mod->symdata = elf_getdata (symscn, NULL);
if (mod->symdata == NULL || mod->symdata->d_buf == NULL)
goto elferr;
// Sanity check number of symbols.
- GElf_Shdr shdr_mem, *shdr = gelf_getshdr (symscn, &shdr_mem);
+ shdr = gelf_getshdr (symscn, &shdr_mem);
if (shdr == NULL || shdr->sh_entsize == 0
|| mod->syments > mod->symdata->d_size / shdr->sh_entsize
|| (size_t) mod->first_global > mod->syments)
@@ -1174,9 +1219,33 @@ find_symtab (Dwfl_Module *mod)
return;
}
- mod->aux_symstrdata = elf_getdata (elf_getscn (mod->aux_sym.elf,
- aux_strshndx),
- NULL);
+ Elf_Scn *aux_strscn = elf_getscn (mod->aux_sym.elf, aux_strshndx);
+ if (aux_strscn == NULL)
+ goto elferr;
+
+ shdr = gelf_getshdr (aux_strscn, &shdr_mem);
+ if (shdr == NULL)
+ goto elferr;
+
+ size_t aux_shstrndx;
+ if (elf_getshdrstrndx (mod->aux_sym.elf, &aux_shstrndx) < 0)
+ goto elferr;
+
+ sname = elf_strptr (mod->aux_sym.elf, aux_shstrndx,
+ shdr->sh_name);
+ if (sname == NULL)
+ goto elferr;
+
+ if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0)
+ /* Try to uncompress, but it might already have been, an error
+ might just indicate, already uncompressed. */
+ elf_compress_gnu (aux_strscn, 0, 0);
+
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ if (elf_compress (aux_strscn, 0, 0) < 0)
+ goto elferr;
+
+ mod->aux_symstrdata = elf_getdata (aux_strscn, NULL);
if (mod->aux_symstrdata == NULL || mod->aux_symstrdata->d_buf == NULL)
goto aux_cleanup;
@@ -1184,12 +1253,28 @@ find_symtab (Dwfl_Module *mod)
mod->aux_symxndxdata = NULL;
else
{
+ shdr = gelf_getshdr (aux_xndxscn, &shdr_mem);
+ if (shdr == NULL)
+ goto elferr;
+
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ if (elf_compress (aux_xndxscn, 0, 0) < 0)
+ goto elferr;
+
mod->aux_symxndxdata = elf_getdata (aux_xndxscn, NULL);
if (mod->aux_symxndxdata == NULL
|| mod->aux_symxndxdata->d_buf == NULL)
goto aux_cleanup;
}
+ shdr = gelf_getshdr (aux_symscn, &shdr_mem);
+ if (shdr == NULL)
+ goto elferr;
+
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ if (elf_compress (aux_symscn, 0, 0) < 0)
+ goto elferr;
+
mod->aux_symdata = elf_getdata (aux_symscn, NULL);
if (mod->aux_symdata == NULL || mod->aux_symdata->d_buf == NULL)
goto aux_cleanup;