summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2014-06-17 13:56:54 -0400
committerRich Felker <dalias@aerifal.cx>2014-06-17 13:56:54 -0400
commitf4cc27601817f6decd773c24496bfbe892bcd244 (patch)
tree6e99f1143b72f742f52b59d34bed23200805082c /arch
parentbfa09700b927c99cff5263483c1d7a4d1fe766e5 (diff)
downloadmusl-f4cc27601817f6decd773c24496bfbe892bcd244.tar.gz
musl-f4cc27601817f6decd773c24496bfbe892bcd244.tar.bz2
musl-f4cc27601817f6decd773c24496bfbe892bcd244.tar.xz
musl-f4cc27601817f6decd773c24496bfbe892bcd244.zip
multiple fixes to sh (superh) dynamic linker relocations
the following issues are fixed: - R_SH_REL32 was adding the load address of the module being relocated to the result. this seems to have been a mistake in the original port, since it does not match other dynamic linker implementations and since adding a difference between two addresses (the symbol value and the relocation address) to a load address does not make sense. - R_SH_TLS_DTPMOD32 was wrongly accepting an inline addend (i.e. using += rather than = on *reloc_addr) which makes no sense; addition is not an operation that's defined on module ids. - R_SH_TLS_DTPOFF32 and R_SH_TLS_TPOFF32 were wrongly using inline addends rather than the RELA-provided addends. in addition, handling of R_SH_GLOB_DAT, R_SH_JMP_SLOT, and R_SH_DIR32 are merged to all honor the addend. the first two should not need it for correct usage generated by toolchains, but other dynamic linkers allow addends here, and it simplifies the code anyway. these issues were spotted while reviewing the code for the purpose of refactoring this part of the dynamic linker. no testing was performed.
Diffstat (limited to 'arch')
-rw-r--r--arch/sh/reloc.h18
1 files changed, 8 insertions, 10 deletions
diff --git a/arch/sh/reloc.h b/arch/sh/reloc.h
index a1393bb3..9090ee3b 100644
--- a/arch/sh/reloc.h
+++ b/arch/sh/reloc.h
@@ -18,30 +18,28 @@ static inline int do_single_reloc(
switch(type) {
case R_SH_GLOB_DAT:
case R_SH_JMP_SLOT:
- *reloc_addr = sym_val;
+ case R_SH_DIR32:
+ *reloc_addr = sym_val + addend;
break;
case R_SH_RELATIVE:
*reloc_addr = (size_t)base_addr + addend;
break;
- case R_SH_DIR32:
- *reloc_addr = sym_val + addend;
- break;
case R_SH_REL32:
- *reloc_addr = sym_val + addend - (size_t)reloc_addr + (size_t)base_addr;
+ *reloc_addr = sym_val + addend - (size_t)reloc_addr;
break;
case R_SH_COPY:
memcpy(reloc_addr, (void *)sym_val, sym_size);
break;
case R_SH_TLS_DTPMOD32:
- *reloc_addr += def.dso ? def.dso->tls_id : self->tls_id;
+ *reloc_addr = def.dso ? def.dso->tls_id : self->tls_id;
break;
case R_SH_TLS_DTPOFF32:
- *reloc_addr += def.sym->st_value;
+ *reloc_addr = def.sym->st_value + addend;
break;
case R_SH_TLS_TPOFF32:
- *reloc_addr += def.sym
- ? def.sym->st_value + def.dso->tls_offset + 8
- : self->tls_offset + 8;
+ *reloc_addr = (def.sym
+ ? def.sym->st_value + def.dso->tls_offset
+ : self->tls_offset) + 8 + addend;
break;
}
return 0;