diff options
author | Andreas Schwab <schwab@suse.de> | 2018-10-02 14:46:51 +0200 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2018-10-13 22:54:51 +0200 |
commit | 2876b3b648f665736ac9c879d34de5e3866ba8f9 (patch) | |
tree | be631dee293e01847e3eea43343b0d249a7532c6 /libdwfl | |
parent | 69d6e67eee30c483ba53a8e1da1b3568033e3dde (diff) |
Handle ADD/SUB relocations
This adds support for ADD and SUB relocations as seen on RISC-V.
Signed-off-by: Andreas Schwab <schwab@suse.de>
Diffstat (limited to 'libdwfl')
-rw-r--r-- | libdwfl/ChangeLog | 4 | ||||
-rw-r--r-- | libdwfl/relocate.c | 21 |
2 files changed, 23 insertions, 2 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 5e9b986d..c5ea5634 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,7 @@ +2018-10-02 Andreas Schwab <schwab@suse.de> + + * relocate.c (relocate): Handle ADD/SUB relocations. + 2018-09-13 Mark Wielaard <mark@klomp.org> * dwfl_segment_report_module.c (dwfl_segment_report_module): diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c index 9afcdebe..58c56786 100644 --- a/libdwfl/relocate.c +++ b/libdwfl/relocate.c @@ -338,7 +338,8 @@ relocate (Dwfl_Module * const mod, So we just pretend it's OK without further relocation. */ return DWFL_E_NOERROR; - Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype); + int addsub = 0; + Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype, &addsub); if (unlikely (type == ELF_T_NUM)) return DWFL_E_BADRELTYPE; @@ -383,6 +384,9 @@ relocate (Dwfl_Module * const mod, { #define DO_TYPE(NAME, Name) \ case ELF_T_##NAME: \ + if (addsub != 0 && addend == NULL) \ + /* These do not make sense with SHT_REL. */ \ + return DWFL_E_BADRELTYPE; \ size = sizeof (GElf_##Name); \ break TYPES; @@ -417,11 +421,24 @@ relocate (Dwfl_Module * const mod, { /* For the addend form, we have the value already. */ value += *addend; + /* For ADD/SUB relocations we need to fetch the section + contents. */ + if (addsub != 0) + { + Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata, + ehdr->e_ident[EI_DATA]); + if (d == NULL) + return DWFL_E_LIBELF; + assert (d == &tmpdata); + } switch (type) { #define DO_TYPE(NAME, Name) \ case ELF_T_##NAME: \ - tmpbuf.Name = value; \ + if (addsub != 0) \ + tmpbuf.Name += value * addsub; \ + else \ + tmpbuf.Name = value; \ break TYPES; #undef DO_TYPE |