summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2004-07-23 00:46:05 +0000
committergrehan <grehan@FreeBSD.org>2004-07-23 00:46:05 +0000
commit05c0231248aeb113690e49124d3b096febc9dd65 (patch)
tree09afbad9b2a5f131edc8274fa5a8656521e0b8cc /sys
parent5f9a1d08785739f2f018ea92ebc54de2cf0b1e29 (diff)
downloadFreeBSD-src-05c0231248aeb113690e49124d3b096febc9dd65.zip
FreeBSD-src-05c0231248aeb113690e49124d3b096febc9dd65.tar.gz
The ADDR16 relocations were assuming that non-local symbols had an
addend of 0. This isn't correct, and was quite easy to break by referring to the address of an element within a structure. However, fixing this exposed the fact that symbol lookups for local variables were returning the base of the section they were contained in. This case is detected by comparing the return value from elf_lookup() to the relocbase+addend value: if it is lesser, but greater than relocbase, then relocbase+addend is taken to be the authoritative value. bug reported by: gallatin
Diffstat (limited to 'sys')
-rw-r--r--sys/powerpc/powerpc/elf_machdep.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/sys/powerpc/powerpc/elf_machdep.c b/sys/powerpc/powerpc/elf_machdep.c
index ae4b219..e9481ff 100644
--- a/sys/powerpc/powerpc/elf_machdep.c
+++ b/sys/powerpc/powerpc/elf_machdep.c
@@ -147,24 +147,34 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
break;
case R_PPC_ADDR16_LO: /* #lo(S) */
- if (addend != 0) {
- addr = relocbase + addend;
- } else {
- addr = lookup(lf, symidx, 1);
- if (addr == 0)
- return -1;
- }
+ addr = lookup(lf, symidx, 1);
+ if (addr == 0)
+ return -1;
+ /*
+ * addend values are sometimes relative to sections
+ * (i.e. .rodata) in rela, where in reality they
+ * are relative to relocbase. Detect this condition.
+ */
+ if (addr > relocbase && addr <= (relocbase + addend))
+ addr = relocbase + addend;
+ else
+ addr += addend;
*hwhere = addr & 0xffff;
break;
case R_PPC_ADDR16_HA: /* #ha(S) */
- if (addend != 0) {
- addr = relocbase + addend;
- } else {
- addr = lookup(lf, symidx, 1);
- if (addr == 0)
- return -1;
- }
+ addr = lookup(lf, symidx, 1);
+ if (addr == 0)
+ return -1;
+ /*
+ * addend values are sometimes relative to sections
+ * (i.e. .rodata) in rela, where in reality they
+ * are relative to relocbase. Detect this condition.
+ */
+ if (addr > relocbase && addr <= (relocbase + addend))
+ addr = relocbase + addend;
+ else
+ addr += addend;
*hwhere = ((addr >> 16) + ((addr & 0x8000) ? 1 : 0))
& 0xffff;
break;
OpenPOWER on IntegriCloud