summaryrefslogtreecommitdiffstats
path: root/third_party/android_crazy_linker
diff options
context:
space:
mode:
authorsimonb <simonb@chromium.org>2015-06-08 11:11:26 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-08 18:11:58 +0000
commite5acfbccce659364606758b687b90488e2f44be2 (patch)
tree835dfbff876a1c7b4430ec79601d0c18ad42704a /third_party/android_crazy_linker
parent1269c367fc73390f0cf22432597d708937cee3ba (diff)
downloadchromium_src-e5acfbccce659364606758b687b90488e2f44be2.zip
chromium_src-e5acfbccce659364606758b687b90488e2f44be2.tar.gz
chromium_src-e5acfbccce659364606758b687b90488e2f44be2.tar.bz2
crazy linker: convert relocation unpacking to Android style.
Replace relocation unpacking code with functions that understand the packing format generated by the Android relocation packer. Switch to using the Android relocation packer when packing during build. BUG=385553 Review URL: https://codereview.chromium.org/1072533002 Cr-Commit-Position: refs/heads/master@{#333293}
Diffstat (limited to 'third_party/android_crazy_linker')
-rw-r--r--third_party/android_crazy_linker/README.chromium2
-rw-r--r--third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.cpp2
-rw-r--r--third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp630
-rw-r--r--third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h110
-rw-r--r--third_party/android_crazy_linker/src/src/crazy_linker_leb128.h49
-rw-r--r--third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp108
-rw-r--r--third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h5
7 files changed, 419 insertions, 487 deletions
diff --git a/third_party/android_crazy_linker/README.chromium b/third_party/android_crazy_linker/README.chromium
index 655c069..97147d2 100644
--- a/third_party/android_crazy_linker/README.chromium
+++ b/third_party/android_crazy_linker/README.chromium
@@ -78,3 +78,5 @@ Local Modifications:
- Fix link_map_.l_addr (was load address, should be load bias).
+- Convert packed relocation code to handle Android packed relocations.
+
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.cpp
index a2e5fab..e265ac3 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.cpp
@@ -193,7 +193,7 @@ bool ElfLoader::ReserveAddressSpace(Error* error) {
return false;
}
- uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
+ uint8_t* addr = NULL;
int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
// Support loading at a fixed address.
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp
index 559c09e..5691ed3 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp
@@ -4,6 +4,7 @@
#include "crazy_linker_elf_relocations.h"
+#include <assert.h>
#include <errno.h>
#include "crazy_linker_debug.h"
@@ -32,6 +33,23 @@
#define DT_FLAGS 30
#endif
+// Extension dynamic tags for Android packed relocations.
+#ifndef DT_LOOS
+#define DT_LOOS 0x6000000d
+#endif
+#ifndef DT_ANDROID_REL
+#define DT_ANDROID_REL (DT_LOOS + 2)
+#endif
+#ifndef DT_ANDROID_RELSZ
+#define DT_ANDROID_RELSZ (DT_LOOS + 3)
+#endif
+#ifndef DT_ANDROID_RELA
+#define DT_ANDROID_RELA (DT_LOOS + 4)
+#endif
+#ifndef DT_ANDROID_RELASZ
+#define DT_ANDROID_RELASZ (DT_LOOS + 5)
+#endif
+
// Processor-specific relocation types supported by the linker.
#ifdef __arm__
@@ -168,9 +186,6 @@ bool ElfRelocations::Init(const ElfView* view, Error* error) {
phdr_ = view->phdr();
phdr_count_ = view->phdr_count();
load_bias_ = view->load_bias();
-#if defined(__arm__) || defined(__aarch64__)
- packed_relocations_ = view->packed_relocations();
-#endif
// We handle only Rel or Rela, but not both. If DT_RELA or DT_RELASZ
// then we require DT_PLTREL to agree.
@@ -231,6 +246,38 @@ bool ElfRelocations::Init(const ElfView* view, Error* error) {
else
has_rel_relocations = true;
break;
+ case DT_ANDROID_RELA:
+ case DT_ANDROID_REL:
+ RLOG(" %s addr=%p\n",
+ (tag == DT_ANDROID_RELA) ? "DT_ANDROID_RELA" : "DT_ANDROID_REL",
+ dyn_addr);
+ if (android_relocations_) {
+ *error = "Unsupported DT_ANDROID_RELA/DT_ANDROID_REL "
+ "combination in dynamic section";
+ return false;
+ }
+ android_relocations_ = reinterpret_cast<uint8_t*>(dyn_addr);
+ if (tag == DT_ANDROID_RELA)
+ has_rela_relocations = true;
+ else
+ has_rel_relocations = true;
+ break;
+ case DT_ANDROID_RELASZ:
+ case DT_ANDROID_RELSZ:
+ RLOG(" %s size=%d\n",
+ (tag == DT_ANDROID_RELASZ)
+ ? "DT_ANDROID_RELASZ" : "DT_ANDROID_RELSZ", dyn_addr);
+ if (android_relocations_size_) {
+ *error = "Unsupported DT_ANDROID_RELASZ/DT_ANDROID_RELSZ "
+ "combination in dyn section";
+ return false;
+ }
+ android_relocations_size_ = dyn_value;
+ if (tag == DT_ANDROID_RELASZ)
+ has_rela_relocations = true;
+ else
+ has_rel_relocations = true;
+ break;
case DT_PLTGOT:
// Only used on MIPS currently. Could also be used on other platforms
// when lazy binding (i.e. RTLD_LAZY) is implemented.
@@ -250,7 +297,7 @@ bool ElfRelocations::Init(const ElfView* view, Error* error) {
has_text_relocations_ = true;
if (dyn_value & DF_SYMBOLIC)
has_symbolic_ = true;
- RLOG(" DT_FLAGS has_text_relocations=%s has_symbolic=%s\n",
+ RLOG(" DT_FLAGS has_text_relocations=%s has_symbolic=%s\n",
has_text_relocations_ ? "true" : "false",
has_symbolic_ ? "true" : "false");
break;
@@ -276,7 +323,8 @@ bool ElfRelocations::Init(const ElfView* view, Error* error) {
}
if (has_rel_relocations && has_rela_relocations) {
- *error = "Combining DT_REL and DT_RELA is not currently supported";
+ *error = "Combining relocations with and without addends is not "
+ "currently supported";
return false;
}
@@ -290,11 +338,13 @@ bool ElfRelocations::Init(const ElfView* view, Error* error) {
}
if (relocations_type_ == DT_REL && has_rela_relocations) {
- *error = "Found DT_RELA in dyn section, but DT_PLTREL is DT_REL";
+ *error = "Found relocations with addends in dyn section, "
+ "but DT_PLTREL is DT_REL";
return false;
}
if (relocations_type_ == DT_RELA && has_rel_relocations) {
- *error = "Found DT_REL in dyn section, but DT_PLTREL is DT_RELA";
+ *error = "Found relocations without addends in dyn section, "
+ "but DT_PLTREL is DT_RELA";
return false;
}
@@ -313,10 +363,8 @@ bool ElfRelocations::ApplyAll(const ElfSymbols* symbols,
}
}
-#if defined(__arm__) || defined(__aarch64__)
- if (!ApplyPackedRelocations(error))
+ if (!ApplyAndroidRelocations(symbols, resolver, error))
return false;
-#endif
if (relocations_type_ == DT_REL) {
if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_),
@@ -364,142 +412,189 @@ bool ElfRelocations::ApplyAll(const ElfSymbols* symbols,
return true;
}
-#if defined(__arm__) || defined(__aarch64__)
+// Helper class for Android packed relocations. Encapsulates the packing
+// flags used by Android for packed relocation groups.
+class AndroidPackedRelocationGroupFlags {
+ public:
+ explicit AndroidPackedRelocationGroupFlags(size_t flags) : flags_(flags) { }
+
+ bool is_relocation_grouped_by_info() const {
+ return hasFlag(RELOCATION_GROUPED_BY_INFO_FLAG);
+ }
+ bool is_relocation_grouped_by_offset_delta() const {
+ return hasFlag(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG);
+ }
+ bool is_relocation_grouped_by_addend() const {
+ return hasFlag(RELOCATION_GROUPED_BY_ADDEND_FLAG);
+ }
+ bool is_relocation_group_has_addend() const {
+ return hasFlag(RELOCATION_GROUP_HAS_ADDEND_FLAG);
+ }
+
+ private:
+ bool hasFlag(size_t flag) const { return (flags_ & flag) != 0; }
-bool ElfRelocations::ForEachPackedRel(const uint8_t* packed_relocations,
- RelRelocationHandler handler,
- void* opaque) {
- Leb128Decoder decoder(packed_relocations);
+ static const size_t RELOCATION_GROUPED_BY_INFO_FLAG = 1 << 0;
+ static const size_t RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 1 << 1;
+ static const size_t RELOCATION_GROUPED_BY_ADDEND_FLAG = 1 << 2;
+ static const size_t RELOCATION_GROUP_HAS_ADDEND_FLAG = 1 << 3;
- // Find the count of pairs and the start address.
- size_t pairs = decoder.Dequeue();
- const ELF::Addr start_address = decoder.Dequeue();
+ const size_t flags_;
+};
- // Emit initial relative relocation.
- ELF::Rel relocation;
- relocation.r_offset = start_address;
- relocation.r_info = ELF_R_INFO(0, RELATIVE_RELOCATION_CODE);
- const ELF::Addr sym_addr = 0;
- const bool resolved = false;
- if (!handler(this, &relocation, opaque))
- return false;
+bool ElfRelocations::ForEachAndroidRelocation(RelocationHandler handler,
+ void* opaque) {
+ // Skip over the "APS2" signature.
+ Sleb128Decoder decoder(android_relocations_ + 4,
+ android_relocations_size_ - 4);
+
+ // Unpacking into a relocation with addend, both for REL and RELA, is
+ // convenient at this point. If REL, the handler needs to take care of
+ // any conversion before use.
+ ELF::Rela relocation;
+ memset(&relocation, 0, sizeof(relocation));
+
+ // Read the relocation count and initial offset.
+ const size_t relocation_count = decoder.pop_front();
+ relocation.r_offset = decoder.pop_front();
+
+ LOG("%s: relocation_count=%d, initial r_offset=%p\n",
+ __FUNCTION__,
+ relocation_count,
+ relocation.r_offset);
+
+ size_t relocations_handled = 0;
+ while (relocations_handled < relocation_count) {
+ // Read the start of the group header to obtain its size and flags.
+ const size_t group_size = decoder.pop_front();
+ AndroidPackedRelocationGroupFlags group_flags(decoder.pop_front());
+
+ // Read other group header fields, depending on the flags read above.
+ size_t group_r_offset_delta = 0;
+ if (group_flags.is_relocation_grouped_by_offset_delta())
+ group_r_offset_delta = decoder.pop_front();
+
+ if (group_flags.is_relocation_grouped_by_info())
+ relocation.r_info = decoder.pop_front();
+
+ if (group_flags.is_relocation_group_has_addend() &&
+ group_flags.is_relocation_grouped_by_addend())
+ relocation.r_addend += decoder.pop_front();
+ else if (!group_flags.is_relocation_group_has_addend())
+ relocation.r_addend = 0;
+
+ // Expand the group into individual relocations.
+ for (size_t group_index = 0; group_index < group_size; group_index++) {
+ if (group_flags.is_relocation_grouped_by_offset_delta())
+ relocation.r_offset += group_r_offset_delta;
+ else
+ relocation.r_offset += decoder.pop_front();
- size_t unpacked_count = 1;
+ if (!group_flags.is_relocation_grouped_by_info())
+ relocation.r_info = decoder.pop_front();
- // Emit relocations for each count-delta pair.
- while (pairs) {
- size_t count = decoder.Dequeue();
- const size_t delta = decoder.Dequeue();
+ if (group_flags.is_relocation_group_has_addend() &&
+ !group_flags.is_relocation_grouped_by_addend())
+ relocation.r_addend += decoder.pop_front();
- // Emit count relative relocations with delta offset.
- while (count) {
- relocation.r_offset += delta;
- if (!handler(this, &relocation, opaque))
+ // Pass the relocation to the supplied handler function. If the handler
+ // returns false we view this as failure and return false to our caller.
+ if (!handler(this, &relocation, opaque)) {
+ LOG("%s: failed handling relocation %d\n",
+ __FUNCTION__,
+ relocations_handled);
return false;
- unpacked_count++;
- count--;
+ }
+
+ relocations_handled++;
}
- pairs--;
}
- RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count);
+ LOG("%s: relocations_handled=%d\n", __FUNCTION__, relocations_handled);
return true;
}
-bool ElfRelocations::ForEachPackedRela(const uint8_t* packed_relocations,
- RelaRelocationHandler handler,
- void* opaque) {
- Sleb128Decoder decoder(packed_relocations);
+namespace {
- // Find the count of pairs.
- size_t pairs = decoder.Dequeue();
+// Validate the Android packed relocations signature.
+bool IsValidAndroidPackedRelocations(const uint8_t* android_relocations,
+ size_t android_relocations_size) {
+ if (android_relocations_size < 4)
+ return false;
- ELF::Addr offset = 0;
- ELF::Sxword addend = 0;
+ // Check for an initial APS2 Android packed relocations header.
+ return (android_relocations[0] == 'A' &&
+ android_relocations[1] == 'P' &&
+ android_relocations[2] == 'S' &&
+ android_relocations[3] == '2');
+}
- const ELF::Addr sym_addr = 0;
- const bool resolved = false;
+// Narrow a Rela to its equivalent Rel. The r_addend field in the input
+// Rela must be zero.
+void ConvertRelaToRel(const ELF::Rela* rela, ELF::Rel* rel) {
+ assert(rela->r_addend == 0);
+ rel->r_offset = rela->r_offset;
+ rel->r_info = rela->r_info;
+}
- size_t unpacked_count = 0;
+} // namespace
- // Emit relocations for each deltas pair.
- while (pairs) {
- offset += decoder.Dequeue();
- addend += decoder.Dequeue();
+// Args for ApplyAndroidRelocation handler function.
+struct ApplyAndroidRelocationArgs {
+ ELF::Addr relocations_type;
+ const ElfSymbols* symbols;
+ ElfRelocations::SymbolResolver* resolver;
+ Error* error;
+};
- ELF::Rela relocation;
- relocation.r_offset = offset;
- relocation.r_info = ELF_R_INFO(0, RELATIVE_RELOCATION_CODE);
- relocation.r_addend = addend;
- if (!handler(this, &relocation, opaque))
- return false;
- unpacked_count++;
- pairs--;
+// Static ForEachAndroidRelocation() handler.
+bool ElfRelocations::ApplyAndroidRelocation(ElfRelocations* relocations,
+ const ELF::Rela* relocation,
+ void* opaque) {
+ // Unpack args from opaque.
+ ApplyAndroidRelocationArgs* args =
+ reinterpret_cast<ApplyAndroidRelocationArgs*>(opaque);
+ const ELF::Addr relocations_type = args->relocations_type;
+ const ElfSymbols* symbols = args->symbols;
+ ElfRelocations::SymbolResolver* resolver = args->resolver;
+ Error* error = args->error;
+
+ // For REL relocations, convert from RELA to REL and apply the conversion.
+ // For RELA relocations, apply RELA directly.
+ if (relocations_type == DT_REL) {
+ ELF::Rel converted;
+ ConvertRelaToRel(relocation, &converted);
+ return relocations->ApplyRelReloc(&converted, symbols, resolver, error);
}
- RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count);
- return true;
-}
-
-bool ElfRelocations::ApplyPackedRel(ElfRelocations* relocations,
- const ELF::Rel* relocation,
- void* opaque) {
- Error* error = reinterpret_cast<Error*>(opaque);
- const ELF::Addr sym_addr = 0;
- const bool resolved = false;
- return relocations->ApplyRelReloc(relocation, sym_addr, resolved, error);
-}
+ if (relocations_type == DT_RELA)
+ return relocations->ApplyRelaReloc(relocation, symbols, resolver, error);
-bool ElfRelocations::ApplyPackedRels(const uint8_t* packed_relocations,
- Error* error) {
- void* opaque = error;
- return ForEachPackedRel(packed_relocations, &ApplyPackedRel, opaque);
-}
-
-bool ElfRelocations::ApplyPackedRela(ElfRelocations* relocations,
- const ELF::Rela* relocation,
- void* opaque) {
- Error* error = reinterpret_cast<Error*>(opaque);
- const ELF::Addr sym_addr = 0;
- const bool resolved = false;
- return relocations->ApplyRelaReloc(relocation, sym_addr, resolved, error);
-}
-
-bool ElfRelocations::ApplyPackedRelas(const uint8_t* packed_relocations,
- Error* error) {
- void* opaque = error;
- return ForEachPackedRela(packed_relocations, &ApplyPackedRela, opaque);
+ return true;
}
-bool ElfRelocations::ApplyPackedRelocations(Error* error) {
- if (!packed_relocations_)
+bool ElfRelocations::ApplyAndroidRelocations(const ElfSymbols* symbols,
+ SymbolResolver* resolver,
+ Error* error) {
+ if (!android_relocations_)
return true;
- // Check for an initial APR1 header, packed relocations.
- if (packed_relocations_[0] == 'A' &&
- packed_relocations_[1] == 'P' &&
- packed_relocations_[2] == 'R' &&
- packed_relocations_[3] == '1') {
- return ApplyPackedRels(packed_relocations_ + 4, error);
- }
-
- // Check for an initial APA1 header, packed relocations with addend.
- if (packed_relocations_[0] == 'A' &&
- packed_relocations_[1] == 'P' &&
- packed_relocations_[2] == 'A' &&
- packed_relocations_[3] == '1') {
- return ApplyPackedRelas(packed_relocations_ + 4, error);
- }
+ if (!IsValidAndroidPackedRelocations(android_relocations_,
+ android_relocations_size_))
+ return false;
- error->Format("Bad packed relocations ident, expected APR1 or APA1");
- return false;
+ ApplyAndroidRelocationArgs args;
+ args.relocations_type = relocations_type_;
+ args.symbols = symbols;
+ args.resolver = resolver;
+ args.error = error;
+ return ForEachAndroidRelocation(&ApplyAndroidRelocation, &args);
}
-#endif // __arm__ || __aarch64__
-bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela,
- ELF::Addr sym_addr,
- bool resolved CRAZY_UNUSED,
- Error* error) {
+bool ElfRelocations::ApplyResolvedRelaReloc(const ELF::Rela* rela,
+ ELF::Addr sym_addr,
+ bool resolved CRAZY_UNUSED,
+ Error* error) {
const ELF::Word rela_type = ELF_R_TYPE(rela->r_info);
const ELF::Word CRAZY_UNUSED rela_symbol = ELF_R_SYM(rela->r_info);
const ELF::Sword CRAZY_UNUSED addend = rela->r_addend;
@@ -591,10 +686,10 @@ bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela,
return true;
}
-bool ElfRelocations::ApplyRelReloc(const ELF::Rel* rel,
- ELF::Addr sym_addr,
- bool resolved CRAZY_UNUSED,
- Error* error) {
+bool ElfRelocations::ApplyResolvedRelReloc(const ELF::Rel* rel,
+ ELF::Addr sym_addr,
+ bool resolved CRAZY_UNUSED,
+ Error* error) {
const ELF::Word rel_type = ELF_R_TYPE(rel->r_info);
const ELF::Word CRAZY_UNUSED rel_symbol = ELF_R_SYM(rel->r_info);
@@ -752,6 +847,43 @@ bool ElfRelocations::ResolveSymbol(ELF::Word rel_type,
return false;
}
+bool ElfRelocations::ApplyRelReloc(const ELF::Rel* rel,
+ const ElfSymbols* symbols,
+ SymbolResolver* resolver,
+ Error* error) {
+ const ELF::Word rel_type = ELF_R_TYPE(rel->r_info);
+ const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info);
+
+ ELF::Addr sym_addr = 0;
+ ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_);
+ RLOG(" reloc=%p offset=%p type=%d symbol=%d\n",
+ reloc,
+ rel->r_offset,
+ rel_type,
+ rel_symbol);
+
+ if (rel_type == 0)
+ return true;
+
+ bool resolved = false;
+
+ // If this is a symbolic relocation, compute the symbol's address.
+ if (__builtin_expect(rel_symbol != 0, 0)) {
+ if (!ResolveSymbol(rel_type,
+ rel_symbol,
+ symbols,
+ resolver,
+ reloc,
+ &sym_addr,
+ error)) {
+ return false;
+ }
+ resolved = true;
+ }
+
+ return ApplyResolvedRelReloc(rel, sym_addr, resolved, error);
+}
+
bool ElfRelocations::ApplyRelRelocs(const ELF::Rel* rel,
size_t rel_count,
const ElfSymbols* symbols,
@@ -763,43 +895,50 @@ bool ElfRelocations::ApplyRelRelocs(const ELF::Rel* rel,
return true;
for (size_t rel_n = 0; rel_n < rel_count; rel++, rel_n++) {
- const ELF::Word rel_type = ELF_R_TYPE(rel->r_info);
- const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info);
+ RLOG(" Relocation %d of %d:\n", rel_n + 1, rel_count);
- ELF::Addr sym_addr = 0;
- ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_);
- RLOG(" %d/%d reloc=%p offset=%p type=%d symbol=%d\n",
- rel_n + 1,
- rel_count,
- reloc,
- rel->r_offset,
- rel_type,
- rel_symbol);
-
- if (rel_type == 0)
- continue;
+ if (!ApplyRelReloc(rel, symbols, resolver, error))
+ return false;
+ }
- bool resolved = false;
+ return true;
+}
- // If this is a symbolic relocation, compute the symbol's address.
- if (__builtin_expect(rel_symbol != 0, 0)) {
- if (!ResolveSymbol(rel_type,
- rel_symbol,
- symbols,
- resolver,
- reloc,
- &sym_addr,
- error)) {
- return false;
- }
- resolved = true;
- }
+bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela,
+ const ElfSymbols* symbols,
+ SymbolResolver* resolver,
+ Error* error) {
+ const ELF::Word rel_type = ELF_R_TYPE(rela->r_info);
+ const ELF::Word rel_symbol = ELF_R_SYM(rela->r_info);
+
+ ELF::Addr sym_addr = 0;
+ ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_);
+ RLOG(" reloc=%p offset=%p type=%d symbol=%d\n",
+ reloc,
+ rela->r_offset,
+ rel_type,
+ rel_symbol);
+
+ if (rel_type == 0)
+ return true;
- if (!ApplyRelReloc(rel, sym_addr, resolved, error))
+ bool resolved = false;
+
+ // If this is a symbolic relocation, compute the symbol's address.
+ if (__builtin_expect(rel_symbol != 0, 0)) {
+ if (!ResolveSymbol(rel_type,
+ rel_symbol,
+ symbols,
+ resolver,
+ reloc,
+ &sym_addr,
+ error)) {
return false;
+ }
+ resolved = true;
}
- return true;
+ return ApplyResolvedRelaReloc(rela, sym_addr, resolved, error);
}
bool ElfRelocations::ApplyRelaRelocs(const ELF::Rela* rela,
@@ -813,39 +952,9 @@ bool ElfRelocations::ApplyRelaRelocs(const ELF::Rela* rela,
return true;
for (size_t rel_n = 0; rel_n < rela_count; rela++, rel_n++) {
- const ELF::Word rel_type = ELF_R_TYPE(rela->r_info);
- const ELF::Word rel_symbol = ELF_R_SYM(rela->r_info);
-
- ELF::Addr sym_addr = 0;
- ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_);
- RLOG(" %d/%d reloc=%p offset=%p type=%d symbol=%d\n",
- rel_n + 1,
- rela_count,
- reloc,
- rela->r_offset,
- rel_type,
- rel_symbol);
-
- if (rel_type == 0)
- continue;
-
- bool resolved = false;
+ RLOG(" Relocation %d of %d:\n", rel_n + 1, rela_count);
- // If this is a symbolic relocation, compute the symbol's address.
- if (__builtin_expect(rel_symbol != 0, 0)) {
- if (!ResolveSymbol(rel_type,
- rel_symbol,
- symbols,
- resolver,
- reloc,
- &sym_addr,
- error)) {
- return false;
- }
- resolved = true;
- }
-
- if (!ApplyRelaReloc(rela, sym_addr, resolved, error))
+ if (!ApplyRelaReloc(rela, symbols, resolver, error))
return false;
}
@@ -941,115 +1050,90 @@ void ElfRelocations::AdjustRelocation(ELF::Word rel_type,
}
}
-#if defined(__arm__) || defined(__aarch64__)
-
-struct AdjustRelocationArgs {
- size_t src_addr;
- size_t dst_addr;
- size_t map_addr;
- size_t size;
-};
-
-template<typename Rel>
-bool ElfRelocations::RelocatePackedRelocation(ElfRelocations* relocations,
- const Rel* rel,
- void* opaque) {
- AdjustRelocationArgs* args = reinterpret_cast<AdjustRelocationArgs*>(opaque);
- const size_t src_addr = args->src_addr;
- const size_t dst_addr = args->dst_addr;
- const size_t map_addr = args->map_addr;
- const size_t size = args->size;
-
- const size_t load_bias = relocations->load_bias_;
-
+void ElfRelocations::AdjustAndroidRelocation(const ELF::Rela* relocation,
+ size_t src_addr,
+ size_t dst_addr,
+ size_t map_addr,
+ size_t size) {
+ // Add this value to each source address to get the corresponding
+ // destination address.
const size_t dst_delta = dst_addr - src_addr;
const size_t map_delta = map_addr - src_addr;
- const ELF::Word rel_type = ELF_R_TYPE(rel->r_info);
- const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info);
- ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias);
+ const ELF::Word rel_type = ELF_R_TYPE(relocation->r_info);
+ const ELF::Word rel_symbol = ELF_R_SYM(relocation->r_info);
+ ELF::Addr src_reloc =
+ static_cast<ELF::Addr>(relocation->r_offset + load_bias_);
if (rel_type == 0 || rel_symbol != 0) {
// Ignore empty and symbolic relocations
- return true;
+ return;
}
if (src_reloc < src_addr || src_reloc >= src_addr + size) {
// Ignore entries that don't relocate addresses inside the source section.
- return true;
+ return;
}
- relocations->AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta);
+ AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta);
+}
+
+// Args for ApplyAndroidRelocation handler function.
+struct RelocateAndroidRelocationArgs {
+ size_t src_addr;
+ size_t dst_addr;
+ size_t map_addr;
+ size_t size;
+};
+
+// Static ForEachAndroidRelocation() handler.
+bool ElfRelocations::RelocateAndroidRelocation(ElfRelocations* relocations,
+ const ELF::Rela* relocation,
+ void* opaque) {
+ // Unpack args from opaque, to obtain addrs and size;
+ RelocateAndroidRelocationArgs* args =
+ reinterpret_cast<RelocateAndroidRelocationArgs*>(opaque);
+ const size_t src_addr = args->src_addr;
+ const size_t dst_addr = args->dst_addr;
+ const size_t map_addr = args->map_addr;
+ const size_t size = args->size;
+
+ // Relocate the given relocation. Because the r_addend field is ignored
+ // in relocating RELA relocations we do not need to convert from REL to
+ // RELA and supply alternative relocator functions; instead we can work
+ // here directly on the RELA supplied by ForEachAndroidRelocation(), even
+ // on REL architectures.
+ relocations->AdjustAndroidRelocation(relocation,
+ src_addr,
+ dst_addr,
+ map_addr,
+ size);
return true;
}
-template bool ElfRelocations::RelocatePackedRelocation<ELF::Rel>(
- ElfRelocations* relocations, const ELF::Rel* rel, void* opaque);
+void ElfRelocations::RelocateAndroidRelocations(size_t src_addr,
+ size_t dst_addr,
+ size_t map_addr,
+ size_t size) {
+ if (!android_relocations_)
+ return;
-template bool ElfRelocations::RelocatePackedRelocation<ELF::Rela>(
- ElfRelocations* relocations, const ELF::Rela* rel, void* opaque);
+ assert(IsValidAndroidPackedRelocations(android_relocations_,
+ android_relocations_size_));
-void ElfRelocations::RelocatePackedRels(const uint8_t* packed_relocations,
- size_t src_addr,
- size_t dst_addr,
- size_t map_addr,
- size_t size) {
- AdjustRelocationArgs args;
+ RelocateAndroidRelocationArgs args;
args.src_addr = src_addr;
args.dst_addr = dst_addr;
args.map_addr = map_addr;
args.size = size;
- ForEachPackedRel(packed_relocations,
- &RelocatePackedRelocation<ELF::Rel>, &args);
+ ForEachAndroidRelocation(&RelocateAndroidRelocation, &args);
}
-void ElfRelocations::RelocatePackedRelas(const uint8_t* packed_relocations,
- size_t src_addr,
+template<typename Rel>
+void ElfRelocations::RelocateRelocations(size_t src_addr,
size_t dst_addr,
size_t map_addr,
size_t size) {
- AdjustRelocationArgs args;
- args.src_addr = src_addr;
- args.dst_addr = dst_addr;
- args.map_addr = map_addr;
- args.size = size;
- ForEachPackedRela(packed_relocations,
- &RelocatePackedRelocation<ELF::Rela>, &args);
-}
-
-void ElfRelocations::RelocatePackedRelocations(size_t src_addr,
- size_t dst_addr,
- size_t map_addr,
- size_t size) {
- if (!packed_relocations_)
- return;
-
- // Check for an initial APR1 header, packed relocations.
- if (packed_relocations_[0] == 'A' &&
- packed_relocations_[1] == 'P' &&
- packed_relocations_[2] == 'R' &&
- packed_relocations_[3] == '1') {
- RelocatePackedRels(packed_relocations_ + 4,
- src_addr, dst_addr, map_addr, size);
- }
-
- // Check for an initial APA1 header, packed relocations with addend.
- if (packed_relocations_[0] == 'A' &&
- packed_relocations_[1] == 'P' &&
- packed_relocations_[2] == 'A' &&
- packed_relocations_[3] == '1') {
- RelocatePackedRelas(packed_relocations_ + 4,
- src_addr, dst_addr, map_addr, size);
- }
-}
-
-#endif // __arm__ || __aarch64__
-
-template<typename Rel>
-void ElfRelocations::RelocateRelocation(size_t src_addr,
- size_t dst_addr,
- size_t map_addr,
- size_t size) {
// Add this value to each source address to get the corresponding
// destination address.
const size_t dst_delta = dst_addr - src_addr;
@@ -1079,10 +1163,10 @@ void ElfRelocations::RelocateRelocation(size_t src_addr,
}
}
-template void ElfRelocations::RelocateRelocation<ELF::Rel>(
+template void ElfRelocations::RelocateRelocations<ELF::Rel>(
size_t src_addr, size_t dst_addr, size_t map_addr, size_t size);
-template void ElfRelocations::RelocateRelocation<ELF::Rela>(
+template void ElfRelocations::RelocateRelocations<ELF::Rela>(
size_t src_addr, size_t dst_addr, size_t map_addr, size_t size);
void ElfRelocations::CopyAndRelocate(size_t src_addr,
@@ -1094,17 +1178,15 @@ void ElfRelocations::CopyAndRelocate(size_t src_addr,
reinterpret_cast<void*>(src_addr),
size);
-#if defined(__arm__) || defined(__aarch64__)
- // Relocate packed relative relocations.
- RelocatePackedRelocations(src_addr, dst_addr, map_addr, size);
-#endif
+ // Relocate android relocations.
+ RelocateAndroidRelocations(src_addr, dst_addr, map_addr, size);
// Relocate relocations.
if (relocations_type_ == DT_REL)
- RelocateRelocation<ELF::Rel>(src_addr, dst_addr, map_addr, size);
+ RelocateRelocations<ELF::Rel>(src_addr, dst_addr, map_addr, size);
if (relocations_type_ == DT_RELA)
- RelocateRelocation<ELF::Rela>(src_addr, dst_addr, map_addr, size);
+ RelocateRelocations<ELF::Rela>(src_addr, dst_addr, map_addr, size);
#ifdef __mips__
// Add this value to each source address to get the corresponding
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h
index d57c90f..1c7c15b 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h
@@ -64,13 +64,21 @@ class ElfRelocations {
ELF::Addr reloc,
ELF::Addr* sym_addr,
Error* error);
+ bool ApplyResolvedRelaReloc(const ELF::Rela* rela,
+ ELF::Addr sym_addr,
+ bool resolved,
+ Error* error);
+ bool ApplyResolvedRelReloc(const ELF::Rel* rel,
+ ELF::Addr sym_addr,
+ bool resolved,
+ Error* error);
bool ApplyRelaReloc(const ELF::Rela* rela,
- ELF::Addr sym_addr,
- bool resolved,
+ const ElfSymbols* symbols,
+ SymbolResolver* resolver,
Error* error);
bool ApplyRelReloc(const ELF::Rel* rel,
- ELF::Addr sym_addr,
- bool resolved,
+ const ElfSymbols* symbols,
+ SymbolResolver* resolver,
Error* error);
bool ApplyRelaRelocs(const ELF::Rela* relocs,
size_t relocs_count,
@@ -87,68 +95,43 @@ class ElfRelocations {
size_t dst_delta,
size_t map_delta);
template<typename Rel>
- void RelocateRelocation(size_t src_addr,
+ void RelocateRelocations(size_t src_addr,
size_t dst_addr,
size_t map_addr,
size_t size);
-
-#if defined(__arm__) || defined(__aarch64__)
- // Packed relocations unpackers. Call the given handler for each
- // relocation in the unpacking stream. There are two versions, one
- // for REL, the other for RELA.
- typedef bool (*RelRelocationHandler)(ElfRelocations* relocations,
- const ELF::Rel* relocation,
- void* opaque);
- bool ForEachPackedRel(const uint8_t* packed_relocations,
- RelRelocationHandler handler,
- void* opaque);
-
- typedef bool (*RelaRelocationHandler)(ElfRelocations* relocations,
+ void AdjustAndroidRelocation(const ELF::Rela* relocation,
+ size_t src_addr,
+ size_t dst_addr,
+ size_t map_addr,
+ size_t size);
+
+ // Android packed relocations unpacker. Calls the given handler for
+ // each relocation in the unpacking stream.
+ typedef bool (*RelocationHandler)(ElfRelocations* relocations,
+ const ELF::Rela* relocation,
+ void* opaque);
+ bool ForEachAndroidRelocation(RelocationHandler handler,
+ void* opaque);
+
+ // Apply Android packed relocations.
+ // On error, return false and set |error| message.
+ // The static function is the ForEachAndroidRelocation() handler.
+ bool ApplyAndroidRelocations(const ElfSymbols* symbols,
+ SymbolResolver* resolver,
+ Error* error);
+ static bool ApplyAndroidRelocation(ElfRelocations* relocations,
+ const ELF::Rela* relocation,
+ void* opaque);
+
+ // Relocate Android packed relocations.
+ // The static function is the ForEachAndroidRelocation() handler.
+ void RelocateAndroidRelocations(size_t src_addr,
+ size_t dst_addr,
+ size_t map_addr,
+ size_t size);
+ static bool RelocateAndroidRelocation(ElfRelocations* relocations,
const ELF::Rela* relocation,
void* opaque);
- bool ForEachPackedRela(const uint8_t* packed_relocations,
- RelaRelocationHandler handler,
- void* opaque);
-
- // Apply packed REL and RELA relocations. On error, return false.
- bool ApplyPackedRels(const uint8_t* packed_relocations, Error* error);
- static bool ApplyPackedRel(ElfRelocations* relocations,
- const ELF::Rel* relocation,
- void* opaque);
- bool ApplyPackedRelas(const uint8_t* packed_relocations, Error* error);
- static bool ApplyPackedRela(ElfRelocations* relocations,
- const ELF::Rela* relocation,
- void* opaque);
-
- // Apply all packed relocations.
- // On error, return false and set |error| message. No-op if no packed
- // relocations are present.
- bool ApplyPackedRelocations(Error* error);
-
- // Relocate packed REL and RELA relocations.
- template<typename Rel>
- static bool RelocatePackedRelocation(ElfRelocations* relocations,
- const Rel* rel,
- void* opaque);
-
- void RelocatePackedRels(const uint8_t* packed_relocations,
- size_t src_addr,
- size_t dst_addr,
- size_t map_addr,
- size_t size);
- void RelocatePackedRelas(const uint8_t* packed_relocations,
- size_t src_addr,
- size_t dst_addr,
- size_t map_addr,
- size_t size);
-
- // Relocate all packed relocations. No-op if no packed relocations
- // are present.
- void RelocatePackedRelocations(size_t src_addr,
- size_t dst_addr,
- size_t map_addr,
- size_t size);
-#endif
#if defined(__mips__)
bool RelocateMipsGot(const ElfSymbols* symbols,
@@ -175,9 +158,8 @@ class ElfRelocations {
ELF::Word mips_gotsym_;
#endif
-#if defined(__arm__) || defined(__aarch64__)
- uint8_t* packed_relocations_;
-#endif
+ uint8_t* android_relocations_;
+ size_t android_relocations_size_;
bool has_text_relocations_;
bool has_symbolic_;
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_leb128.h b/third_party/android_crazy_linker/src/src/crazy_linker_leb128.h
index 0888d77..787566e 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_leb128.h
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_leb128.h
@@ -5,6 +5,7 @@
#ifndef CRAZY_LINKER_LEB128_H
#define CRAZY_LINKER_LEB128_H
+#include <assert.h>
#include <stdint.h>
// Helper classes for decoding LEB128, used in packed relocation data.
@@ -12,58 +13,36 @@
namespace crazy {
-class Leb128Decoder {
- public:
- explicit Leb128Decoder(const uint8_t* encoding)
- : encoding_(encoding), cursor_(0) { }
-
- size_t Dequeue() {
- size_t value = 0;
-
- size_t shift = 0;
- uint8_t byte;
-
- do {
- byte = encoding_[cursor_++];
- value |= static_cast<size_t>(byte & 127) << shift;
- shift += 7;
- } while (byte & 128);
-
- return value;
- }
-
- private:
- const uint8_t* encoding_;
- size_t cursor_;
-};
-
class Sleb128Decoder {
public:
- explicit Sleb128Decoder(const uint8_t* encoding)
- : encoding_(encoding), cursor_(0) { }
+ Sleb128Decoder(const uint8_t* buffer, size_t count)
+ : current_(buffer), end_(buffer + count) { }
- ssize_t Dequeue() {
- ssize_t value = 0;
+ size_t pop_front() {
+ size_t value = 0;
static const size_t size = CHAR_BIT * sizeof(value);
size_t shift = 0;
uint8_t byte;
do {
- byte = encoding_[cursor_++];
- value |= (static_cast<ssize_t>(byte & 127) << shift);
+ assert(current_ < end_);
+
+ byte = *current_++;
+ value |= (static_cast<size_t>(byte & 127) << shift);
shift += 7;
} while (byte & 128);
- if (shift < size && (byte & 64))
- value |= -(static_cast<ssize_t>(1) << shift);
+ if (shift < size && (byte & 64)) {
+ value |= -(static_cast<size_t>(1) << shift);
+ }
return value;
}
private:
- const uint8_t* encoding_;
- size_t cursor_;
+ const uint8_t* current_;
+ const uint8_t* const end_;
};
} // namespace crazy
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp
index f45824c..b982a7d 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp
@@ -58,18 +58,6 @@
#define DT_PREINIT_ARRAYSZ 33
#endif
-#ifndef DT_LOOS
-#define DT_LOOS 0x6000000d
-#endif
-
-// Extension dynamic tags for packed relocations.
-#if defined(__arm__) || defined(__aarch64__)
-
-#define DT_ANDROID_REL_OFFSET (DT_LOOS)
-#define DT_ANDROID_REL_SIZE (DT_LOOS + 1)
-
-#endif // __arm__ || __aarch64__
-
namespace crazy {
namespace {
@@ -194,57 +182,6 @@ class SharedLibraryResolver : public ElfRelocations::SymbolResolver {
Vector<LibraryView*>* dependencies_;
};
-#if defined(__arm__) || defined(__aarch64__)
-
-// Helper class to provide a simple scoped buffer. ScopedPtr is not
-// usable here because it calls delete, not delete [].
-class ScopedBuffer {
- public:
- explicit ScopedBuffer(size_t bytes) : buffer_(new uint8_t[bytes]) { }
- ~ScopedBuffer() { delete [] buffer_; }
-
- uint8_t* Get() { return buffer_; }
-
- uint8_t* Release() {
- uint8_t* ptr = buffer_;
- buffer_ = NULL;
- return ptr;
- }
-
- private:
- uint8_t* buffer_;
-};
-
-// Read an .android.rel.dyn packed relocations section.
-// Returns an allocated buffer holding the data, or NULL on error.
-uint8_t* ReadPackedRelocations(const char* full_path,
- off_t offset,
- size_t bytes,
- Error* error) {
- FileDescriptor fd;
- if (!fd.OpenReadOnly(full_path)) {
- error->Format("Error opening file '%s'", full_path);
- return NULL;
- }
- if (fd.SeekTo(offset) == -1) {
- error->Format("Error seeking to %d in file '%s'", offset, full_path);
- return NULL;
- }
-
- ScopedBuffer buffer(bytes);
- const ssize_t bytes_read = fd.Read(buffer.Get(), bytes);
- if (static_cast<size_t>(bytes_read) != bytes) {
- error->Format("Error reading %d bytes from file '%s'", bytes, full_path);
- return NULL;
- }
- fd.Close();
-
- uint8_t* packed_data = buffer.Release();
- return packed_data;
-}
-
-#endif // __arm__ || __aarch64__
-
} // namespace
SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); }
@@ -253,10 +190,6 @@ SharedLibrary::~SharedLibrary() {
// Ensure the library is unmapped on destruction.
if (view_.load_address())
munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size());
-
-#if defined(__arm__) || defined(__aarch64__)
- delete [] packed_relocations_;
-#endif
}
bool SharedLibrary::Load(const char* full_path,
@@ -312,11 +245,6 @@ bool SharedLibrary::Load(const char* full_path,
phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_);
#endif
-#if defined(__arm__) || defined(__aarch64__)
- off_t packed_relocations_offset = 0;
- size_t packed_relocations_size = 0;
-#endif
-
LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_);
ElfView::DynamicIterator dyn(&view_);
for (; dyn.HasNext(); dyn.GetNext()) {
@@ -375,16 +303,6 @@ bool SharedLibrary::Load(const char* full_path,
if (dyn_value & DF_SYMBOLIC)
has_DT_SYMBOLIC_ = true;
break;
-#if defined(__arm__) || defined(__aarch64__)
- case DT_ANDROID_REL_OFFSET:
- packed_relocations_offset = dyn.GetOffset();
- LOG(" DT_ANDROID_REL_OFFSET addr=%p\n", packed_relocations_offset);
- break;
- case DT_ANDROID_REL_SIZE:
- packed_relocations_size = dyn.GetValue();
- LOG(" DT_ANDROID_REL_SIZE=%d\n", packed_relocations_size);
- break;
-#endif
#if defined(__mips__)
case DT_MIPS_RLD_MAP:
*dyn.GetValuePointer() =
@@ -396,32 +314,6 @@ bool SharedLibrary::Load(const char* full_path,
}
}
-#if defined(__arm__) || defined(__aarch64__)
- // If packed relocations are present in the target library, read the
- // section data and save it in packed_relocations_.
- if (packed_relocations_offset && packed_relocations_size) {
- LOG("%s: Packed relocations found at offset %d, %d bytes\n",
- __FUNCTION__,
- packed_relocations_offset,
- packed_relocations_size);
-
- packed_relocations_ =
- ReadPackedRelocations(full_path,
- packed_relocations_offset + file_offset,
- packed_relocations_size,
- error);
- if (!packed_relocations_)
- return false;
-
- LOG("%s: Packed relocations stored at %p\n",
- __FUNCTION__,
- packed_relocations_);
-
- // Add packed relocations to the view.
- view_.RegisterPackedRelocations(packed_relocations_);
- }
-#endif
-
LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_);
return true;
}
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h
index 410c914..ef8f469 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h
@@ -194,11 +194,6 @@ class SharedLibrary {
size_t arm_exidx_count_;
#endif
-#if defined(__arm__) || defined(__aarch64__)
- // Packed relocations data, NULL if absent.
- uint8_t* packed_relocations_;
-#endif
-
link_map_t link_map_;
bool has_DT_SYMBOLIC_;