diff options
author | kib <kib@FreeBSD.org> | 2015-09-20 01:27:59 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2015-09-20 01:27:59 +0000 |
commit | 518734671fcba3801baeb67e70a8ba2f134ba44b (patch) | |
tree | a3938733f5d6f30948a42db47e8b9ee2521c366d /sys/amd64 | |
parent | a3fcca6713520dc0bf112298215886bcceed5a0f (diff) | |
download | FreeBSD-src-518734671fcba3801baeb67e70a8ba2f134ba44b.zip FreeBSD-src-518734671fcba3801baeb67e70a8ba2f134ba44b.tar.gz |
Add support for weak symbols to the kernel linkers. It means that
linkers no longer raise an error when undefined weak symbols are
found, but relocate as if the symbol value was 0. Note that we do not
repeat the mistake of userspace dynamic linker of making the symbol
lookup prefer non-weak symbol definition over the weak one, if both
are available. In fact, kernel linker uses the first definition
found, and ignores duplicates.
Signature of the elf_lookup() and elf_obj_lookup() functions changed
to split result/error code and the symbol address returned.
Otherwise, it is impossible to return zero address as the symbol
value, to MD relocation code. This explains the mechanical changes in
elf_machdep.c sources.
The powerpc64 R_PPC_JMP_SLOT handler did not checked error from the
lookup() call, the patch leaves the code as is (untested).
Reported by: glebius
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Diffstat (limited to 'sys/amd64')
-rw-r--r-- | sys/amd64/amd64/elf_machdep.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c index d1cffd9..d961f09 100644 --- a/sys/amd64/amd64/elf_machdep.c +++ b/sys/amd64/amd64/elf_machdep.c @@ -168,6 +168,7 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, Elf_Size rtype, symidx; const Elf_Rel *rel; const Elf_Rela *rela; + int error; switch (type) { case ELF_RELOC_REL: @@ -203,29 +204,29 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, break; case R_X86_64_64: /* S + A */ - addr = lookup(lf, symidx, 1); + error = lookup(lf, symidx, 1, &addr); val = addr + addend; - if (addr == 0) + if (error != 0) return -1; if (*where != val) *where = val; break; case R_X86_64_PC32: /* S + A - P */ - addr = lookup(lf, symidx, 1); + error = lookup(lf, symidx, 1, &addr); where32 = (Elf32_Addr *)where; val32 = (Elf32_Addr)(addr + addend - (Elf_Addr)where); - if (addr == 0) + if (error != 0) return -1; if (*where32 != val32) *where32 = val32; break; case R_X86_64_32S: /* S + A sign extend */ - addr = lookup(lf, symidx, 1); + error = lookup(lf, symidx, 1, &addr); val32 = (Elf32_Addr)(addr + addend); where32 = (Elf32_Addr *)where; - if (addr == 0) + if (error != 0) return -1; if (*where32 != val32) *where32 = val32; @@ -242,8 +243,8 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, case R_X86_64_GLOB_DAT: /* S */ case R_X86_64_JMP_SLOT: /* XXX need addend + offset */ - addr = lookup(lf, symidx, 1); - if (addr == 0) + error = lookup(lf, symidx, 1, &addr); + if (error != 0) return -1; if (*where != addr) *where = addr; |