am 2e44e464: am 9c4783b1: Merge changes I713800ce,I1dea46c3

* commit '2e44e4649a5ebf00e7ab1bc5ff32f6bd79845347':
  Refactor soinfo::relocate
  Add ARM_IRELATIVE relocation
This commit is contained in:
Dmitriy Ivanov 2015-01-09 23:55:42 +00:00 committed by Android Git Automerger
commit dde3d83a6f
3 changed files with 115 additions and 102 deletions

View File

@ -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

View File

@ -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<ElfW(Addr)*>(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<ElfW(Addr)*>(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<ElfW(Addr)*>(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<ElfW(Addr)*>(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<ElfW(Addr)*>(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<ElfW(Addr)*>(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<size_t>(reloc),
static_cast<size_t>(sym_addr + rela->r_addend), sym_name);
*reinterpret_cast<ElfW(Addr)*>(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<size_t>(reloc),
static_cast<size_t>(sym_addr + rela->r_addend), sym_name);
*reinterpret_cast<ElfW(Addr)*>(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<size_t>(reloc),
static_cast<size_t>(base));
*reinterpret_cast<ElfW(Addr)*>(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<ElfW(Addr)*>(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<ElfW(Addr)*>(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<ElfW(Addr)*>(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<void*>(reloc), reinterpret_cast<void*>(base));
*reinterpret_cast<ElfW(Addr)*>(reloc) += base;
break;
case R_GENERIC_IRELATIVE:
count_relocation(kRelocRelative);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "RELO IRELATIVE %p <- %p", reinterpret_cast<void*>(reloc), reinterpret_cast<void*>(base));
*reinterpret_cast<ElfW(Addr)*>(reloc) = call_ifunc_resolver(base + *reinterpret_cast<ElfW(Addr)*>(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<ElfW(Addr)*>(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<ElfW(Addr)*>(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<void*>(reloc), reinterpret_cast<void*>(base));
*reinterpret_cast<ElfW(Addr)*>(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<void*>(reloc), reinterpret_cast<void*>(base));
*reinterpret_cast<ElfW(Addr)*>(reloc) = call_ifunc_resolver(base + *reinterpret_cast<ElfW(Addr)*>(reloc));
break;
#endif
default:
DL_ERR("unknown reloc type %d @ %p (%zu)", type, rel, idx);
return -1;

54
linker/linker_relocs.h Normal file
View File

@ -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 <elf.h>
#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