+2015-12-18 Mark Wielaard <mjw@redhat.com>
+
+ * dwfl_module_getdwarf.c (find_symtab): Uncompress symstr, xndx, sym
+ sections and aux_str, aux_xndx and aux_sym sections if necessary.
+ * relocate.c (relocate_getsym): Uncompress symtab and symtab_shndx
+ if necessary.
+ (resolve_symbol): Uncompress strtab section if necessary.
+ (relocate_section): Uncompress the section the relocations apply to
+ if necessary.
+
2015-11-18 Chih-Hung Hsieh <chh@google.com>
* linux-proc-maps.c (proc_maps_report): Move nested function
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;
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)
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;
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;
{
GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
if (shdr != NULL)
- switch (shdr->sh_type)
- {
- default:
- continue;
- case SHT_SYMTAB:
- cache->symelf = relocated;
- cache->symdata = elf_getdata (scn, NULL);
- cache->strtabndx = shdr->sh_link;
- if (unlikely (cache->symdata == NULL))
- return DWFL_E_LIBELF;
- break;
- case SHT_SYMTAB_SHNDX:
- cache->symxndxdata = elf_getdata (scn, NULL);
- if (unlikely (cache->symxndxdata == NULL))
+ {
+ /* We need uncompressed data. */
+ if ((shdr->sh_type == SHT_SYMTAB
+ || shdr->sh_type == SHT_SYMTAB_SHNDX)
+ && (shdr->sh_flags & SHF_COMPRESSED) != 0)
+ if (elf_compress (scn, 0, 0) < 0)
return DWFL_E_LIBELF;
- break;
- }
+
+ switch (shdr->sh_type)
+ {
+ default:
+ continue;
+ case SHT_SYMTAB:
+ cache->symelf = relocated;
+ cache->symdata = elf_getdata (scn, NULL);
+ cache->strtabndx = shdr->sh_link;
+ if (unlikely (cache->symdata == NULL))
+ return DWFL_E_LIBELF;
+ break;
+ case SHT_SYMTAB_SHNDX:
+ cache->symxndxdata = elf_getdata (scn, NULL);
+ if (unlikely (cache->symxndxdata == NULL))
+ return DWFL_E_LIBELF;
+ break;
+ }
+ }
if (cache->symdata != NULL && cache->symxndxdata != NULL)
break;
}
/* Cache the strtab for this symtab. */
assert (referer->symfile == NULL
|| referer->symfile->elf != symtab->symelf);
- symtab->symstrdata = elf_getdata (elf_getscn (symtab->symelf,
- symtab->strtabndx),
- NULL);
+
+ Elf_Scn *scn = elf_getscn (symtab->symelf, symtab->strtabndx);
+ if (scn == NULL)
+ return DWFL_E_LIBELF;
+
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr == NULL)
+ return DWFL_E_LIBELF;
+
+ if (symtab->symshstrndx == SHN_UNDEF
+ && elf_getshdrstrndx (symtab->symelf, &symtab->symshstrndx) < 0)
+ return DWFL_E_LIBELF;
+
+ const char *sname = elf_strptr (symtab->symelf, symtab->symshstrndx,
+ shdr->sh_name);
+ if (sname == NULL)
+ return DWFL_E_LIBELF;
+
+ /* If the section is already decompressed, that isn't an error. */
+ if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0)
+ elf_compress_gnu (scn, 0, 0);
+
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ if (elf_compress (scn, 0, 0) < 0)
+ return DWFL_E_LIBELF;
+
+ symtab->symstrdata = elf_getdata (scn, NULL);
if (unlikely (symtab->symstrdata == NULL
|| symtab->symstrdata->d_buf == NULL))
return DWFL_E_LIBELF;
Elf_Scn *scn, GElf_Shdr *shdr,
Elf_Scn *tscn, bool debugscn, bool partial)
{
- /* First, fetch the name of the section these relocations apply to. */
+ /* First, fetch the name of the section these relocations apply to.
+ Then try to decompress both relocation and target section. */
GElf_Shdr tshdr_mem;
GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
+ if (tshdr == NULL)
+ return DWFL_E_LIBELF;
+
const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
if (tname == NULL)
return DWFL_E_LIBELF;
- if (unlikely (tshdr->sh_type == SHT_NOBITS) || unlikely (tshdr->sh_size == 0))
- /* No contents to relocate. */
- return DWFL_E_NOERROR;
-
if (debugscn && ! ebl_debugscn_p (mod->ebl, tname))
/* This relocation section is not for a debugging section.
Nothing to do here. */
return DWFL_E_NOERROR;
+ if (strncmp (tname, ".zdebug", strlen ("zdebug")) == 0)
+ elf_compress_gnu (tscn, 0, 0);
+
+ if ((tshdr->sh_flags & SHF_COMPRESSED) != 0)
+ if (elf_compress (tscn, 0, 0) < 0)
+ return DWFL_E_LIBELF;
+
+ /* Reload Shdr in case section was just decompressed. */
+ tshdr = gelf_getshdr (tscn, &tshdr_mem);
+ if (tshdr == NULL)
+ return DWFL_E_LIBELF;
+
+ if (unlikely (tshdr->sh_type == SHT_NOBITS)
+ || unlikely (tshdr->sh_size == 0))
+ /* No contents to relocate. */
+ return DWFL_E_NOERROR;
+
+ const char *sname = elf_strptr (relocated, shstrndx, shdr->sh_name);
+ if (sname == NULL)
+ return DWFL_E_LIBELF;
+
+ if (strncmp (sname, ".zdebug", strlen ("zdebug")) == 0)
+ elf_compress_gnu (scn, 0, 0);
+
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ if (elf_compress (scn, 0, 0) < 0)
+ return DWFL_E_LIBELF;
+
+ /* Reload Shdr in case section was just decompressed. */
+ GElf_Shdr shdr_mem;
+ shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr == NULL)
+ return DWFL_E_LIBELF;
+
/* Fetch the section data that needs the relocations applied. */
Elf_Data *tdata = elf_rawdata (tscn, NULL);
if (tdata == NULL)
+2015-12-18 Mark Wielaard <mjw@redhat.com>
+
+ * eblopenbackend.c (default_debugscn_p): Also match .zdebug sections.
+
2015-12-08 Jose E. Marchesi <jose.marchesi@oracle.com>
* libebl.h: Prototype for ebl_ra_offset.
const size_t ndwarf_scn_names = (sizeof (dwarf_scn_names)
/ sizeof (dwarf_scn_names[0]));
for (size_t cnt = 0; cnt < ndwarf_scn_names; ++cnt)
- if (strcmp (name, dwarf_scn_names[cnt]) == 0)
+ if (strcmp (name, dwarf_scn_names[cnt]) == 0
+ || (strncmp (name, ".zdebug", strlen (".zdebug")) == 0
+ && strcmp (&name[2], &dwarf_scn_names[cnt][1]) == 0))
return true;
return false;