From a137f539801a05d395cfef1dd7a61b6fd8c36330 Mon Sep 17 00:00:00 2001 From: Dmitriy Ivanov Date: Thu, 8 Jan 2015 22:22:27 -0800 Subject: [PATCH 1/2] Add ARM_IRELATIVE relocation Bug: 17399706 Change-Id: I1dea46c3a3c4572558e718283489c323794176c7 --- libc/arch-arm/include/machine/elf_machdep.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libc/arch-arm/include/machine/elf_machdep.h b/libc/arch-arm/include/machine/elf_machdep.h index 97d8434ae..542f63821 100644 --- a/libc/arch-arm/include/machine/elf_machdep.h +++ b/libc/arch-arm/include/machine/elf_machdep.h @@ -102,6 +102,8 @@ /* 112-127 are reserved for private experiments. */ +#define R_ARM_IRELATIVE 160 + #define R_ARM_RXPC25 249 #define R_ARM_RSBREL32 250 #define R_ARM_THM_RPC22 251 From cefef7dab67472d59d45ef1d002a20edf8edde75 Mon Sep 17 00:00:00 2001 From: Dmitriy Ivanov Date: Thu, 8 Jan 2015 23:30:15 -0800 Subject: [PATCH 2/2] Refactor soinfo::relocate Move common relocation types outside of ifdefs Change-Id: I713800ce123a18178b5ac80c0b3c7bd6b21a02c2 --- linker/linker.cpp | 161 +++++++++++++++-------------------------- linker/linker_relocs.h | 54 ++++++++++++++ 2 files changed, 113 insertions(+), 102 deletions(-) create mode 100644 linker/linker_relocs.h diff --git a/linker/linker.cpp b/linker/linker.cpp index e2f514e21..e0fec0f08 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -53,6 +53,7 @@ #include "linker_debug.h" #include "linker_environ.h" #include "linker_phdr.h" +#include "linker_relocs.h" #include "linker_allocator.h" /* >>> IMPORTANT NOTE - READ ME BEFORE MODIFYING <<< @@ -1288,7 +1289,7 @@ int soinfo::relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& glob const char* sym_name = nullptr; DEBUG("Processing '%s' relocation at index %zd", name, idx); - if (type == 0) { // R_*_NONE + if (type == R_GENERIC_NONE) { continue; } @@ -1358,21 +1359,40 @@ int soinfo::relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& glob } switch (type) { -#if defined(__aarch64__) - case R_AARCH64_JUMP_SLOT: + case R_GENERIC_JUMP_SLOT: count_relocation(kRelocAbsolute); MARK(rela->r_offset); TRACE_TYPE(RELO, "RELO JMP_SLOT %16llx <- %16llx %s\n", reloc, (sym_addr + rela->r_addend), sym_name); *reinterpret_cast(reloc) = (sym_addr + rela->r_addend); break; - case R_AARCH64_GLOB_DAT: + case R_GENERIC_GLOB_DAT: count_relocation(kRelocAbsolute); MARK(rela->r_offset); TRACE_TYPE(RELO, "RELO GLOB_DAT %16llx <- %16llx %s\n", reloc, (sym_addr + rela->r_addend), sym_name); *reinterpret_cast(reloc) = (sym_addr + rela->r_addend); break; + case R_GENERIC_RELATIVE: + count_relocation(kRelocRelative); + MARK(rela->r_offset); + if (sym) { + DL_ERR("error: encountered _RELATIVE relocation with a symbol"); + return -1; + } + TRACE_TYPE(RELO, "RELO RELATIVE %16llx <- %16llx\n", + reloc, (base + rela->r_addend)); + *reinterpret_cast(reloc) = (base + rela->r_addend); + break; + + case R_GENERIC_IRELATIVE: + count_relocation(kRelocRelative); + MARK(rela->r_offset); + TRACE_TYPE(RELO, "RELO IRELATIVE %16llx <- %16llx\n", reloc, (base + rela->r_addend)); + *reinterpret_cast(reloc) = call_ifunc_resolver(base + rela->r_addend); + break; + +#if defined(__aarch64__) case R_AARCH64_ABS64: count_relocation(kRelocAbsolute); MARK(rela->r_offset); @@ -1452,25 +1472,6 @@ int soinfo::relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& glob } break; - case R_AARCH64_RELATIVE: - count_relocation(kRelocRelative); - MARK(rela->r_offset); - if (sym) { - DL_ERR("odd RELATIVE form..."); - return -1; - } - TRACE_TYPE(RELO, "RELO RELATIVE %16llx <- %16llx\n", - reloc, (base + rela->r_addend)); - *reinterpret_cast(reloc) = (base + rela->r_addend); - break; - - case R_AARCH64_IRELATIVE: - count_relocation(kRelocRelative); - MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO IRELATIVE %16llx <- %16llx\n", reloc, (base + rela->r_addend)); - *reinterpret_cast(reloc) = call_ifunc_resolver(base + rela->r_addend); - break; - case R_AARCH64_COPY: /* * ET_EXEC is not supported so this should not happen. @@ -1492,37 +1493,6 @@ int soinfo::relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& glob reloc, (sym_addr + rela->r_addend), rela->r_offset); break; #elif defined(__x86_64__) - case R_X86_64_JUMP_SLOT: - count_relocation(kRelocAbsolute); - MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO JMP_SLOT %08zx <- %08zx %s", static_cast(reloc), - static_cast(sym_addr + rela->r_addend), sym_name); - *reinterpret_cast(reloc) = sym_addr + rela->r_addend; - break; - case R_X86_64_GLOB_DAT: - count_relocation(kRelocAbsolute); - MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO GLOB_DAT %08zx <- %08zx %s", static_cast(reloc), - static_cast(sym_addr + rela->r_addend), sym_name); - *reinterpret_cast(reloc) = sym_addr + rela->r_addend; - break; - case R_X86_64_RELATIVE: - count_relocation(kRelocRelative); - MARK(rela->r_offset); - if (sym) { - DL_ERR("odd RELATIVE form..."); - return -1; - } - TRACE_TYPE(RELO, "RELO RELATIVE %08zx <- +%08zx", static_cast(reloc), - static_cast(base)); - *reinterpret_cast(reloc) = base + rela->r_addend; - break; - case R_X86_64_IRELATIVE: - count_relocation(kRelocRelative); - MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO IRELATIVE %16llx <- %16llx\n", reloc, (base + rela->r_addend)); - *reinterpret_cast(reloc) = call_ifunc_resolver(base + rela->r_addend); - break; case R_X86_64_32: count_relocation(kRelocRelative); MARK(rela->r_offset); @@ -1566,7 +1536,7 @@ int soinfo::relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global const char* sym_name = nullptr; DEBUG("Processing '%s' relocation at index %zd", name, idx); - if (type == 0) { // R_*_NONE + if (type == R_GENERIC_NONE) { continue; } @@ -1598,21 +1568,21 @@ int soinfo::relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global */ switch (type) { +#if !defined(__mips__) + case R_GENERIC_JUMP_SLOT: + case R_GENERIC_GLOB_DAT: + case R_GENERIC_RELATIVE: + case R_GENERIC_IRELATIVE: +#endif + #if defined(__arm__) - case R_ARM_JUMP_SLOT: - case R_ARM_GLOB_DAT: - case R_ARM_ABS32: - case R_ARM_RELATIVE: /* Don't care. */ + case R_ARM_ABS32: /* Don't care. */ // sym_addr was initialized to be zero above or relocation // code below does not care about value of sym_addr. // No need to do anything. break; #elif defined(__i386__) - case R_386_JMP_SLOT: - case R_386_GLOB_DAT: case R_386_32: - case R_386_RELATIVE: /* Don't care. */ - case R_386_IRELATIVE: // sym_addr was initialized to be zero above or relocation // code below does not care about value of sym_addr. // No need to do anything. @@ -1638,19 +1608,42 @@ int soinfo::relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global } switch (type) { -#if defined(__arm__) - case R_ARM_JUMP_SLOT: +#if !defined(__mips__) + case R_GENERIC_JUMP_SLOT: count_relocation(kRelocAbsolute); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO JMP_SLOT %08x <- %08x %s", reloc, sym_addr, sym_name); *reinterpret_cast(reloc) = sym_addr; break; - case R_ARM_GLOB_DAT: + + case R_GENERIC_GLOB_DAT: count_relocation(kRelocAbsolute); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO GLOB_DAT %08x <- %08x %s", reloc, sym_addr, sym_name); *reinterpret_cast(reloc) = sym_addr; break; + + case R_GENERIC_RELATIVE: + count_relocation(kRelocRelative); + MARK(rel->r_offset); + if (sym) { + DL_ERR("odd RELATIVE form..."); + return -1; + } + TRACE_TYPE(RELO, "RELO RELATIVE %p <- +%p", + reinterpret_cast(reloc), reinterpret_cast(base)); + *reinterpret_cast(reloc) += base; + break; + + case R_GENERIC_IRELATIVE: + count_relocation(kRelocRelative); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "RELO IRELATIVE %p <- %p", reinterpret_cast(reloc), reinterpret_cast(base)); + *reinterpret_cast(reloc) = call_ifunc_resolver(base + *reinterpret_cast(reloc)); + break; +#endif + +#if defined(__arm__) case R_ARM_ABS32: count_relocation(kRelocAbsolute); MARK(rel->r_offset); @@ -1677,18 +1670,6 @@ int soinfo::relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global DL_ERR("%s R_ARM_COPY relocations are not supported", name); return -1; #elif defined(__i386__) - case R_386_JMP_SLOT: - count_relocation(kRelocAbsolute); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO JMP_SLOT %08x <- %08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast(reloc) = sym_addr; - break; - case R_386_GLOB_DAT: - count_relocation(kRelocAbsolute); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO GLOB_DAT %08x <- %08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast(reloc) = sym_addr; - break; case R_386_32: count_relocation(kRelocRelative); MARK(rel->r_offset); @@ -1727,30 +1708,6 @@ int soinfo::relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global break; #endif -#if defined(__arm__) - case R_ARM_RELATIVE: -#elif defined(__i386__) - case R_386_RELATIVE: -#endif - count_relocation(kRelocRelative); - MARK(rel->r_offset); - if (sym) { - DL_ERR("odd RELATIVE form..."); - return -1; - } - TRACE_TYPE(RELO, "RELO RELATIVE %p <- +%p", - reinterpret_cast(reloc), reinterpret_cast(base)); - *reinterpret_cast(reloc) += base; - break; -#if defined(__i386__) - case R_386_IRELATIVE: - count_relocation(kRelocRelative); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO IRELATIVE %p <- %p", reinterpret_cast(reloc), reinterpret_cast(base)); - *reinterpret_cast(reloc) = call_ifunc_resolver(base + *reinterpret_cast(reloc)); - break; -#endif - default: DL_ERR("unknown reloc type %d @ %p (%zu)", type, rel, idx); return -1; diff --git a/linker/linker_relocs.h b/linker/linker_relocs.h new file mode 100644 index 000000000..12c14974c --- /dev/null +++ b/linker/linker_relocs.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LINKER_RELOCS_H +#define __LINKER_RELOCS_H + +#include + +#define R_GENERIC_NONE 0 // R_*_NONE is always 0 + +#if defined (__aarch64__) + +#define R_GENERIC_JUMP_SLOT R_AARCH64_JUMP_SLOT +#define R_GENERIC_GLOB_DAT R_AARCH64_GLOB_DAT +#define R_GENERIC_RELATIVE R_AARCH64_RELATIVE +#define R_GENERIC_IRELATIVE R_AARCH64_IRELATIVE + +#elif defined (__arm__) + +#define R_GENERIC_JUMP_SLOT R_ARM_JUMP_SLOT +#define R_GENERIC_GLOB_DAT R_ARM_GLOB_DAT +#define R_GENERIC_RELATIVE R_ARM_RELATIVE +#define R_GENERIC_IRELATIVE R_ARM_IRELATIVE + +#elif defined (__i386__) + +#define R_GENERIC_JUMP_SLOT R_386_JMP_SLOT +#define R_GENERIC_GLOB_DAT R_386_GLOB_DAT +#define R_GENERIC_RELATIVE R_386_RELATIVE +#define R_GENERIC_IRELATIVE R_386_IRELATIVE + +#elif defined (__x86_64__) + +#define R_GENERIC_JUMP_SLOT R_X86_64_JUMP_SLOT +#define R_GENERIC_GLOB_DAT R_X86_64_GLOB_DAT +#define R_GENERIC_RELATIVE R_X86_64_RELATIVE +#define R_GENERIC_IRELATIVE R_X86_64_IRELATIVE + +#endif + +#endif // __LINKER_RELOCS_H