1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-14 10:09:48 +00:00

libdwarf: Handle .rel relocations

Some architectures use .rel relocations (for debug data), so they must
be handled.

This was discovered from ctfconvert on ARM object files.  The lack of
relocation handling caused all string lookups to return the string at
offset 0 in .debug_str, typically "FreeBSD clang version ..."

Reviewed by:	gnn, imp, rpaulo (earlier version)
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D1819
This commit is contained in:
Ed Maste 2015-02-12 02:08:44 +00:00
parent 21c31ec174
commit d133198b4b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=278611
5 changed files with 50 additions and 33 deletions

View File

@ -49,7 +49,7 @@
struct _libdwarf_globals {
Dwarf_Handler errhand;
Dwarf_Ptr errarg;
int applyrela;
int applyreloc;
};
extern struct _libdwarf_globals _libdwarf;

View File

@ -33,8 +33,8 @@ dwarf_set_reloc_application(int apply)
{
int oldapply;
oldapply = _libdwarf.applyrela;
_libdwarf.applyrela = apply;
oldapply = _libdwarf.applyreloc;
_libdwarf.applyreloc = apply;
return (oldapply);
}

View File

@ -24,7 +24,7 @@
.\"
.\" $Id: dwarf_set_reloc_application.3 2075 2011-10-27 03:47:28Z jkoshy $
.\"
.Dd June 26, 2011
.Dd February 11, 2015
.Os
.Dt DWARF_SET_RELOC_APPLICATION 3
.Sh NAME
@ -47,6 +47,8 @@ handled by the DWARF(3) library.
If the argument
.Ar apply
holds a non-zero value, the library will process all the relevant
.Dq ".rel"
and
.Dq ".rela"
relocation sections and will apply the relocation records found to
their corresponding DWARF sections.

View File

@ -31,5 +31,5 @@ ELFTC_VCSID("$Id: libdwarf.c 2070 2011-10-27 03:05:32Z jkoshy $");
struct _libdwarf_globals _libdwarf = {
.errhand = NULL,
.errarg = NULL,
.applyrela = 1
.applyreloc = 1
};

View File

@ -50,36 +50,46 @@ static const char *debug_name[] = {
};
static void
_dwarf_elf_apply_reloc(Dwarf_Debug dbg, void *buf, Elf_Data *rel_data,
_dwarf_elf_write_reloc(Dwarf_Debug dbg, Elf_Data *symtab_data, int endian,
void *buf, uint64_t offset, GElf_Xword r_info, GElf_Sxword r_addend)
{
GElf_Sym sym;
int size;
if (gelf_getsym(symtab_data, GELF_R_SYM(r_info), &sym) == NULL)
return;
if ((size = _dwarf_get_reloc_size(dbg, GELF_R_TYPE(r_info))) == 0)
return; /* Unknown or non-absolute relocation. */
if (endian == ELFDATA2MSB)
_dwarf_write_msb(buf, &offset, sym.st_value + r_addend, size);
else
_dwarf_write_lsb(buf, &offset, sym.st_value + r_addend, size);
}
static void
_dwarf_elf_apply_rel_reloc(Dwarf_Debug dbg, void *buf, Elf_Data *rel_data,
Elf_Data *symtab_data, int endian)
{
Dwarf_Unsigned type;
GElf_Rela rela;
GElf_Sym sym;
size_t symndx;
uint64_t offset;
int size, j;
GElf_Rel rel;
int j;
j = 0;
while (gelf_getrela(rel_data, j++, &rela) != NULL) {
symndx = GELF_R_SYM(rela.r_info);
type = GELF_R_TYPE(rela.r_info);
while (gelf_getrel(rel_data, j++, &rel) != NULL)
_dwarf_elf_write_reloc(dbg, symtab_data, endian, buf,
rel.r_offset, rel.r_info, 0);
}
if (gelf_getsym(symtab_data, symndx, &sym) == NULL)
continue;
static void
_dwarf_elf_apply_rela_reloc(Dwarf_Debug dbg, void *buf, Elf_Data *rel_data,
Elf_Data *symtab_data, int endian)
{
GElf_Rela rela;
int j;
offset = rela.r_offset;
size = _dwarf_get_reloc_size(dbg, type);
if (size == 0)
continue; /* Unknown or non-absolute relocation. */
if (endian == ELFDATA2MSB)
_dwarf_write_msb(buf, &offset,
sym.st_value + rela.r_addend, size);
else
_dwarf_write_lsb(buf, &offset,
sym.st_value + rela.r_addend, size);
}
j = 0;
while (gelf_getrela(rel_data, j++, &rela) != NULL)
_dwarf_elf_write_reloc(dbg, symtab_data, endian, buf,
rela.r_offset, rela.r_info, rela.r_addend);
}
static int
@ -108,7 +118,8 @@ _dwarf_elf_relocate(Dwarf_Debug dbg, Elf *elf, Dwarf_Elf_Data *ed, size_t shndx,
return (DW_DLE_ELF);
}
if (sh.sh_type != SHT_RELA || sh.sh_size == 0)
if ((sh.sh_type != SHT_REL && sh.sh_type != SHT_RELA) ||
sh.sh_size == 0)
continue;
if (sh.sh_info == shndx && sh.sh_link == symtab) {
@ -129,8 +140,12 @@ _dwarf_elf_relocate(Dwarf_Debug dbg, Elf *elf, Dwarf_Elf_Data *ed, size_t shndx,
}
memcpy(ed->ed_alloc, ed->ed_data->d_buf,
ed->ed_data->d_size);
_dwarf_elf_apply_reloc(dbg, ed->ed_alloc, rel,
symtab_data, eh.e_ident[EI_DATA]);
if (sh.sh_type == SHT_REL)
_dwarf_elf_apply_rel_reloc(dbg, ed->ed_alloc,
rel, symtab_data, eh.e_ident[EI_DATA]);
else
_dwarf_elf_apply_rela_reloc(dbg, ed->ed_alloc,
rel, symtab_data, eh.e_ident[EI_DATA]);
return (DW_DLE_NONE);
}
@ -286,7 +301,7 @@ _dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error *error)
}
}
if (_libdwarf.applyrela) {
if (_libdwarf.applyreloc) {
if (_dwarf_elf_relocate(dbg, elf,
&e->eo_data[j], elf_ndxscn(scn), symtab_ndx,
symtab_data, error) != DW_DLE_NONE)