int
-dwarf_form_relocatable (attr, sym, name, addend)
+dwarf_form_relocatable (attr, sym, name, addend, secname)
Dwarf_Attribute *attr;
GElf_Sym *sym;
const char **name;
GElf_Sxword *addend;
+ const char **secname;
{
if (attr == NULL)
return -1;
default:
return ((addend != NULL && INTUSE(dwarf_formsdata) (attr, addend)) ? -1
: __libdw_relocatable (attr->cu->dbg, IDX_last, NULL, 0,
- sym, name, addend, 0));
+ sym, name, addend, 0, secname));
case DW_FORM_addr:
width = attr->cu->address_size;
}
return __libdw_relocatable (attr->cu->dbg, cu_sec_idx (attr->cu),
- attr->valp, width, sym, name, addend, 0);
+ attr->valp, width, sym, name, addend, 0, secname);
}
int
-dwarf_lineaddr_relocatable (line, sym, name, addend)
+dwarf_lineaddr_relocatable (line, sym, name, addend, secname)
Dwarf_Line *line;
GElf_Sym *sym;
const char **name;
GElf_Sxword *addend;
+ const char **secname;
{
if (line == NULL)
return -1;
: line->cu->lines->reloc[line
- line->cu->lines->info],
line->cu->address_size, sym, name, addend,
- line->addr);
+ line->addr, secname);
}
/* Relocatable address access functions.
These retrieve an address that might require relocation in an ET_REL
- file. They return -1 for errors. If successful, they fill in SYM (if
- not null) with the ELF symbol describing the address fetched. If NAME
- is not null, it is filled with the symbol name, or with NULL if there is
- no named symbol involved. If ADDEND is not null, it is filled with the
- offset relative to that symbol. If the symbol refers to a normal
- section, the return value is that section index (which might be above
- SHN_LORESERVE). If the symbol does not refer to a normal section,
- the return value is zero and SYM->st_shndx has a special SHN_* value.
+ file. They return -1 for errors. If successful, they fill in SYM
+ (if not null) with the ELF symbol describing the address fetched.
+
+ If the symbol refers to a normal section, the return value is that
+ section index (which might be above SHN_LORESERVE). If the symbol
+ does not refer to a normal section, the return value is zero and
+ SYM->st_shndx has a special SHN_* value. If SECNAME is not null, it
+ is filled with the name of the symbol's section if available, or NULL
+ if not available (or for a special st_shndx).
+
+ If NAME is not null, it is filled with the symbol name, or with NULL
+ if there is no named symbol involved. If ADDEND is not null, it is
+ filled with the offset relative to that symbol.
+
An address that required no relocation appears as a SHN_ABS symbol
with st_value 0 and the whole address in the addend. */
/* Like dwarf_formaddr, but as described above. */
extern int dwarf_form_relocatable (Dwarf_Attribute *attr,
GElf_Sym *sym, const char **name,
- GElf_Sxword *addend);
+ GElf_Sxword *addend,
+ const char **secname);
/* Like dwarf_lineaddr, but as described above. */
extern int dwarf_lineaddr_relocatable (Dwarf_Line *line,
GElf_Sym *sym, const char **name,
- GElf_Sxword *addend);
+ GElf_Sxword *addend,
+ const char **secname);
/* Get abbreviation at given offset for given DIE. */
extern int __libdw_relocatable (Dwarf *dbg, int sec_idx,
const unsigned char *valp, unsigned int width,
GElf_Sym *sym, const char **name,
- GElf_Sxword *addend, GElf_Sxword offset)
+ GElf_Sxword *addend, GElf_Sxword offset,
+ const char **secname)
__nonnull_attribute__ (1) internal_function;
__libdw_relocatable (Dwarf *dbg, int sec_idx,
const unsigned char *valp, unsigned int width,
GElf_Sym *sym, const char **name, GElf_Sxword *addend,
- GElf_Sxword offset)
+ GElf_Sxword offset, const char **secname)
{
struct dwarf_section_reloc *const r = dbg->relocate->sectionrel[sec_idx];
int symndx;
*addend = offset + (width == 8
? read_8ubyte_unaligned (dbg, valp)
: read_4ubyte_unaligned (dbg, valp));
+ if (secname != NULL)
+ *secname = NULL;
}
else if (likely (result > 0))
{
*addend += offset;
result = (sym->st_shndx < SHN_LORESERVE ? sym->st_shndx
: sym->st_shndx == SHN_XINDEX ? shndx : SHN_UNDEF);
+ if (secname != NULL)
+ {
+ Elf *symelf = ((Elf_Data_Scn *) r->symdata)->s->elf;
+ size_t shstrndx;
+ GElf_Shdr shdr;
+ if (result == 0
+ || elf_getshdrstrndx (symelf, &shstrndx) < 0
+ || gelf_getshdr (elf_getscn (symelf, result), &shdr) == NULL)
+ *secname = NULL;
+ else
+ *secname = elf_strptr (symelf, shstrndx, shdr.sh_name);
+ }
}
}