summaryrefslogtreecommitdiffstats
path: root/libdwfl
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@suse.de>2018-10-02 14:46:51 +0200
committerMark Wielaard <mark@klomp.org>2018-10-13 22:54:51 +0200
commit2876b3b648f665736ac9c879d34de5e3866ba8f9 (patch)
treebe631dee293e01847e3eea43343b0d249a7532c6 /libdwfl
parent69d6e67eee30c483ba53a8e1da1b3568033e3dde (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/ChangeLog4
-rw-r--r--libdwfl/relocate.c21
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