Merge "Merge push-and-run-{prebuilt}-test-jar files."
diff --git a/build/Android.common_build.mk b/build/Android.common_build.mk
index 386128e..e4be21b 100644
--- a/build/Android.common_build.mk
+++ b/build/Android.common_build.mk
@@ -122,7 +122,7 @@
endif
# Clang on the target. Target builds use GCC by default.
-ART_TARGET_CLANG :=
+ART_TARGET_CLANG := false
ART_TARGET_CLANG_arm :=
ART_TARGET_CLANG_arm64 :=
ART_TARGET_CLANG_mips :=
@@ -168,7 +168,7 @@
ART_TARGET_CLANG_CFLAGS_x86 :=
ART_TARGET_CLANG_CFLAGS_x86_64 :=
-# these are necessary for Clang ARM64 ART builds
+# These are necessary for Clang ARM64 ART builds. TODO: remove.
ART_TARGET_CLANG_CFLAGS_arm64 += \
-Wno-implicit-exception-spec-mismatch \
-DNVALGRIND \
@@ -236,6 +236,14 @@
ART_TARGET_CFLAGS += -DART_BASE_ADDRESS_MIN_DELTA=$(LIBART_IMG_TARGET_MIN_BASE_ADDRESS_DELTA)
ART_TARGET_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LIBART_IMG_TARGET_MAX_BASE_ADDRESS_DELTA)
+# Colorize clang compiler warnings.
+ifeq ($(ART_HOST_CLANG),true)
+ ART_HOST_CFLAGS += -fcolor-diagnostics
+endif
+ifeq ($(ART_TARGET_CLANG),true)
+ ART_TARGET_CFLAGS += -fcolor-diagnostics
+endif
+
ART_TARGET_LDFLAGS :=
ifeq ($(TARGET_CPU_SMP),true)
ART_TARGET_CFLAGS += -DANDROID_SMP=1
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 8b5e6d5..133044a 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -125,8 +125,6 @@
utils/scoped_arena_allocator.cc \
buffered_output_stream.cc \
compiler.cc \
- elf_fixup.cc \
- elf_stripper.cc \
elf_writer.cc \
elf_writer_quick.cc \
file_output_stream.cc \
diff --git a/compiler/dex/local_value_numbering.cc b/compiler/dex/local_value_numbering.cc
index 4279955..e411164 100644
--- a/compiler/dex/local_value_numbering.cc
+++ b/compiler/dex/local_value_numbering.cc
@@ -1169,8 +1169,9 @@
const MirFieldInfo& field_info = gvn_->GetMirGraph()->GetIFieldLoweringInfo(mir);
uint16_t res;
if (!field_info.IsResolved() || field_info.IsVolatile()) {
- // Volatile fields always get a new memory version; field id is irrelevant.
// Unresolved fields may be volatile, so handle them as such to be safe.
+ HandleInvokeOrClInitOrAcquireOp(mir); // Volatile GETs have acquire semantics.
+ // Volatile fields always get a new memory version; field id is irrelevant.
// Use result s_reg - will be unique.
res = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
} else {
@@ -1269,14 +1270,16 @@
uint16_t LocalValueNumbering::HandleSGet(MIR* mir, uint16_t opcode) {
const MirSFieldLoweringInfo& field_info = gvn_->GetMirGraph()->GetSFieldLoweringInfo(mir);
- if (!field_info.IsInitialized() && (mir->optimization_flags & MIR_IGNORE_CLINIT_CHECK) == 0) {
- // Class initialization can call arbitrary functions, we need to wipe aliasing values.
- HandleInvokeOrClInit(mir);
+ if (!field_info.IsResolved() || field_info.IsVolatile() ||
+ (!field_info.IsInitialized() && (mir->optimization_flags & MIR_IGNORE_CLINIT_CHECK) == 0)) {
+ // Volatile SGETs (and unresolved fields are potentially volatile) have acquire semantics
+ // and class initialization can call arbitrary functions, we need to wipe aliasing values.
+ HandleInvokeOrClInitOrAcquireOp(mir);
}
uint16_t res;
if (!field_info.IsResolved() || field_info.IsVolatile()) {
- // Volatile fields always get a new memory version; field id is irrelevant.
// Unresolved fields may be volatile, so handle them as such to be safe.
+ // Volatile fields always get a new memory version; field id is irrelevant.
// Use result s_reg - will be unique.
res = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
} else {
@@ -1306,7 +1309,7 @@
const MirSFieldLoweringInfo& field_info = gvn_->GetMirGraph()->GetSFieldLoweringInfo(mir);
if (!field_info.IsInitialized() && (mir->optimization_flags & MIR_IGNORE_CLINIT_CHECK) == 0) {
// Class initialization can call arbitrary functions, we need to wipe aliasing values.
- HandleInvokeOrClInit(mir);
+ HandleInvokeOrClInitOrAcquireOp(mir);
}
uint16_t type = opcode - Instruction::SPUT;
if (!field_info.IsResolved()) {
@@ -1351,7 +1354,7 @@
}
}
-void LocalValueNumbering::HandleInvokeOrClInit(MIR* mir) {
+void LocalValueNumbering::HandleInvokeOrClInitOrAcquireOp(MIR* mir) {
// Use mir->offset as modifier; without elaborate inlining, it will be unique.
global_memory_version_ =
gvn_->LookupValue(kInvokeMemoryVersionBumpOp, 0u, 0u, mir->offset);
@@ -1404,9 +1407,7 @@
case Instruction::MONITOR_ENTER:
HandleNullCheck(mir, GetOperandValue(mir->ssa_rep->uses[0]));
- // NOTE: Keeping all aliasing values intact. Programs that rely on loads/stores of the
- // same non-volatile locations outside and inside a synchronized block being different
- // contain races that we cannot fix.
+ HandleInvokeOrClInitOrAcquireOp(mir); // Acquire operation.
break;
case Instruction::MONITOR_EXIT:
@@ -1462,14 +1463,12 @@
// Intentional fall-through.
case Instruction::INVOKE_STATIC:
case Instruction::INVOKE_STATIC_RANGE:
- if ((mir->optimization_flags & MIR_INLINED) == 0) {
- // Make ref args aliasing.
- for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
- uint16_t reg = GetOperandValue(mir->ssa_rep->uses[i]);
- non_aliasing_refs_.erase(reg);
- }
- HandleInvokeOrClInit(mir);
+ // Make ref args aliasing.
+ for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
+ uint16_t reg = GetOperandValue(mir->ssa_rep->uses[i]);
+ non_aliasing_refs_.erase(reg);
}
+ HandleInvokeOrClInitOrAcquireOp(mir);
break;
case Instruction::MOVE_RESULT:
diff --git a/compiler/dex/local_value_numbering.h b/compiler/dex/local_value_numbering.h
index e11c6e5..c60da32 100644
--- a/compiler/dex/local_value_numbering.h
+++ b/compiler/dex/local_value_numbering.h
@@ -308,7 +308,7 @@
uint16_t HandleSGet(MIR* mir, uint16_t opcode);
void HandleSPut(MIR* mir, uint16_t opcode);
void RemoveSFieldsForType(uint16_t type);
- void HandleInvokeOrClInit(MIR* mir);
+ void HandleInvokeOrClInitOrAcquireOp(MIR* mir);
bool SameMemoryVersion(const LocalValueNumbering& other) const;
diff --git a/compiler/dex/local_value_numbering_test.cc b/compiler/dex/local_value_numbering_test.cc
index e53c640..067bea2 100644
--- a/compiler/dex/local_value_numbering_test.cc
+++ b/compiler/dex/local_value_numbering_test.cc
@@ -338,16 +338,19 @@
DEF_IGET(Instruction::IGET, 1u, 0u, 0u), // Non-volatile.
DEF_IGET(Instruction::IGET, 2u, 10u, 1u), // Volatile.
DEF_IGET(Instruction::IGET, 3u, 2u, 1u), // Non-volatile.
+ DEF_IGET(Instruction::IGET, 4u, 0u, 0u), // Non-volatile.
};
PrepareIFields(ifields);
PrepareMIRs(mirs);
PerformLVN();
- ASSERT_EQ(value_names_.size(), 4u);
+ ASSERT_EQ(value_names_.size(), 5u);
EXPECT_NE(value_names_[0], value_names_[2]); // Volatile has always different value name.
EXPECT_NE(value_names_[1], value_names_[3]); // Used different base because of volatile.
+ EXPECT_NE(value_names_[1], value_names_[4]); // Not guaranteed to be the same after "acquire".
+
for (size_t i = 0; i != arraysize(mirs); ++i) {
- EXPECT_EQ((i == 2u) ? MIR_IGNORE_NULL_CHECK : 0,
+ EXPECT_EQ((i == 2u || i == 4u) ? MIR_IGNORE_NULL_CHECK : 0,
mirs_[i].optimization_flags) << i;
}
}
@@ -363,7 +366,7 @@
DEF_IGET(Instruction::IGET, 1u, 20u, 0u), // Resolved field #1, unique object.
DEF_IGET(Instruction::IGET, 2u, 21u, 0u), // Resolved field #1.
DEF_IGET_WIDE(Instruction::IGET_WIDE, 3u, 21u, 1u), // Resolved field #2.
- DEF_IGET(Instruction::IGET, 4u, 22u, 2u), // IGET doesn't clobber anything.
+ DEF_IGET(Instruction::IGET, 4u, 22u, 2u), // Unresolved IGET can be "acquire".
DEF_IGET(Instruction::IGET, 5u, 20u, 0u), // Resolved field #1, unique object.
DEF_IGET(Instruction::IGET, 6u, 21u, 0u), // Resolved field #1.
DEF_IGET_WIDE(Instruction::IGET_WIDE, 7u, 21u, 1u), // Resolved field #2.
@@ -381,14 +384,15 @@
PrepareMIRs(mirs);
PerformLVN();
ASSERT_EQ(value_names_.size(), 16u);
- EXPECT_EQ(value_names_[1], value_names_[5]);
- EXPECT_EQ(value_names_[2], value_names_[6]);
- EXPECT_EQ(value_names_[3], value_names_[7]);
- EXPECT_EQ(value_names_[1], value_names_[9]);
- EXPECT_NE(value_names_[2], value_names_[10]); // This aliased with unresolved IPUT.
- EXPECT_EQ(value_names_[3], value_names_[11]);
- EXPECT_EQ(value_names_[12], value_names_[15]);
- EXPECT_NE(value_names_[1], value_names_[14]); // This aliased with unresolved IPUT.
+ // Unresolved field is potentially volatile, so we need to adhere to the volatile semantics.
+ EXPECT_EQ(value_names_[1], value_names_[5]); // Unique object.
+ EXPECT_NE(value_names_[2], value_names_[6]); // Not guaranteed to be the same after "acquire".
+ EXPECT_NE(value_names_[3], value_names_[7]); // Not guaranteed to be the same after "acquire".
+ EXPECT_EQ(value_names_[1], value_names_[9]); // Unique object.
+ EXPECT_NE(value_names_[6], value_names_[10]); // This aliased with unresolved IPUT.
+ EXPECT_EQ(value_names_[7], value_names_[11]); // Still the same after "release".
+ EXPECT_EQ(value_names_[12], value_names_[15]); // Still the same after "release".
+ EXPECT_NE(value_names_[1], value_names_[14]); // This aliased with unresolved IPUT.
EXPECT_EQ(mirs_[0].optimization_flags, 0u);
EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
EXPECT_EQ(mirs_[2].optimization_flags, 0u);
@@ -409,7 +413,7 @@
static const MIRDef mirs[] = {
DEF_SGET(Instruction::SGET, 0u, 0u), // Resolved field #1.
DEF_SGET_WIDE(Instruction::SGET_WIDE, 1u, 1u), // Resolved field #2.
- DEF_SGET(Instruction::SGET, 2u, 2u), // SGET doesn't clobber anything.
+ DEF_SGET(Instruction::SGET, 2u, 2u), // Unresolved SGET can be "acquire".
DEF_SGET(Instruction::SGET, 3u, 0u), // Resolved field #1.
DEF_SGET_WIDE(Instruction::SGET_WIDE, 4u, 1u), // Resolved field #2.
DEF_SPUT(Instruction::SPUT, 5u, 2u), // SPUT clobbers field #1 (#2 is wide).
@@ -421,10 +425,11 @@
PrepareMIRs(mirs);
PerformLVN();
ASSERT_EQ(value_names_.size(), 8u);
- EXPECT_EQ(value_names_[0], value_names_[3]);
- EXPECT_EQ(value_names_[1], value_names_[4]);
- EXPECT_NE(value_names_[0], value_names_[6]); // This aliased with unresolved IPUT.
- EXPECT_EQ(value_names_[1], value_names_[7]);
+ // Unresolved field is potentially volatile, so we need to adhere to the volatile semantics.
+ EXPECT_NE(value_names_[0], value_names_[3]); // Not guaranteed to be the same after "acquire".
+ EXPECT_NE(value_names_[1], value_names_[4]); // Not guaranteed to be the same after "acquire".
+ EXPECT_NE(value_names_[3], value_names_[6]); // This aliased with unresolved IPUT.
+ EXPECT_EQ(value_names_[4], value_names_[7]); // Still the same after "release".
for (size_t i = 0u; i != mir_count_; ++i) {
EXPECT_EQ(0, mirs_[i].optimization_flags) << i;
}
diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc
index 246ae44..51b6709 100644
--- a/compiler/dex/mir_dataflow.cc
+++ b/compiler/dex/mir_dataflow.cc
@@ -1163,7 +1163,7 @@
if (!MIR::DecodedInstruction::IsPseudoMirOp(mir->dalvikInsn.opcode)) {
int flags = mir->dalvikInsn.FlagsOf();
- if ((flags & Instruction::kInvoke) != 0 && (mir->optimization_flags & MIR_INLINED) == 0) {
+ if ((flags & Instruction::kInvoke) != 0) {
attributes_ &= ~METHOD_IS_LEAF;
}
}
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index dda9e77..bcbfb5a 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -568,8 +568,6 @@
const uint16_t* code_ptr, const uint16_t* code_end) {
bool in_try_block = try_block_addr->IsBitSet(cur_offset);
bool is_throw = (insn->dalvikInsn.opcode == Instruction::THROW);
- bool build_all_edges =
- (cu_->disable_opt & (1 << kSuppressExceptionEdges)) || is_throw || in_try_block;
/* In try block */
if (in_try_block) {
@@ -605,6 +603,8 @@
}
in_try_block = (cur_block->successor_block_list_type != kNotUsed);
}
+ bool build_all_edges =
+ (cu_->disable_opt & (1 << kSuppressExceptionEdges)) || is_throw || in_try_block;
if (!in_try_block && build_all_edges) {
BasicBlock* eh_block = CreateNewBB(kExceptionHandling);
cur_block->taken = eh_block->id;
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index 1a4b23e..bf09446 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -845,7 +845,7 @@
RegLocation rl_object = LoadValue(rl_src_obj, kRefReg);
RegLocation rl_new_value;
if (!is_long) {
- rl_new_value = LoadValue(rl_src_new_value);
+ rl_new_value = LoadValue(rl_src_new_value, LocToRegClass(rl_src_new_value));
} else if (load_early) {
rl_new_value = LoadValueWide(rl_src_new_value, kCoreReg);
}
@@ -868,7 +868,7 @@
RegLocation rl_expected;
if (!is_long) {
- rl_expected = LoadValue(rl_src_expected);
+ rl_expected = LoadValue(rl_src_expected, LocToRegClass(rl_src_new_value));
} else if (load_early) {
rl_expected = LoadValueWide(rl_src_expected, kCoreReg);
} else {
diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc
index 88123e1..97f3994 100644
--- a/compiler/dex/quick/arm64/int_arm64.cc
+++ b/compiler/dex/quick/arm64/int_arm64.cc
@@ -925,7 +925,7 @@
LIR* Arm64Mir2Lir::OpPcRelLoad(RegStorage reg, LIR* target) {
ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
- return RawLIR(current_dalvik_offset_, WIDE(kA64Ldr2rp), reg.GetReg(), 0, 0, 0, 0, target);
+ return RawLIR(current_dalvik_offset_, kA64Ldr2rp, As32BitReg(reg).GetReg(), 0, 0, 0, 0, target);
}
LIR* Arm64Mir2Lir::OpVldm(RegStorage r_base, int count) {
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index f305017..e18116e 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -447,15 +447,16 @@
buf.push_back((data >> 24) & 0xff);
}
-// Push 8 bytes on 64-bit target systems; 4 on 32-bit target systems.
-static void PushPointer(std::vector<uint8_t>&buf, const void* pointer, bool target64) {
- uint64_t data = reinterpret_cast<uintptr_t>(pointer);
- if (target64) {
- Push32(buf, data & 0xFFFFFFFF);
- Push32(buf, (data >> 32) & 0xFFFFFFFF);
- } else {
- Push32(buf, static_cast<uint32_t>(data));
- }
+/**
+ * @brief Push a compressed reference which needs patching at link/patchoat-time.
+ * @details This needs to be kept consistent with the code which actually does the patching in
+ * oat_writer.cc and in the patchoat tool.
+ */
+static void PushUnpatchedReference(std::vector<uint8_t>&buf) {
+ // Note that we can safely initialize the patches to zero. The code deduplication mechanism takes
+ // the patches into account when determining whether two pieces of codes are functionally
+ // equivalent.
+ Push32(buf, UINT32_C(0));
}
static void AlignBuffer(std::vector<uint8_t>&buf, size_t offset) {
@@ -481,9 +482,7 @@
reinterpret_cast<const DexFile*>(UnwrapPointer(data_lir->operands[1]));
patches_.push_back(LinkerPatch::CodePatch(code_buffer_.size(),
target_dex_file, target_method_idx));
- const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx);
- // unique value based on target to ensure code deduplication works
- PushPointer(code_buffer_, &target_method_id, cu_->target64);
+ PushUnpatchedReference(code_buffer_);
data_lir = NEXT_LIR(data_lir);
}
data_lir = method_literal_list_;
@@ -493,9 +492,7 @@
reinterpret_cast<const DexFile*>(UnwrapPointer(data_lir->operands[1]));
patches_.push_back(LinkerPatch::MethodPatch(code_buffer_.size(),
target_dex_file, target_method_idx));
- const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx);
- // unique value based on target to ensure code deduplication works
- PushPointer(code_buffer_, &target_method_id, cu_->target64);
+ PushUnpatchedReference(code_buffer_);
data_lir = NEXT_LIR(data_lir);
}
// Push class literals.
@@ -506,9 +503,7 @@
reinterpret_cast<const DexFile*>(UnwrapPointer(data_lir->operands[1]));
patches_.push_back(LinkerPatch::TypePatch(code_buffer_.size(),
class_dex_file, target_type_idx));
- const DexFile::TypeId& target_method_id = class_dex_file->GetTypeId(target_type_idx);
- // unique value based on target to ensure code deduplication works
- PushPointer(code_buffer_, &target_method_id, cu_->target64);
+ PushUnpatchedReference(code_buffer_);
data_lir = NEXT_LIR(data_lir);
}
}
@@ -772,7 +767,9 @@
/* Determine the offset of each literal field */
int Mir2Lir::AssignLiteralOffset(CodeOffset offset) {
offset = AssignLiteralOffsetCommon(literal_list_, offset);
- unsigned int ptr_size = GetInstructionSetPointerSize(cu_->instruction_set);
+ constexpr unsigned int ptr_size = sizeof(uint32_t);
+ COMPILE_ASSERT(ptr_size >= sizeof(mirror::HeapReference<mirror::Object>),
+ ptr_size_cannot_hold_a_heap_reference);
offset = AssignLiteralPointerOffsetCommon(code_literal_list_, offset, ptr_size);
offset = AssignLiteralPointerOffsetCommon(method_literal_list_, offset, ptr_size);
offset = AssignLiteralPointerOffsetCommon(class_literal_list_, offset, ptr_size);
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index 2523380..0f1d765 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -566,7 +566,6 @@
break;
}
if (result) {
- invoke->optimization_flags |= MIR_INLINED;
// If the invoke has not been eliminated yet, check now whether we should do it.
// This is done so that dataflow analysis does not get tripped up seeing nop invoke.
if (static_cast<int>(invoke->dalvikInsn.opcode) != kMirOpNop) {
@@ -583,7 +582,6 @@
}
}
if (move_result != nullptr) {
- move_result->optimization_flags |= MIR_INLINED;
move_result->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
}
}
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index 9f7a881..3f7ecfe 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -214,9 +214,8 @@
void Mir2Lir::GenCompareAndBranch(Instruction::Code opcode, RegLocation rl_src1,
RegLocation rl_src2, LIR* taken,
LIR* fall_through) {
- DCHECK(!rl_src1.fp);
- DCHECK(!rl_src2.fp);
ConditionCode cond;
+ RegisterClass reg_class = (rl_src1.ref || rl_src2.ref) ? kRefReg : kCoreReg;
switch (opcode) {
case Instruction::IF_EQ:
cond = kCondEq;
@@ -249,7 +248,7 @@
cond = FlipComparisonOrder(cond);
}
- rl_src1 = LoadValue(rl_src1);
+ rl_src1 = LoadValue(rl_src1, reg_class);
// Is this really an immediate comparison?
if (rl_src2.is_const) {
// If it's already live in a register or not easily materialized, just keep going
@@ -273,15 +272,15 @@
}
}
- rl_src2 = LoadValue(rl_src2);
+ rl_src2 = LoadValue(rl_src2, reg_class);
OpCmpBranch(cond, rl_src1.reg, rl_src2.reg, taken);
}
void Mir2Lir::GenCompareZeroAndBranch(Instruction::Code opcode, RegLocation rl_src, LIR* taken,
LIR* fall_through) {
ConditionCode cond;
- DCHECK(!rl_src.fp);
- rl_src = LoadValue(rl_src);
+ RegisterClass reg_class = rl_src.ref ? kRefReg : kCoreReg;
+ rl_src = LoadValue(rl_src, reg_class);
switch (opcode) {
case Instruction::IF_EQZ:
cond = kCondEq;
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 67a75cb..bafb57d 100755
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1643,7 +1643,7 @@
FreeTemp(rl_temp_offset);
}
} else {
- rl_value = LoadValue(rl_src_value);
+ rl_value = LoadValue(rl_src_value, LocToRegClass(rl_src_value));
if (rl_value.ref) {
StoreRefIndexed(rl_object.reg, rl_offset.reg, rl_value.reg, 0);
} else {
@@ -1666,16 +1666,6 @@
}
void Mir2Lir::GenInvoke(CallInfo* info) {
- if ((info->opt_flags & MIR_INLINED) != 0) {
- // Already inlined but we may still need the null check.
- if (info->type != kStatic &&
- ((cu_->disable_opt & (1 << kNullCheckElimination)) != 0 ||
- (info->opt_flags & MIR_IGNORE_NULL_CHECK) == 0)) {
- RegLocation rl_obj = LoadValue(info->args[0], kRefReg);
- GenNullCheck(rl_obj.reg);
- }
- return;
- }
DCHECK(cu_->compiler_driver->GetMethodInlinerMap() != nullptr);
if (cu_->compiler_driver->GetMethodInlinerMap()->GetMethodInliner(cu_->dex_file)
->GenIntrinsic(this, info)) {
diff --git a/compiler/dex/quick/gen_loadstore.cc b/compiler/dex/quick/gen_loadstore.cc
index e5798fd..39b40a0 100644
--- a/compiler/dex/quick/gen_loadstore.cc
+++ b/compiler/dex/quick/gen_loadstore.cc
@@ -166,10 +166,6 @@
return rl_src;
}
-RegLocation Mir2Lir::LoadValue(RegLocation rl_src) {
- return LoadValue(rl_src, LocToRegClass(rl_src));
-}
-
void Mir2Lir::StoreValue(RegLocation rl_dest, RegLocation rl_src) {
/*
* Sanity checking - should never try to store to the same
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 6942c0f..e7160ad 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -500,17 +500,11 @@
break;
case Instruction::MOVE_RESULT_WIDE:
- if ((opt_flags & MIR_INLINED) != 0) {
- break; // Nop - combined w/ previous invoke.
- }
StoreValueWide(rl_dest, GetReturnWide(LocToRegClass(rl_dest)));
break;
case Instruction::MOVE_RESULT:
case Instruction::MOVE_RESULT_OBJECT:
- if ((opt_flags & MIR_INLINED) != 0) {
- break; // Nop - combined w/ previous invoke.
- }
StoreValue(rl_dest, GetReturn(LocToRegClass(rl_dest)));
break;
@@ -867,7 +861,7 @@
case Instruction::INVOKE_STATIC_RANGE:
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, true));
- if (!kLeafOptimization && (opt_flags & MIR_INLINED) == 0) {
+ if (!kLeafOptimization) {
// If the invocation is not inlined, we can assume there is already a
// suspend check at the return site
mir_graph_->AppendGenSuspendTestList(bb);
@@ -875,59 +869,59 @@
break;
case Instruction::INVOKE_STATIC:
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, false));
- if (!kLeafOptimization && (opt_flags & MIR_INLINED) == 0) {
+ if (!kLeafOptimization) {
mir_graph_->AppendGenSuspendTestList(bb);
}
break;
case Instruction::INVOKE_DIRECT:
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, false));
- if (!kLeafOptimization && (opt_flags & MIR_INLINED) == 0) {
+ if (!kLeafOptimization) {
mir_graph_->AppendGenSuspendTestList(bb);
}
break;
case Instruction::INVOKE_DIRECT_RANGE:
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, true));
- if (!kLeafOptimization && (opt_flags & MIR_INLINED) == 0) {
+ if (!kLeafOptimization) {
mir_graph_->AppendGenSuspendTestList(bb);
}
break;
case Instruction::INVOKE_VIRTUAL:
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, false));
- if (!kLeafOptimization && (opt_flags & MIR_INLINED) == 0) {
+ if (!kLeafOptimization) {
mir_graph_->AppendGenSuspendTestList(bb);
}
break;
case Instruction::INVOKE_VIRTUAL_RANGE:
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, true));
- if (!kLeafOptimization && (opt_flags & MIR_INLINED) == 0) {
+ if (!kLeafOptimization) {
mir_graph_->AppendGenSuspendTestList(bb);
}
break;
case Instruction::INVOKE_SUPER:
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, false));
- if (!kLeafOptimization && (opt_flags & MIR_INLINED) == 0) {
+ if (!kLeafOptimization) {
mir_graph_->AppendGenSuspendTestList(bb);
}
break;
case Instruction::INVOKE_SUPER_RANGE:
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, true));
- if (!kLeafOptimization && (opt_flags & MIR_INLINED) == 0) {
+ if (!kLeafOptimization) {
mir_graph_->AppendGenSuspendTestList(bb);
}
break;
case Instruction::INVOKE_INTERFACE:
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, false));
- if (!kLeafOptimization && (opt_flags & MIR_INLINED) == 0) {
+ if (!kLeafOptimization) {
mir_graph_->AppendGenSuspendTestList(bb);
}
break;
case Instruction::INVOKE_INTERFACE_RANGE:
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, true));
- if (!kLeafOptimization && (opt_flags & MIR_INLINED) == 0) {
+ if (!kLeafOptimization) {
mir_graph_->AppendGenSuspendTestList(bb);
}
break;
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 67a8c0f..3de4c56 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -1008,8 +1008,6 @@
}
// Load Dalvik value with 32-bit memory storage. If compressed object reference, decompress.
virtual RegLocation LoadValue(RegLocation rl_src, RegisterClass op_kind);
- // Same as above, but derive the target register class from the location record.
- virtual RegLocation LoadValue(RegLocation rl_src);
// Load Dalvik value with 64-bit memory storage.
virtual RegLocation LoadValueWide(RegLocation rl_src, RegisterClass op_kind);
// Load Dalvik value with 32-bit memory storage. If compressed object reference, decompress.
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 4357657..8638204 100755
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -1155,7 +1155,7 @@
LockTemp(rs_r0);
RegLocation rl_object = LoadValue(rl_src_obj, kRefReg);
- RegLocation rl_new_value = LoadValue(rl_src_new_value);
+ RegLocation rl_new_value = LoadValue(rl_src_new_value, LocToRegClass(rl_src_new_value));
if (is_object && !mir_graph_->IsConstantNullRef(rl_new_value)) {
// Mark card for object assuming new value is stored.
diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc
index 30384ec..6898b50 100644
--- a/compiler/dex/quick/x86/utility_x86.cc
+++ b/compiler/dex/quick/x86/utility_x86.cc
@@ -1113,20 +1113,18 @@
}
uint32_t index = mir->dalvikInsn.vB;
- if (!(mir->optimization_flags & MIR_INLINED)) {
- DCHECK(cu_->compiler_driver->GetMethodInlinerMap() != nullptr);
- DexFileMethodInliner* method_inliner =
- cu_->compiler_driver->GetMethodInlinerMap()->GetMethodInliner(cu_->dex_file);
- InlineMethod method;
- if (method_inliner->IsIntrinsic(index, &method)) {
- switch (method.opcode) {
- case kIntrinsicAbsDouble:
- case kIntrinsicMinMaxDouble:
- store_method_addr_ = true;
- break;
- default:
- break;
- }
+ DCHECK(cu_->compiler_driver->GetMethodInlinerMap() != nullptr);
+ DexFileMethodInliner* method_inliner =
+ cu_->compiler_driver->GetMethodInlinerMap()->GetMethodInliner(cu_->dex_file);
+ InlineMethod method;
+ if (method_inliner->IsIntrinsic(index, &method)) {
+ switch (method.opcode) {
+ case kIntrinsicAbsDouble:
+ case kIntrinsicMinMaxDouble:
+ store_method_addr_ = true;
+ break;
+ default:
+ break;
}
}
}
diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h
index 3be2478..74ee038 100644
--- a/compiler/elf_builder.h
+++ b/compiler/elf_builder.h
@@ -1094,7 +1094,8 @@
elf_header_.e_ident[EI_MAG1] = ELFMAG1;
elf_header_.e_ident[EI_MAG2] = ELFMAG2;
elf_header_.e_ident[EI_MAG3] = ELFMAG3;
- elf_header_.e_ident[EI_CLASS] = ELFCLASS32;
+ elf_header_.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
+ ? ELFCLASS32 : ELFCLASS64;;
elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
diff --git a/compiler/elf_fixup.cc b/compiler/elf_fixup.cc
deleted file mode 100644
index 0d34879..0000000
--- a/compiler/elf_fixup.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#include "elf_fixup.h"
-
-#include <inttypes.h>
-#include <memory>
-
-#include "base/logging.h"
-#include "base/stringprintf.h"
-#include "elf_file.h"
-#include "elf_writer.h"
-
-namespace art {
-
-static const bool DEBUG_FIXUP = false;
-
-bool ElfFixup::Fixup(File* file, uintptr_t oat_data_begin) {
- std::string error_msg;
- std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, &error_msg));
- CHECK(elf_file.get() != nullptr) << error_msg;
-
- // Lookup "oatdata" symbol address.
- Elf32_Addr oatdata_address = ElfWriter::GetOatDataAddress(elf_file.get());
- Elf32_Off base_address = oat_data_begin - oatdata_address;
-
- if (!FixupDynamic(*elf_file.get(), base_address)) {
- LOG(WARNING) << "Failed to fixup .dynamic in " << file->GetPath();
- return false;
- }
- if (!FixupSectionHeaders(*elf_file.get(), base_address)) {
- LOG(WARNING) << "Failed to fixup section headers in " << file->GetPath();
- return false;
- }
- if (!FixupProgramHeaders(*elf_file.get(), base_address)) {
- LOG(WARNING) << "Failed to fixup program headers in " << file->GetPath();
- return false;
- }
- if (!FixupSymbols(*elf_file.get(), base_address, true)) {
- LOG(WARNING) << "Failed to fixup .dynsym in " << file->GetPath();
- return false;
- }
- if (!FixupSymbols(*elf_file.get(), base_address, false)) {
- LOG(WARNING) << "Failed to fixup .symtab in " << file->GetPath();
- return false;
- }
- if (!FixupRelocations(*elf_file.get(), base_address)) {
- LOG(WARNING) << "Failed to fixup .rel.dyn in " << file->GetPath();
- return false;
- }
- if (!elf_file->FixupDebugSections(base_address)) {
- LOG(WARNING) << "Failed to fixup debug sections in " << file->GetPath();
- return false;
- }
- return true;
-}
-
-
-bool ElfFixup::FixupDynamic(ElfFile& elf_file, uintptr_t base_address) {
- for (Elf32_Word i = 0; i < elf_file.GetDynamicNum(); i++) {
- Elf32_Dyn& elf_dyn = elf_file.GetDynamic(i);
- Elf32_Word d_tag = elf_dyn.d_tag;
- if (IsDynamicSectionPointer(d_tag, elf_file.GetHeader().e_machine)) {
- uint32_t d_ptr = elf_dyn.d_un.d_ptr;
- if (DEBUG_FIXUP) {
- LOG(INFO) << StringPrintf("In %s moving Elf32_Dyn[%d] from 0x%08x to 0x%08" PRIxPTR,
- elf_file.GetFile().GetPath().c_str(), i,
- d_ptr, d_ptr + base_address);
- }
- d_ptr += base_address;
- elf_dyn.d_un.d_ptr = d_ptr;
- }
- }
- return true;
-}
-
-bool ElfFixup::FixupSectionHeaders(ElfFile& elf_file, uintptr_t base_address) {
- for (Elf32_Word i = 0; i < elf_file.GetSectionHeaderNum(); i++) {
- Elf32_Shdr* sh = elf_file.GetSectionHeader(i);
- CHECK(sh != nullptr);
- // 0 implies that the section will not exist in the memory of the process
- if (sh->sh_addr == 0) {
- continue;
- }
- if (DEBUG_FIXUP) {
- LOG(INFO) << StringPrintf("In %s moving Elf32_Shdr[%d] from 0x%08x to 0x%08" PRIxPTR,
- elf_file.GetFile().GetPath().c_str(), i,
- sh->sh_addr, sh->sh_addr + base_address);
- }
- sh->sh_addr += base_address;
- }
- return true;
-}
-
-bool ElfFixup::FixupProgramHeaders(ElfFile& elf_file, uintptr_t base_address) {
- // TODO: ELFObjectFile doesn't have give to Elf32_Phdr, so we do that ourselves for now.
- for (Elf32_Word i = 0; i < elf_file.GetProgramHeaderNum(); i++) {
- Elf32_Phdr* ph = elf_file.GetProgramHeader(i);
- CHECK(ph != nullptr);
- CHECK_EQ(ph->p_vaddr, ph->p_paddr) << elf_file.GetFile().GetPath() << " i=" << i;
- CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
- << elf_file.GetFile().GetPath() << " i=" << i;
- if (DEBUG_FIXUP) {
- LOG(INFO) << StringPrintf("In %s moving Elf32_Phdr[%d] from 0x%08x to 0x%08" PRIxPTR,
- elf_file.GetFile().GetPath().c_str(), i,
- ph->p_vaddr, ph->p_vaddr + base_address);
- }
- ph->p_vaddr += base_address;
- ph->p_paddr += base_address;
- CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
- << elf_file.GetFile().GetPath() << " i=" << i;
- }
- return true;
-}
-
-bool ElfFixup::FixupSymbols(ElfFile& elf_file, uintptr_t base_address, bool dynamic) {
- Elf32_Word section_type = dynamic ? SHT_DYNSYM : SHT_SYMTAB;
- // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile
- Elf32_Shdr* symbol_section = elf_file.FindSectionByType(section_type);
- if (symbol_section == nullptr) {
- // file is missing optional .symtab
- CHECK(!dynamic) << elf_file.GetFile().GetPath();
- return true;
- }
- for (uint32_t i = 0; i < elf_file.GetSymbolNum(*symbol_section); i++) {
- Elf32_Sym* symbol = elf_file.GetSymbol(section_type, i);
- CHECK(symbol != nullptr);
- if (symbol->st_value != 0) {
- if (DEBUG_FIXUP) {
- LOG(INFO) << StringPrintf("In %s moving Elf32_Sym[%d] from 0x%08x to 0x%08" PRIxPTR,
- elf_file.GetFile().GetPath().c_str(), i,
- symbol->st_value, symbol->st_value + base_address);
- }
- symbol->st_value += base_address;
- }
- }
- return true;
-}
-
-bool ElfFixup::FixupRelocations(ElfFile& elf_file, uintptr_t base_address) {
- for (Elf32_Word i = 0; i < elf_file.GetSectionHeaderNum(); i++) {
- Elf32_Shdr* sh = elf_file.GetSectionHeader(i);
- CHECK(sh != nullptr);
- if (sh->sh_type == SHT_REL) {
- for (uint32_t i = 0; i < elf_file.GetRelNum(*sh); i++) {
- Elf32_Rel& rel = elf_file.GetRel(*sh, i);
- if (DEBUG_FIXUP) {
- LOG(INFO) << StringPrintf("In %s moving Elf32_Rel[%d] from 0x%08x to 0x%08" PRIxPTR,
- elf_file.GetFile().GetPath().c_str(), i,
- rel.r_offset, rel.r_offset + base_address);
- }
- rel.r_offset += base_address;
- }
- } else if (sh->sh_type == SHT_RELA) {
- for (uint32_t i = 0; i < elf_file.GetRelaNum(*sh); i++) {
- Elf32_Rela& rela = elf_file.GetRela(*sh, i);
- if (DEBUG_FIXUP) {
- LOG(INFO) << StringPrintf("In %s moving Elf32_Rela[%d] from 0x%08x to 0x%08" PRIxPTR,
- elf_file.GetFile().GetPath().c_str(), i,
- rela.r_offset, rela.r_offset + base_address);
- }
- rela.r_offset += base_address;
- }
- }
- }
- return true;
-}
-
-} // namespace art
diff --git a/compiler/elf_fixup.h b/compiler/elf_fixup.h
deleted file mode 100644
index 1abf06b..0000000
--- a/compiler/elf_fixup.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2012 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 ART_COMPILER_ELF_FIXUP_H_
-#define ART_COMPILER_ELF_FIXUP_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "os.h"
-
-namespace art {
-
-class ElfFile;
-
-class ElfFixup {
- public:
- // Fixup an ELF file so that that oat header will be loaded at oat_begin.
- // Returns true on success, false on failure.
- static bool Fixup(File* file, uintptr_t oat_data_begin);
-
- private:
- // Fixup .dynamic d_ptr values for the expected base_address.
- static bool FixupDynamic(ElfFile& elf_file, uintptr_t base_address);
-
- // Fixup Elf32_Shdr p_vaddr to load at the desired address.
- static bool FixupSectionHeaders(ElfFile& elf_file, uintptr_t base_address);
-
- // Fixup Elf32_Phdr p_vaddr to load at the desired address.
- static bool FixupProgramHeaders(ElfFile& elf_file, uintptr_t base_address);
-
- // Fixup symbol table
- static bool FixupSymbols(ElfFile& elf_file, uintptr_t base_address, bool dynamic);
-
- // Fixup dynamic relocations
- static bool FixupRelocations(ElfFile& elf_file, uintptr_t base_address);
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(ElfFixup);
-};
-
-} // namespace art
-
-#endif // ART_COMPILER_ELF_FIXUP_H_
diff --git a/compiler/elf_stripper.cc b/compiler/elf_stripper.cc
deleted file mode 100644
index 457d8a0..0000000
--- a/compiler/elf_stripper.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#include "elf_stripper.h"
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <memory>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/stringprintf.h"
-#include "elf_file.h"
-#include "elf_utils.h"
-#include "utils.h"
-
-namespace art {
-
-bool ElfStripper::Strip(File* file, std::string* error_msg) {
- std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, error_msg));
- if (elf_file.get() == nullptr) {
- return false;
- }
-
- // ELF files produced by MCLinker look roughly like this
- //
- // +------------+
- // | Elf32_Ehdr | contains number of Elf32_Shdr and offset to first
- // +------------+
- // | Elf32_Phdr | program headers
- // | Elf32_Phdr |
- // | ... |
- // | Elf32_Phdr |
- // +------------+
- // | section | mixture of needed and unneeded sections
- // +------------+
- // | section |
- // +------------+
- // | ... |
- // +------------+
- // | section |
- // +------------+
- // | Elf32_Shdr | section headers
- // | Elf32_Shdr |
- // | ... | contains offset to section start
- // | Elf32_Shdr |
- // +------------+
- //
- // To strip:
- // - leave the Elf32_Ehdr and Elf32_Phdr values in place.
- // - walk the sections making a new set of Elf32_Shdr section headers for what we want to keep
- // - move the sections are keeping up to fill in gaps of sections we want to strip
- // - write new Elf32_Shdr section headers to end of file, updating Elf32_Ehdr
- // - truncate rest of file
- //
-
- std::vector<Elf32_Shdr> section_headers;
- std::vector<Elf32_Word> section_headers_original_indexes;
- section_headers.reserve(elf_file->GetSectionHeaderNum());
-
-
- Elf32_Shdr* string_section = elf_file->GetSectionNameStringSection();
- CHECK(string_section != nullptr);
- for (Elf32_Word i = 0; i < elf_file->GetSectionHeaderNum(); i++) {
- Elf32_Shdr* sh = elf_file->GetSectionHeader(i);
- CHECK(sh != nullptr);
- const char* name = elf_file->GetString(*string_section, sh->sh_name);
- if (name == nullptr) {
- CHECK_EQ(0U, i);
- section_headers.push_back(*sh);
- section_headers_original_indexes.push_back(0);
- continue;
- }
- if (StartsWith(name, ".debug")
- || (strcmp(name, ".strtab") == 0)
- || (strcmp(name, ".symtab") == 0)) {
- continue;
- }
- section_headers.push_back(*sh);
- section_headers_original_indexes.push_back(i);
- }
- CHECK_NE(0U, section_headers.size());
- CHECK_EQ(section_headers.size(), section_headers_original_indexes.size());
-
- // section 0 is the NULL section, sections start at offset of first section
- CHECK(elf_file->GetSectionHeader(1) != nullptr);
- Elf32_Off offset = elf_file->GetSectionHeader(1)->sh_offset;
- for (size_t i = 1; i < section_headers.size(); i++) {
- Elf32_Shdr& new_sh = section_headers[i];
- Elf32_Shdr* old_sh = elf_file->GetSectionHeader(section_headers_original_indexes[i]);
- CHECK(old_sh != nullptr);
- CHECK_EQ(new_sh.sh_name, old_sh->sh_name);
- if (old_sh->sh_addralign > 1) {
- offset = RoundUp(offset, old_sh->sh_addralign);
- }
- if (old_sh->sh_offset == offset) {
- // already in place
- offset += old_sh->sh_size;
- continue;
- }
- // shift section earlier
- memmove(elf_file->Begin() + offset,
- elf_file->Begin() + old_sh->sh_offset,
- old_sh->sh_size);
- new_sh.sh_offset = offset;
- offset += old_sh->sh_size;
- }
-
- Elf32_Off shoff = offset;
- size_t section_headers_size_in_bytes = section_headers.size() * sizeof(Elf32_Shdr);
- memcpy(elf_file->Begin() + offset, §ion_headers[0], section_headers_size_in_bytes);
- offset += section_headers_size_in_bytes;
-
- elf_file->GetHeader().e_shnum = section_headers.size();
- elf_file->GetHeader().e_shoff = shoff;
- int result = ftruncate(file->Fd(), offset);
- if (result != 0) {
- *error_msg = StringPrintf("Failed to truncate while stripping ELF file: '%s': %s",
- file->GetPath().c_str(), strerror(errno));
- return false;
- }
- return true;
-}
-
-} // namespace art
diff --git a/compiler/elf_stripper.h b/compiler/elf_stripper.h
deleted file mode 100644
index f1a1d46..0000000
--- a/compiler/elf_stripper.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2012 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 ART_COMPILER_ELF_STRIPPER_H_
-#define ART_COMPILER_ELF_STRIPPER_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "os.h"
-
-namespace art {
-
-class ElfStripper {
- public:
- // Strip an ELF file of unneeded debugging information.
- // Returns true on success, false on failure.
- static bool Strip(File* file, std::string* error_msg);
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(ElfStripper);
-};
-
-} // namespace art
-
-#endif // ART_COMPILER_ELF_STRIPPER_H_
diff --git a/compiler/elf_writer.cc b/compiler/elf_writer.cc
index 55ee18e..47402f3 100644
--- a/compiler/elf_writer.cc
+++ b/compiler/elf_writer.cc
@@ -30,8 +30,8 @@
namespace art {
-uint32_t ElfWriter::GetOatDataAddress(ElfFile* elf_file) {
- Elf32_Addr oatdata_address = elf_file->FindSymbolAddress(SHT_DYNSYM,
+uintptr_t ElfWriter::GetOatDataAddress(ElfFile* elf_file) {
+ uintptr_t oatdata_address = elf_file->FindSymbolAddress(SHT_DYNSYM,
"oatdata",
false);
CHECK_NE(0U, oatdata_address);
@@ -51,4 +51,16 @@
CHECK_NE(0U, oat_data_offset);
}
+bool ElfWriter::Fixup(File* file, uintptr_t oat_data_begin) {
+ std::string error_msg;
+ std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, &error_msg));
+ CHECK(elf_file.get() != nullptr) << error_msg;
+
+ // Lookup "oatdata" symbol address.
+ uintptr_t oatdata_address = ElfWriter::GetOatDataAddress(elf_file.get());
+ uintptr_t base_address = oat_data_begin - oatdata_address;
+
+ return elf_file->Fixup(base_address);
+}
+
} // namespace art
diff --git a/compiler/elf_writer.h b/compiler/elf_writer.h
index 03b965a..033c1f8 100644
--- a/compiler/elf_writer.h
+++ b/compiler/elf_writer.h
@@ -42,7 +42,9 @@
size_t& oat_data_offset);
// Returns runtime oat_data runtime address for an opened ElfFile.
- static uint32_t GetOatDataAddress(ElfFile* elf_file);
+ static uintptr_t GetOatDataAddress(ElfFile* elf_file);
+
+ static bool Fixup(File* file, uintptr_t oat_data_begin);
protected:
ElfWriter(const CompilerDriver& driver, File* elf_file)
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index 2a37049..5834e8e 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -23,7 +23,7 @@
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "common_compiler_test.h"
-#include "elf_fixup.h"
+#include "elf_writer.h"
#include "gc/space/image_space.h"
#include "image_writer.h"
#include "lock_word.h"
@@ -101,7 +101,7 @@
bool success_image =
writer.Write(image_file.GetFilename(), dup_oat->GetPath(), dup_oat->GetPath());
ASSERT_TRUE(success_image);
- bool success_fixup = ElfFixup::Fixup(dup_oat.get(), writer.GetOatDataBegin());
+ bool success_fixup = ElfWriter::Fixup(dup_oat.get(), writer.GetOatDataBegin());
ASSERT_TRUE(success_fixup);
}
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 1c8b8d5..6fff5f4 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -811,11 +811,12 @@
}
static OatHeader* GetOatHeaderFromElf(ElfFile* elf) {
- Elf32_Shdr* data_sec = elf->FindSectionByName(".rodata");
- if (data_sec == nullptr) {
+ uint64_t data_sec_offset;
+ bool has_data_sec = elf->GetSectionOffsetAndSize(".rodata", &data_sec_offset, nullptr);
+ if (!has_data_sec) {
return nullptr;
}
- return reinterpret_cast<OatHeader*>(elf->Begin() + data_sec->sh_offset);
+ return reinterpret_cast<OatHeader*>(elf->Begin() + data_sec_offset);
}
void ImageWriter::SetOatChecksumFromElfFile(File* elf_file) {
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index 1dcd4b3..f432e66 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -1991,7 +1991,7 @@
MemberOffset offs) {
X86_64ManagedRegister dest = mdest.AsX86_64();
CHECK(dest.IsCpuRegister() && dest.IsCpuRegister());
- movq(dest.AsCpuRegister(), Address(base.AsX86_64().AsCpuRegister(), offs));
+ movl(dest.AsCpuRegister(), Address(base.AsX86_64().AsCpuRegister(), offs));
if (kPoisonHeapReferences) {
negl(dest.AsCpuRegister());
}
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 09825e2..e1f513d 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -44,8 +44,7 @@
#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
-#include "elf_fixup.h"
-#include "elf_stripper.h"
+#include "elf_writer.h"
#include "gc/space/image_space.h"
#include "gc/space/space-inl.h"
#include "image_writer.h"
@@ -472,7 +471,7 @@
PLOG(ERROR) << "Failed to open ELF file: " << oat_filename;
return false;
}
- if (!ElfFixup::Fixup(oat_file.get(), oat_data_begin)) {
+ if (!ElfWriter::Fixup(oat_file.get(), oat_data_begin)) {
LOG(ERROR) << "Failed to fixup ELF file " << oat_file->GetPath();
return false;
}
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 50b4ece..bbaf0e4 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -29,6 +29,7 @@
#include "base/stringprintf.h"
#include "elf_utils.h"
#include "elf_file.h"
+#include "elf_file_impl.h"
#include "gc/space/image_space.h"
#include "image.h"
#include "instruction_set.h"
@@ -467,15 +468,16 @@
return true;
}
-template <typename ptr_t>
-bool PatchOat::CheckOatFile(const Elf32_Shdr& patches_sec) {
- if (patches_sec.sh_type != SHT_OAT_PATCH) {
+template <typename ElfFileImpl, typename ptr_t>
+bool PatchOat::CheckOatFile(ElfFileImpl* oat_file) {
+ auto patches_sec = oat_file->FindSectionByName(".oat_patches");
+ if (patches_sec->sh_type != SHT_OAT_PATCH) {
return false;
}
- ptr_t* patches = reinterpret_cast<ptr_t*>(oat_file_->Begin() + patches_sec.sh_offset);
- ptr_t* patches_end = patches + (patches_sec.sh_size / sizeof(ptr_t));
- Elf32_Shdr* oat_data_sec = oat_file_->FindSectionByName(".rodata");
- Elf32_Shdr* oat_text_sec = oat_file_->FindSectionByName(".text");
+ ptr_t* patches = reinterpret_cast<ptr_t*>(oat_file->Begin() + patches_sec->sh_offset);
+ ptr_t* patches_end = patches + (patches_sec->sh_size / sizeof(ptr_t));
+ auto oat_data_sec = oat_file->FindSectionByName(".rodata");
+ auto oat_text_sec = oat_file->FindSectionByName(".text");
if (oat_data_sec == nullptr) {
return false;
}
@@ -495,14 +497,15 @@
return true;
}
-bool PatchOat::PatchOatHeader() {
- Elf32_Shdr *rodata_sec = oat_file_->FindSectionByName(".rodata");
+template <typename ElfFileImpl>
+bool PatchOat::PatchOatHeader(ElfFileImpl* oat_file) {
+ auto rodata_sec = oat_file->FindSectionByName(".rodata");
if (rodata_sec == nullptr) {
return false;
}
- OatHeader* oat_header = reinterpret_cast<OatHeader*>(oat_file_->Begin() + rodata_sec->sh_offset);
+ OatHeader* oat_header = reinterpret_cast<OatHeader*>(oat_file->Begin() + rodata_sec->sh_offset);
if (!oat_header->IsValid()) {
- LOG(ERROR) << "Elf file " << oat_file_->GetFile().GetPath() << " has an invalid oat header";
+ LOG(ERROR) << "Elf file " << oat_file->GetFile().GetPath() << " has an invalid oat header";
return false;
}
oat_header->RelocateOat(delta_);
@@ -510,28 +513,31 @@
}
bool PatchOat::PatchElf() {
+ if (oat_file_->is_elf64_)
+ return PatchElf<ElfFileImpl64>(oat_file_->GetImpl64());
+ else
+ return PatchElf<ElfFileImpl32>(oat_file_->GetImpl32());
+}
+
+template <typename ElfFileImpl>
+bool PatchOat::PatchElf(ElfFileImpl* oat_file) {
TimingLogger::ScopedTiming t("Fixup Elf Text Section", timings_);
- if (!PatchTextSection()) {
+ if (!PatchTextSection<ElfFileImpl>(oat_file)) {
return false;
}
- if (!PatchOatHeader()) {
+ if (!PatchOatHeader<ElfFileImpl>(oat_file)) {
return false;
}
bool need_fixup = false;
- t.NewTiming("Fixup Elf Headers");
- // Fixup Phdr's
- for (unsigned int i = 0; i < oat_file_->GetProgramHeaderNum(); i++) {
- Elf32_Phdr* hdr = oat_file_->GetProgramHeader(i);
- CHECK(hdr != nullptr);
+ for (unsigned int i = 0; i < oat_file->GetProgramHeaderNum(); i++) {
+ auto hdr = oat_file->GetProgramHeader(i);
if (hdr->p_vaddr != 0 && hdr->p_vaddr != hdr->p_offset) {
need_fixup = true;
- hdr->p_vaddr += delta_;
}
if (hdr->p_paddr != 0 && hdr->p_paddr != hdr->p_offset) {
need_fixup = true;
- hdr->p_paddr += delta_;
}
}
if (!need_fixup) {
@@ -539,67 +545,39 @@
// their addr. Therefore we do not need to update these parts.
return true;
}
+
+ t.NewTiming("Fixup Elf Headers");
+ // Fixup Phdr's
+ oat_file->FixupProgramHeaders(delta_);
+
t.NewTiming("Fixup Section Headers");
- for (unsigned int i = 0; i < oat_file_->GetSectionHeaderNum(); i++) {
- Elf32_Shdr* hdr = oat_file_->GetSectionHeader(i);
- CHECK(hdr != nullptr);
- if (hdr->sh_addr != 0) {
- hdr->sh_addr += delta_;
- }
- }
+ // Fixup Shdr's
+ oat_file->FixupSectionHeaders(delta_);
t.NewTiming("Fixup Dynamics");
- for (Elf32_Word i = 0; i < oat_file_->GetDynamicNum(); i++) {
- Elf32_Dyn& dyn = oat_file_->GetDynamic(i);
- if (IsDynamicSectionPointer(dyn.d_tag, oat_file_->GetHeader().e_machine)) {
- dyn.d_un.d_ptr += delta_;
- }
- }
+ oat_file->FixupDynamic(delta_);
t.NewTiming("Fixup Elf Symbols");
// Fixup dynsym
- Elf32_Shdr* dynsym_sec = oat_file_->FindSectionByName(".dynsym");
- CHECK(dynsym_sec != nullptr);
- if (!PatchSymbols(dynsym_sec)) {
+ if (!oat_file->FixupSymbols(delta_, true)) {
return false;
}
-
// Fixup symtab
- Elf32_Shdr* symtab_sec = oat_file_->FindSectionByName(".symtab");
- if (symtab_sec != nullptr) {
- if (!PatchSymbols(symtab_sec)) {
- return false;
- }
+ if (!oat_file->FixupSymbols(delta_, false)) {
+ return false;
}
t.NewTiming("Fixup Debug Sections");
- if (!oat_file_->FixupDebugSections(delta_)) {
+ if (!oat_file->FixupDebugSections(delta_)) {
return false;
}
return true;
}
-bool PatchOat::PatchSymbols(Elf32_Shdr* section) {
- Elf32_Sym* syms = reinterpret_cast<Elf32_Sym*>(oat_file_->Begin() + section->sh_offset);
- const Elf32_Sym* last_sym =
- reinterpret_cast<Elf32_Sym*>(oat_file_->Begin() + section->sh_offset + section->sh_size);
- CHECK_EQ(section->sh_size % sizeof(Elf32_Sym), 0u)
- << "Symtab section size is not multiple of symbol size";
- for (; syms < last_sym; syms++) {
- uint8_t sttype = ELF32_ST_TYPE(syms->st_info);
- Elf32_Word shndx = syms->st_shndx;
- if (shndx != SHN_ABS && shndx != SHN_COMMON && shndx != SHN_UNDEF &&
- (sttype == STT_FUNC || sttype == STT_OBJECT)) {
- CHECK_NE(syms->st_value, 0u);
- syms->st_value += delta_;
- }
- }
- return true;
-}
-
-bool PatchOat::PatchTextSection() {
- Elf32_Shdr* patches_sec = oat_file_->FindSectionByName(".oat_patches");
+template <typename ElfFileImpl>
+bool PatchOat::PatchTextSection(ElfFileImpl* oat_file) {
+ auto patches_sec = oat_file->FindSectionByName(".oat_patches");
if (patches_sec == nullptr) {
LOG(ERROR) << ".oat_patches section not found. Aborting patch";
return false;
@@ -611,9 +589,9 @@
switch (patches_sec->sh_entsize) {
case sizeof(uint32_t):
- return PatchTextSection<uint32_t>(*patches_sec);
+ return PatchTextSection<ElfFileImpl, uint32_t>(oat_file);
case sizeof(uint64_t):
- return PatchTextSection<uint64_t>(*patches_sec);
+ return PatchTextSection<ElfFileImpl, uint64_t>(oat_file);
default:
LOG(ERROR) << ".oat_patches Entsize of " << patches_sec->sh_entsize << "bits "
<< "is not valid";
@@ -621,14 +599,16 @@
}
}
-template <typename ptr_t>
-bool PatchOat::PatchTextSection(const Elf32_Shdr& patches_sec) {
- DCHECK(CheckOatFile<ptr_t>(patches_sec)) << "Oat file invalid";
- ptr_t* patches = reinterpret_cast<ptr_t*>(oat_file_->Begin() + patches_sec.sh_offset);
- ptr_t* patches_end = patches + (patches_sec.sh_size / sizeof(ptr_t));
- Elf32_Shdr* oat_text_sec = oat_file_->FindSectionByName(".text");
+template <typename ElfFileImpl, typename patch_loc_t>
+bool PatchOat::PatchTextSection(ElfFileImpl* oat_file) {
+ bool oat_file_valid = CheckOatFile<ElfFileImpl, patch_loc_t>(oat_file);
+ CHECK(oat_file_valid) << "Oat file invalid";
+ auto patches_sec = oat_file->FindSectionByName(".oat_patches");
+ patch_loc_t* patches = reinterpret_cast<patch_loc_t*>(oat_file->Begin() + patches_sec->sh_offset);
+ patch_loc_t* patches_end = patches + (patches_sec->sh_size / sizeof(patch_loc_t));
+ auto oat_text_sec = oat_file->FindSectionByName(".text");
CHECK(oat_text_sec != nullptr);
- byte* to_patch = oat_file_->Begin() + oat_text_sec->sh_offset;
+ byte* to_patch = oat_file->Begin() + oat_text_sec->sh_offset;
uintptr_t to_patch_end = reinterpret_cast<uintptr_t>(to_patch) + oat_text_sec->sh_size;
for (; patches < patches_end; patches++) {
@@ -768,7 +748,7 @@
if (f.get() != nullptr) {
if (fchmod(f->Fd(), 0644) != 0) {
PLOG(ERROR) << "Unable to make " << name << " world readable";
- unlink(name);
+ TEMP_FAILURE_RETRY(unlink(name));
return nullptr;
}
}
@@ -1086,11 +1066,11 @@
if (!success) {
if (new_oat_out) {
CHECK(!output_oat_filename.empty());
- unlink(output_oat_filename.c_str());
+ TEMP_FAILURE_RETRY(unlink(output_oat_filename.c_str()));
}
if (new_image_out) {
CHECK(!output_image_filename.empty());
- unlink(output_image_filename.c_str());
+ TEMP_FAILURE_RETRY(unlink(output_image_filename.c_str()));
}
}
if (dump_timings) {
diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h
index 9086d58..7dd95f5 100644
--- a/patchoat/patchoat.h
+++ b/patchoat/patchoat.h
@@ -76,12 +76,15 @@
// Patches oat in place, modifying the oat_file given to the constructor.
bool PatchElf();
- bool PatchTextSection();
+ template <typename ElfFileImpl>
+ bool PatchElf(ElfFileImpl* oat_file);
+ template <typename ElfFileImpl>
+ bool PatchTextSection(ElfFileImpl* oat_file);
// Templatized version to actually do the patching with the right sized offsets.
- template <typename ptr_t> bool PatchTextSection(const Elf32_Shdr& patches_sec);
- template <typename ptr_t> bool CheckOatFile(const Elf32_Shdr& patches_sec);
- bool PatchOatHeader();
- bool PatchSymbols(Elf32_Shdr* section);
+ template <typename ElfFileImpl, typename patch_loc_t> bool PatchTextSection(ElfFileImpl* oat_file);
+ template <typename ElfFileImpl, typename patch_loc_t> bool CheckOatFile(ElfFileImpl* oat_filec);
+ template <typename ElfFileImpl>
+ bool PatchOatHeader(ElfFileImpl* oat_file);
bool PatchImage() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/elf.h b/runtime/elf.h
index 6e007a2..60b5248 100644
--- a/runtime/elf.h
+++ b/runtime/elf.h
@@ -1411,6 +1411,7 @@
// BEGIN android-added for <elf.h> compat
static inline unsigned char ELF32_ST_TYPE(unsigned char st_info) { return st_info & 0x0f; }
+static inline unsigned char ELF64_ST_TYPE(unsigned char st_info) { return st_info & 0x0f; }
// END android-added for <elf.h> compat
// Symbol table entries for ELF64.
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 65a557b..3b8358d 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -16,6 +16,7 @@
#include "elf_file.h"
+#include <inttypes.h>
#include <sys/types.h>
#include <unistd.h>
@@ -106,7 +107,12 @@
delete entry;
}
-ElfFile::ElfFile(File* file, bool writable, bool program_header_only)
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::ElfFileImpl(File* file, bool writable, bool program_header_only)
: file_(file),
writable_(writable),
program_header_only_(program_header_only),
@@ -128,9 +134,20 @@
CHECK(file != nullptr);
}
-ElfFile* ElfFile::Open(File* file, bool writable, bool program_header_only,
- std::string* error_msg) {
- std::unique_ptr<ElfFile> elf_file(new ElfFile(file, writable, program_header_only));
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>*
+ ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::Open(File* file, bool writable, bool program_header_only,
+ std::string* error_msg) {
+ std::unique_ptr<ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>>
+ elf_file(new ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ (file, writable, program_header_only));
int prot;
int flags;
if (writable) {
@@ -146,15 +163,31 @@
return elf_file.release();
}
-ElfFile* ElfFile::Open(File* file, int prot, int flags, std::string* error_msg) {
- std::unique_ptr<ElfFile> elf_file(new ElfFile(file, (prot & PROT_WRITE) == PROT_WRITE, false));
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>*
+ ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::Open(File* file, int prot, int flags, std::string* error_msg) {
+ std::unique_ptr<ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>>
+ elf_file(new ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ (file, (prot & PROT_WRITE) == PROT_WRITE, false));
if (!elf_file->Setup(prot, flags, error_msg)) {
return nullptr;
}
return elf_file.release();
}
-bool ElfFile::Setup(int prot, int flags, std::string* error_msg) {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::Setup(int prot, int flags, std::string* error_msg) {
int64_t temp_file_length = file_->GetLength();
if (temp_file_length < 0) {
errno = -temp_file_length;
@@ -163,16 +196,16 @@
return false;
}
size_t file_length = static_cast<size_t>(temp_file_length);
- if (file_length < sizeof(Elf32_Ehdr)) {
+ if (file_length < sizeof(Elf_Ehdr)) {
*error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF header of "
- "%zd bytes: '%s'", file_length, sizeof(Elf32_Ehdr),
+ "%zd bytes: '%s'", file_length, sizeof(Elf_Ehdr),
file_->GetPath().c_str());
return false;
}
if (program_header_only_) {
// first just map ELF header to get program header size information
- size_t elf_header_size = sizeof(Elf32_Ehdr);
+ size_t elf_header_size = sizeof(Elf_Ehdr);
if (!SetMap(MemMap::MapFile(elf_header_size, prot, flags, file_->Fd(), 0,
file_->GetPath().c_str(), error_msg),
error_msg)) {
@@ -183,7 +216,7 @@
if (file_length < program_header_size) {
*error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF program "
"header of %zd bytes: '%s'", file_length,
- sizeof(Elf32_Ehdr), file_->GetPath().c_str());
+ sizeof(Elf_Ehdr), file_->GetPath().c_str());
return false;
}
if (!SetMap(MemMap::MapFile(program_header_size, prot, flags, file_->Fd(), 0,
@@ -215,7 +248,7 @@
}
// Find shstrtab.
- Elf32_Shdr* shstrtab_section_header = GetSectionNameStringSection();
+ Elf_Shdr* shstrtab_section_header = GetSectionNameStringSection();
if (shstrtab_section_header == nullptr) {
*error_msg = StringPrintf("Failed to find shstrtab section header in ELF file: '%s'",
file_->GetPath().c_str());
@@ -236,8 +269,8 @@
}
// Find other sections from section headers
- for (Elf32_Word i = 0; i < GetSectionHeaderNum(); i++) {
- Elf32_Shdr* section_header = GetSectionHeader(i);
+ for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
+ Elf_Shdr* section_header = GetSectionHeader(i);
if (section_header == nullptr) {
*error_msg = StringPrintf("Failed to find section header for section %d in ELF file: '%s'",
i, file_->GetPath().c_str());
@@ -311,7 +344,12 @@
return true;
}
-ElfFile::~ElfFile() {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::~ElfFileImpl() {
STLDeleteElements(&segments_);
delete symtab_symbol_table_;
delete dynsym_symbol_table_;
@@ -321,8 +359,13 @@
}
}
-bool ElfFile::CheckAndSet(Elf32_Off offset, const char* label,
- byte** target, std::string* error_msg) {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::CheckAndSet(Elf32_Off offset, const char* label,
+ byte** target, std::string* error_msg) {
if (Begin() + offset >= End()) {
*error_msg = StringPrintf("Offset %d is out of range for %s in ELF file: '%s'", offset, label,
file_->GetPath().c_str());
@@ -332,18 +375,23 @@
return true;
}
-bool ElfFile::CheckSectionsLinked(const byte* source, const byte* target) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::CheckSectionsLinked(const byte* source, const byte* target) const {
// Only works in whole-program mode, as we need to iterate over the sections.
// Note that we normally can't search by type, as duplicates are allowed for most section types.
if (program_header_only_) {
return true;
}
- Elf32_Shdr* source_section = nullptr;
- Elf32_Word target_index = 0;
+ Elf_Shdr* source_section = nullptr;
+ Elf_Word target_index = 0;
bool target_found = false;
- for (Elf32_Word i = 0; i < GetSectionHeaderNum(); i++) {
- Elf32_Shdr* section_header = GetSectionHeader(i);
+ for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
+ Elf_Shdr* section_header = GetSectionHeader(i);
if (Begin() + section_header->sh_offset == source) {
// Found the source.
@@ -363,7 +411,12 @@
return target_found && source_section != nullptr && source_section->sh_link == target_index;
}
-bool ElfFile::CheckSectionsExist(std::string* error_msg) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::CheckSectionsExist(std::string* error_msg) const {
if (!program_header_only_) {
// If in full mode, need section headers.
if (section_headers_start_ == nullptr) {
@@ -432,7 +485,12 @@
return true;
}
-bool ElfFile::SetMap(MemMap* map, std::string* error_msg) {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::SetMap(MemMap* map, std::string* error_msg) {
if (map == nullptr) {
// MemMap::Open should have already set an error.
DCHECK(!error_msg->empty());
@@ -442,7 +500,7 @@
CHECK(map_.get() != nullptr) << file_->GetPath();
CHECK(map_->Begin() != nullptr) << file_->GetPath();
- header_ = reinterpret_cast<Elf32_Ehdr*>(map_->Begin());
+ header_ = reinterpret_cast<Elf_Ehdr*>(map_->Begin());
if ((ELFMAG0 != header_->e_ident[EI_MAG0])
|| (ELFMAG1 != header_->e_ident[EI_MAG1])
|| (ELFMAG2 != header_->e_ident[EI_MAG2])
@@ -456,9 +514,10 @@
header_->e_ident[EI_MAG3]);
return false;
}
- if (ELFCLASS32 != header_->e_ident[EI_CLASS]) {
+ uint8_t elf_class = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)) ? ELFCLASS64 : ELFCLASS32;
+ if (elf_class != header_->e_ident[EI_CLASS]) {
*error_msg = StringPrintf("Failed to find expected EI_CLASS value %d in %s, found %d",
- ELFCLASS32,
+ elf_class,
file_->GetPath().c_str(),
header_->e_ident[EI_CLASS]);
return false;
@@ -495,7 +554,7 @@
*error_msg = StringPrintf("Failed to find expected e_entry value %d in %s, found %d",
0,
file_->GetPath().c_str(),
- header_->e_entry);
+ static_cast<int32_t>(header_->e_entry));
return false;
}
if (0 == header_->e_phoff) {
@@ -548,15 +607,15 @@
if (!program_header_only_) {
if (header_->e_phoff >= Size()) {
- *error_msg = StringPrintf("Failed to find e_phoff value %d less than %zd in %s",
- header_->e_phoff,
+ *error_msg = StringPrintf("Failed to find e_phoff value %" PRIu64 " less than %zd in %s",
+ static_cast<uint64_t>(header_->e_phoff),
Size(),
file_->GetPath().c_str());
return false;
}
if (header_->e_shoff >= Size()) {
- *error_msg = StringPrintf("Failed to find e_shoff value %d less than %zd in %s",
- header_->e_shoff,
+ *error_msg = StringPrintf("Failed to find e_shoff value %" PRIu64 " less than %zd in %s",
+ static_cast<uint64_t>(header_->e_shoff),
Size(),
file_->GetPath().c_str());
return false;
@@ -565,39 +624,64 @@
return true;
}
-
-Elf32_Ehdr& ElfFile::GetHeader() const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Ehdr& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetHeader() const {
CHECK(header_ != nullptr); // Header has been checked in SetMap. This is a sanity check.
return *header_;
}
-byte* ElfFile::GetProgramHeadersStart() const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+byte* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetProgramHeadersStart() const {
CHECK(program_headers_start_ != nullptr); // Header has been set in Setup. This is a sanity
// check.
return program_headers_start_;
}
-byte* ElfFile::GetSectionHeadersStart() const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+byte* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetSectionHeadersStart() const {
CHECK(!program_header_only_); // Only used in "full" mode.
CHECK(section_headers_start_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
return section_headers_start_;
}
-Elf32_Phdr& ElfFile::GetDynamicProgramHeader() const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Phdr& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetDynamicProgramHeader() const {
CHECK(dynamic_program_header_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
return *dynamic_program_header_;
}
-Elf32_Dyn* ElfFile::GetDynamicSectionStart() const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Dyn* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetDynamicSectionStart() const {
CHECK(dynamic_section_start_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
return dynamic_section_start_;
}
-static bool IsSymbolSectionType(Elf32_Word section_type) {
- return ((section_type == SHT_SYMTAB) || (section_type == SHT_DYNSYM));
-}
-
-Elf32_Sym* ElfFile::GetSymbolSectionStart(Elf32_Word section_type) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetSymbolSectionStart(Elf_Word section_type) const {
CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
switch (section_type) {
case SHT_SYMTAB: {
@@ -615,7 +699,12 @@
}
}
-const char* ElfFile::GetStringSectionStart(Elf32_Word section_type) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+const char* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetStringSectionStart(Elf_Word section_type) const {
CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
switch (section_type) {
case SHT_SYMTAB: {
@@ -631,7 +720,12 @@
}
}
-const char* ElfFile::GetString(Elf32_Word section_type, Elf32_Word i) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+const char* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetString(Elf_Word section_type, Elf_Word i) const {
CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
if (i == 0) {
return nullptr;
@@ -646,19 +740,39 @@
// WARNING: The following methods do not check for an error condition (non-existent hash section).
// It is the caller's job to do this.
-Elf32_Word* ElfFile::GetHashSectionStart() const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Word* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetHashSectionStart() const {
return hash_section_start_;
}
-Elf32_Word ElfFile::GetHashBucketNum() const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetHashBucketNum() const {
return GetHashSectionStart()[0];
}
-Elf32_Word ElfFile::GetHashChainNum() const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetHashChainNum() const {
return GetHashSectionStart()[1];
}
-Elf32_Word ElfFile::GetHashBucket(size_t i, bool* ok) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetHashBucket(size_t i, bool* ok) const {
if (i >= GetHashBucketNum()) {
*ok = false;
return 0;
@@ -668,7 +782,12 @@
return GetHashSectionStart()[2 + i];
}
-Elf32_Word ElfFile::GetHashChain(size_t i, bool* ok) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetHashChain(size_t i, bool* ok) const {
if (i >= GetHashBucketNum()) {
*ok = false;
return 0;
@@ -678,22 +797,37 @@
return GetHashSectionStart()[2 + GetHashBucketNum() + i];
}
-Elf32_Word ElfFile::GetProgramHeaderNum() const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetProgramHeaderNum() const {
return GetHeader().e_phnum;
}
-Elf32_Phdr* ElfFile::GetProgramHeader(Elf32_Word i) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Phdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetProgramHeader(Elf_Word i) const {
CHECK_LT(i, GetProgramHeaderNum()) << file_->GetPath(); // Sanity check for caller.
byte* program_header = GetProgramHeadersStart() + (i * GetHeader().e_phentsize);
if (program_header >= End()) {
return nullptr; // Failure condition.
}
- return reinterpret_cast<Elf32_Phdr*>(program_header);
+ return reinterpret_cast<Elf_Phdr*>(program_header);
}
-Elf32_Phdr* ElfFile::FindProgamHeaderByType(Elf32_Word type) const {
- for (Elf32_Word i = 0; i < GetProgramHeaderNum(); i++) {
- Elf32_Phdr* program_header = GetProgramHeader(i);
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Phdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FindProgamHeaderByType(Elf_Word type) const {
+ for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
+ Elf_Phdr* program_header = GetProgramHeader(i);
if (program_header->p_type == type) {
return program_header;
}
@@ -701,11 +835,21 @@
return nullptr;
}
-Elf32_Word ElfFile::GetSectionHeaderNum() const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetSectionHeaderNum() const {
return GetHeader().e_shnum;
}
-Elf32_Shdr* ElfFile::GetSectionHeader(Elf32_Word i) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetSectionHeader(Elf_Word i) const {
// Can only access arbitrary sections when we have the whole file, not just program header.
// Even if we Load(), it doesn't bring in all the sections.
CHECK(!program_header_only_) << file_->GetPath();
@@ -716,15 +860,20 @@
if (section_header >= End()) {
return nullptr; // Failure condition.
}
- return reinterpret_cast<Elf32_Shdr*>(section_header);
+ return reinterpret_cast<Elf_Shdr*>(section_header);
}
-Elf32_Shdr* ElfFile::FindSectionByType(Elf32_Word type) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FindSectionByType(Elf_Word type) const {
// Can only access arbitrary sections when we have the whole file, not just program header.
// We could change this to switch on known types if they were detected during loading.
CHECK(!program_header_only_) << file_->GetPath();
- for (Elf32_Word i = 0; i < GetSectionHeaderNum(); i++) {
- Elf32_Shdr* section_header = GetSectionHeader(i);
+ for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
+ Elf_Shdr* section_header = GetSectionHeader(i);
if (section_header->sh_type == type) {
return section_header;
}
@@ -746,16 +895,26 @@
return h;
}
-Elf32_Shdr* ElfFile::GetSectionNameStringSection() const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetSectionNameStringSection() const {
return GetSectionHeader(GetHeader().e_shstrndx);
}
-const byte* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+const byte* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FindDynamicSymbolAddress(const std::string& symbol_name) const {
// Check that we have a hash section.
if (GetHashSectionStart() == nullptr) {
return nullptr; // Failure condition.
}
- const Elf32_Sym* sym = FindDynamicSymbol(symbol_name);
+ const Elf_Sym* sym = FindDynamicSymbol(symbol_name);
if (sym != nullptr) {
return base_address_ + sym->st_value;
} else {
@@ -764,20 +923,25 @@
}
// WARNING: Only called from FindDynamicSymbolAddress. Elides check for hash section.
-const Elf32_Sym* ElfFile::FindDynamicSymbol(const std::string& symbol_name) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+const Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FindDynamicSymbol(const std::string& symbol_name) const {
if (GetHashBucketNum() == 0) {
// No dynamic symbols at all.
return nullptr;
}
- Elf32_Word hash = elfhash(symbol_name.c_str());
- Elf32_Word bucket_index = hash % GetHashBucketNum();
+ Elf_Word hash = elfhash(symbol_name.c_str());
+ Elf_Word bucket_index = hash % GetHashBucketNum();
bool ok;
- Elf32_Word symbol_and_chain_index = GetHashBucket(bucket_index, &ok);
+ Elf_Word symbol_and_chain_index = GetHashBucket(bucket_index, &ok);
if (!ok) {
return nullptr;
}
while (symbol_and_chain_index != 0 /* STN_UNDEF */) {
- Elf32_Sym* symbol = GetSymbol(SHT_DYNSYM, symbol_and_chain_index);
+ Elf_Sym* symbol = GetSymbol(SHT_DYNSYM, symbol_and_chain_index);
if (symbol == nullptr) {
return nullptr; // Failure condition.
}
@@ -793,23 +957,49 @@
return nullptr;
}
-Elf32_Word ElfFile::GetSymbolNum(Elf32_Shdr& section_header) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::IsSymbolSectionType(Elf_Word section_type) {
+ return ((section_type == SHT_SYMTAB) || (section_type == SHT_DYNSYM));
+}
+
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetSymbolNum(Elf_Shdr& section_header) const {
CHECK(IsSymbolSectionType(section_header.sh_type))
<< file_->GetPath() << " " << section_header.sh_type;
CHECK_NE(0U, section_header.sh_entsize) << file_->GetPath();
return section_header.sh_size / section_header.sh_entsize;
}
-Elf32_Sym* ElfFile::GetSymbol(Elf32_Word section_type,
- Elf32_Word i) const {
- Elf32_Sym* sym_start = GetSymbolSectionStart(section_type);
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetSymbol(Elf_Word section_type,
+ Elf_Word i) const {
+ Elf_Sym* sym_start = GetSymbolSectionStart(section_type);
if (sym_start == nullptr) {
return nullptr;
}
return sym_start + i;
}
-ElfFile::SymbolTable** ElfFile::GetSymbolTable(Elf32_Word section_type) {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+typename ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::SymbolTable** ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetSymbolTable(Elf_Word section_type) {
CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
switch (section_type) {
case SHT_SYMTAB: {
@@ -825,9 +1015,14 @@
}
}
-Elf32_Sym* ElfFile::FindSymbolByName(Elf32_Word section_type,
- const std::string& symbol_name,
- bool build_map) {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FindSymbolByName(Elf_Word section_type,
+ const std::string& symbol_name,
+ bool build_map) {
CHECK(!program_header_only_) << file_->GetPath();
CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
@@ -836,20 +1031,22 @@
if (*symbol_table == nullptr) {
DCHECK(build_map);
*symbol_table = new SymbolTable;
- Elf32_Shdr* symbol_section = FindSectionByType(section_type);
+ Elf_Shdr* symbol_section = FindSectionByType(section_type);
if (symbol_section == nullptr) {
return nullptr; // Failure condition.
}
- Elf32_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
+ Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
if (string_section == nullptr) {
return nullptr; // Failure condition.
}
for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
- Elf32_Sym* symbol = GetSymbol(section_type, i);
+ Elf_Sym* symbol = GetSymbol(section_type, i);
if (symbol == nullptr) {
return nullptr; // Failure condition.
}
- unsigned char type = ELF32_ST_TYPE(symbol->st_info);
+ unsigned char type = (sizeof(Elf_Addr) == sizeof(Elf64_Addr))
+ ? ELF64_ST_TYPE(symbol->st_info)
+ : ELF32_ST_TYPE(symbol->st_info);
if (type == STT_NOTYPE) {
continue;
}
@@ -857,7 +1054,7 @@
if (name == nullptr) {
continue;
}
- std::pair<SymbolTable::iterator, bool> result =
+ std::pair<typename SymbolTable::iterator, bool> result =
(*symbol_table)->insert(std::make_pair(name, symbol));
if (!result.second) {
// If a duplicate, make sure it has the same logical value. Seen on x86.
@@ -872,7 +1069,7 @@
}
}
CHECK(*symbol_table != nullptr);
- SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name);
+ typename SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name);
if (it == (*symbol_table)->end()) {
return nullptr;
}
@@ -880,16 +1077,16 @@
}
// Fall back to linear search
- Elf32_Shdr* symbol_section = FindSectionByType(section_type);
+ Elf_Shdr* symbol_section = FindSectionByType(section_type);
if (symbol_section == nullptr) {
return nullptr;
}
- Elf32_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
+ Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
if (string_section == nullptr) {
return nullptr;
}
for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
- Elf32_Sym* symbol = GetSymbol(section_type, i);
+ Elf_Sym* symbol = GetSymbol(section_type, i);
if (symbol == nullptr) {
return nullptr; // Failure condition.
}
@@ -904,20 +1101,30 @@
return nullptr;
}
-Elf32_Addr ElfFile::FindSymbolAddress(Elf32_Word section_type,
- const std::string& symbol_name,
- bool build_map) {
- Elf32_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map);
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Addr ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FindSymbolAddress(Elf_Word section_type,
+ const std::string& symbol_name,
+ bool build_map) {
+ Elf_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map);
if (symbol == nullptr) {
return 0;
}
return symbol->st_value;
}
-const char* ElfFile::GetString(Elf32_Shdr& string_section, Elf32_Word i) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+const char* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetString(Elf_Shdr& string_section, Elf_Word i) const {
CHECK(!program_header_only_) << file_->GetPath();
// TODO: remove this static_cast from enum when using -std=gnu++0x
- if (static_cast<Elf32_Word>(SHT_STRTAB) != string_section.sh_type) {
+ if (static_cast<Elf_Word>(SHT_STRTAB) != string_section.sh_type) {
return nullptr; // Failure condition.
}
if (i >= string_section.sh_size) {
@@ -934,18 +1141,33 @@
return reinterpret_cast<const char*>(string);
}
-Elf32_Word ElfFile::GetDynamicNum() const {
- return GetDynamicProgramHeader().p_filesz / sizeof(Elf32_Dyn);
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetDynamicNum() const {
+ return GetDynamicProgramHeader().p_filesz / sizeof(Elf_Dyn);
}
-Elf32_Dyn& ElfFile::GetDynamic(Elf32_Word i) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Dyn& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetDynamic(Elf_Word i) const {
CHECK_LT(i, GetDynamicNum()) << file_->GetPath();
return *(GetDynamicSectionStart() + i);
}
-Elf32_Dyn* ElfFile::FindDynamicByType(Elf32_Sword type) const {
- for (Elf32_Word i = 0; i < GetDynamicNum(); i++) {
- Elf32_Dyn* dyn = &GetDynamic(i);
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Dyn* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FindDynamicByType(Elf_Sword type) const {
+ for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
+ Elf_Dyn* dyn = &GetDynamic(i);
if (dyn->d_tag == type) {
return dyn;
}
@@ -953,8 +1175,13 @@
return NULL;
}
-Elf32_Word ElfFile::FindDynamicValueByType(Elf32_Sword type) const {
- Elf32_Dyn* dyn = FindDynamicByType(type);
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FindDynamicValueByType(Elf_Sword type) const {
+ Elf_Dyn* dyn = FindDynamicByType(type);
if (dyn == NULL) {
return 0;
} else {
@@ -962,53 +1189,88 @@
}
}
-Elf32_Rel* ElfFile::GetRelSectionStart(Elf32_Shdr& section_header) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Rel* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetRelSectionStart(Elf_Shdr& section_header) const {
CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
- return reinterpret_cast<Elf32_Rel*>(Begin() + section_header.sh_offset);
+ return reinterpret_cast<Elf_Rel*>(Begin() + section_header.sh_offset);
}
-Elf32_Word ElfFile::GetRelNum(Elf32_Shdr& section_header) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetRelNum(Elf_Shdr& section_header) const {
CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
CHECK_NE(0U, section_header.sh_entsize) << file_->GetPath();
return section_header.sh_size / section_header.sh_entsize;
}
-Elf32_Rel& ElfFile::GetRel(Elf32_Shdr& section_header, Elf32_Word i) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Rel& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetRel(Elf_Shdr& section_header, Elf_Word i) const {
CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
CHECK_LT(i, GetRelNum(section_header)) << file_->GetPath();
return *(GetRelSectionStart(section_header) + i);
}
-Elf32_Rela* ElfFile::GetRelaSectionStart(Elf32_Shdr& section_header) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Rela* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetRelaSectionStart(Elf_Shdr& section_header) const {
CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
- return reinterpret_cast<Elf32_Rela*>(Begin() + section_header.sh_offset);
+ return reinterpret_cast<Elf_Rela*>(Begin() + section_header.sh_offset);
}
-Elf32_Word ElfFile::GetRelaNum(Elf32_Shdr& section_header) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetRelaNum(Elf_Shdr& section_header) const {
CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
return section_header.sh_size / section_header.sh_entsize;
}
-Elf32_Rela& ElfFile::GetRela(Elf32_Shdr& section_header, Elf32_Word i) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Rela& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetRela(Elf_Shdr& section_header, Elf_Word i) const {
CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
CHECK_LT(i, GetRelaNum(section_header)) << file_->GetPath();
return *(GetRelaSectionStart(section_header) + i);
}
// Base on bionic phdr_table_get_load_size
-size_t ElfFile::GetLoadedSize() const {
- Elf32_Addr min_vaddr = 0xFFFFFFFFu;
- Elf32_Addr max_vaddr = 0x00000000u;
- for (Elf32_Word i = 0; i < GetProgramHeaderNum(); i++) {
- Elf32_Phdr* program_header = GetProgramHeader(i);
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+size_t ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GetLoadedSize() const {
+ Elf_Addr min_vaddr = 0xFFFFFFFFu;
+ Elf_Addr max_vaddr = 0x00000000u;
+ for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
+ Elf_Phdr* program_header = GetProgramHeader(i);
if (program_header->p_type != PT_LOAD) {
continue;
}
- Elf32_Addr begin_vaddr = program_header->p_vaddr;
+ Elf_Addr begin_vaddr = program_header->p_vaddr;
if (begin_vaddr < min_vaddr) {
min_vaddr = begin_vaddr;
}
- Elf32_Addr end_vaddr = program_header->p_vaddr + program_header->p_memsz;
+ Elf_Addr end_vaddr = program_header->p_vaddr + program_header->p_memsz;
if (end_vaddr > max_vaddr) {
max_vaddr = end_vaddr;
}
@@ -1020,7 +1282,12 @@
return loaded_size;
}
-bool ElfFile::Load(bool executable, std::string* error_msg) {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::Load(bool executable, std::string* error_msg) {
CHECK(program_header_only_) << file_->GetPath();
if (executable) {
@@ -1057,8 +1324,8 @@
}
bool reserved = false;
- for (Elf32_Word i = 0; i < GetProgramHeaderNum(); i++) {
- Elf32_Phdr* program_header = GetProgramHeader(i);
+ for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
+ Elf_Phdr* program_header = GetProgramHeader(i);
if (program_header == nullptr) {
*error_msg = StringPrintf("No program header for entry %d in ELF file %s.",
i, file_->GetPath().c_str());
@@ -1137,8 +1404,8 @@
}
if (file_length < (program_header->p_offset + program_header->p_memsz)) {
*error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF segment "
- "%d of %d bytes: '%s'", file_length, i,
- program_header->p_offset + program_header->p_memsz,
+ "%d of %" PRIu64 " bytes: '%s'", file_length, i,
+ static_cast<uint64_t>(program_header->p_offset + program_header->p_memsz),
file_->GetPath().c_str());
return false;
}
@@ -1170,10 +1437,10 @@
file_->GetPath().c_str());
return false;
}
- dynamic_section_start_ = reinterpret_cast<Elf32_Dyn*>(dsptr);
+ dynamic_section_start_ = reinterpret_cast<Elf_Dyn*>(dsptr);
- for (Elf32_Word i = 0; i < GetDynamicNum(); i++) {
- Elf32_Dyn& elf_dyn = GetDynamic(i);
+ for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
+ Elf_Dyn& elf_dyn = GetDynamic(i);
byte* d_ptr = base_address_ + elf_dyn.d_un.d_ptr;
switch (elf_dyn.d_tag) {
case DT_HASH: {
@@ -1182,7 +1449,7 @@
d_ptr, file_->GetPath().c_str());
return false;
}
- hash_section_start_ = reinterpret_cast<Elf32_Word*>(d_ptr);
+ hash_section_start_ = reinterpret_cast<Elf_Word*>(d_ptr);
break;
}
case DT_STRTAB: {
@@ -1200,7 +1467,7 @@
d_ptr, file_->GetPath().c_str());
return false;
}
- dynsym_section_start_ = reinterpret_cast<Elf32_Sym*>(d_ptr);
+ dynsym_section_start_ = reinterpret_cast<Elf_Sym*>(d_ptr);
break;
}
case DT_NULL: {
@@ -1228,7 +1495,12 @@
return true;
}
-bool ElfFile::ValidPointer(const byte* start) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::ValidPointer(const byte* start) const {
for (size_t i = 0; i < segments_.size(); ++i) {
const MemMap* segment = segments_[i];
if (segment->Begin() <= start && start < segment->End()) {
@@ -1239,14 +1511,19 @@
}
-Elf32_Shdr* ElfFile::FindSectionByName(const std::string& name) const {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FindSectionByName(const std::string& name) const {
CHECK(!program_header_only_);
- Elf32_Shdr* shstrtab_sec = GetSectionNameStringSection();
+ Elf_Shdr* shstrtab_sec = GetSectionNameStringSection();
if (shstrtab_sec == nullptr) {
return nullptr;
}
for (uint32_t i = 0; i < GetSectionHeaderNum(); i++) {
- Elf32_Shdr* shdr = GetSectionHeader(i);
+ Elf_Shdr* shdr = GetSectionHeader(i);
if (shdr == nullptr) {
return nullptr;
}
@@ -1731,14 +2008,19 @@
return true;
}
-bool ElfFile::FixupDebugSections(off_t base_address_delta) {
- const Elf32_Shdr* debug_info = FindSectionByName(".debug_info");
- const Elf32_Shdr* debug_abbrev = FindSectionByName(".debug_abbrev");
- const Elf32_Shdr* eh_frame = FindSectionByName(".eh_frame");
- const Elf32_Shdr* debug_str = FindSectionByName(".debug_str");
- const Elf32_Shdr* debug_line = FindSectionByName(".debug_line");
- const Elf32_Shdr* strtab_sec = FindSectionByName(".strtab");
- const Elf32_Shdr* symtab_sec = FindSectionByName(".symtab");
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FixupDebugSections(off_t base_address_delta) {
+ const Elf_Shdr* debug_info = FindSectionByName(".debug_info");
+ const Elf_Shdr* debug_abbrev = FindSectionByName(".debug_abbrev");
+ const Elf_Shdr* eh_frame = FindSectionByName(".eh_frame");
+ const Elf_Shdr* debug_str = FindSectionByName(".debug_str");
+ const Elf_Shdr* debug_line = FindSectionByName(".debug_line");
+ const Elf_Shdr* strtab_sec = FindSectionByName(".strtab");
+ const Elf_Shdr* symtab_sec = FindSectionByName(".symtab");
if (debug_info == nullptr || debug_abbrev == nullptr ||
debug_str == nullptr || strtab_sec == nullptr || symtab_sec == nullptr) {
@@ -1781,7 +2063,12 @@
return FixupDebugInfo(base_address_delta, info_iter.get());
}
-void ElfFile::GdbJITSupport() {
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+void ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::GdbJITSupport() {
// We only get here if we only are mapping the program header.
DCHECK(program_header_only_);
@@ -1789,15 +2076,18 @@
std::string error_msg;
// Make it MAP_PRIVATE so we can just give it to gdb if all the necessary
// sections are there.
- std::unique_ptr<ElfFile> all_ptr(Open(const_cast<File*>(file_), PROT_READ | PROT_WRITE,
- MAP_PRIVATE, &error_msg));
+ std::unique_ptr<ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>>
+ all_ptr(Open(const_cast<File*>(file_), PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, &error_msg));
if (all_ptr.get() == nullptr) {
return;
}
- ElfFile& all = *all_ptr;
+ ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>& all = *all_ptr;
// We need the eh_frame for gdb but debug info might be present without it.
- const Elf32_Shdr* eh_frame = all.FindSectionByName(".eh_frame");
+ const Elf_Shdr* eh_frame = all.FindSectionByName(".eh_frame");
if (eh_frame == nullptr) {
return;
}
@@ -1806,7 +2096,7 @@
// We need to add in a strtab and symtab to the image.
// all is MAP_PRIVATE so it can be written to freely.
// We also already have strtab and symtab so we are fine there.
- Elf32_Ehdr& elf_hdr = all.GetHeader();
+ Elf_Ehdr& elf_hdr = all.GetHeader();
elf_hdr.e_entry = 0;
elf_hdr.e_phoff = 0;
elf_hdr.e_phnum = 0;
@@ -1824,4 +2114,477 @@
gdb_file_mapping_.reset(all_ptr.release());
}
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::Strip(std::string* error_msg) {
+ // ELF files produced by MCLinker look roughly like this
+ //
+ // +------------+
+ // | Elf_Ehdr | contains number of Elf_Shdr and offset to first
+ // +------------+
+ // | Elf_Phdr | program headers
+ // | Elf_Phdr |
+ // | ... |
+ // | Elf_Phdr |
+ // +------------+
+ // | section | mixture of needed and unneeded sections
+ // +------------+
+ // | section |
+ // +------------+
+ // | ... |
+ // +------------+
+ // | section |
+ // +------------+
+ // | Elf_Shdr | section headers
+ // | Elf_Shdr |
+ // | ... | contains offset to section start
+ // | Elf_Shdr |
+ // +------------+
+ //
+ // To strip:
+ // - leave the Elf_Ehdr and Elf_Phdr values in place.
+ // - walk the sections making a new set of Elf_Shdr section headers for what we want to keep
+ // - move the sections are keeping up to fill in gaps of sections we want to strip
+ // - write new Elf_Shdr section headers to end of file, updating Elf_Ehdr
+ // - truncate rest of file
+ //
+
+ std::vector<Elf_Shdr> section_headers;
+ std::vector<Elf_Word> section_headers_original_indexes;
+ section_headers.reserve(GetSectionHeaderNum());
+
+
+ Elf_Shdr* string_section = GetSectionNameStringSection();
+ CHECK(string_section != nullptr);
+ for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
+ Elf_Shdr* sh = GetSectionHeader(i);
+ CHECK(sh != nullptr);
+ const char* name = GetString(*string_section, sh->sh_name);
+ if (name == nullptr) {
+ CHECK_EQ(0U, i);
+ section_headers.push_back(*sh);
+ section_headers_original_indexes.push_back(0);
+ continue;
+ }
+ if (StartsWith(name, ".debug")
+ || (strcmp(name, ".strtab") == 0)
+ || (strcmp(name, ".symtab") == 0)) {
+ continue;
+ }
+ section_headers.push_back(*sh);
+ section_headers_original_indexes.push_back(i);
+ }
+ CHECK_NE(0U, section_headers.size());
+ CHECK_EQ(section_headers.size(), section_headers_original_indexes.size());
+
+ // section 0 is the NULL section, sections start at offset of first section
+ CHECK(GetSectionHeader(1) != nullptr);
+ Elf_Off offset = GetSectionHeader(1)->sh_offset;
+ for (size_t i = 1; i < section_headers.size(); i++) {
+ Elf_Shdr& new_sh = section_headers[i];
+ Elf_Shdr* old_sh = GetSectionHeader(section_headers_original_indexes[i]);
+ CHECK(old_sh != nullptr);
+ CHECK_EQ(new_sh.sh_name, old_sh->sh_name);
+ if (old_sh->sh_addralign > 1) {
+ offset = RoundUp(offset, old_sh->sh_addralign);
+ }
+ if (old_sh->sh_offset == offset) {
+ // already in place
+ offset += old_sh->sh_size;
+ continue;
+ }
+ // shift section earlier
+ memmove(Begin() + offset,
+ Begin() + old_sh->sh_offset,
+ old_sh->sh_size);
+ new_sh.sh_offset = offset;
+ offset += old_sh->sh_size;
+ }
+
+ Elf_Off shoff = offset;
+ size_t section_headers_size_in_bytes = section_headers.size() * sizeof(Elf_Shdr);
+ memcpy(Begin() + offset, §ion_headers[0], section_headers_size_in_bytes);
+ offset += section_headers_size_in_bytes;
+
+ GetHeader().e_shnum = section_headers.size();
+ GetHeader().e_shoff = shoff;
+ int result = ftruncate(file_->Fd(), offset);
+ if (result != 0) {
+ *error_msg = StringPrintf("Failed to truncate while stripping ELF file: '%s': %s",
+ file_->GetPath().c_str(), strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+static const bool DEBUG_FIXUP = false;
+
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::Fixup(uintptr_t base_address) {
+ if (!FixupDynamic(base_address)) {
+ LOG(WARNING) << "Failed to fixup .dynamic in " << file_->GetPath();
+ return false;
+ }
+ if (!FixupSectionHeaders(base_address)) {
+ LOG(WARNING) << "Failed to fixup section headers in " << file_->GetPath();
+ return false;
+ }
+ if (!FixupProgramHeaders(base_address)) {
+ LOG(WARNING) << "Failed to fixup program headers in " << file_->GetPath();
+ return false;
+ }
+ if (!FixupSymbols(base_address, true)) {
+ LOG(WARNING) << "Failed to fixup .dynsym in " << file_->GetPath();
+ return false;
+ }
+ if (!FixupSymbols(base_address, false)) {
+ LOG(WARNING) << "Failed to fixup .symtab in " << file_->GetPath();
+ return false;
+ }
+ if (!FixupRelocations(base_address)) {
+ LOG(WARNING) << "Failed to fixup .rel.dyn in " << file_->GetPath();
+ return false;
+ }
+ if (!FixupDebugSections(base_address)) {
+ LOG(WARNING) << "Failed to fixup debug sections in " << file_->GetPath();
+ return false;
+ }
+ return true;
+}
+
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FixupDynamic(uintptr_t base_address) {
+ for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
+ Elf_Dyn& elf_dyn = GetDynamic(i);
+ Elf_Word d_tag = elf_dyn.d_tag;
+ if (IsDynamicSectionPointer(d_tag, GetHeader().e_machine)) {
+ Elf_Addr d_ptr = elf_dyn.d_un.d_ptr;
+ if (DEBUG_FIXUP) {
+ LOG(INFO) << StringPrintf("In %s moving Elf_Dyn[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
+ GetFile().GetPath().c_str(), i,
+ static_cast<uint64_t>(d_ptr),
+ static_cast<uint64_t>(d_ptr + base_address));
+ }
+ d_ptr += base_address;
+ elf_dyn.d_un.d_ptr = d_ptr;
+ }
+ }
+ return true;
+}
+
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FixupSectionHeaders(uintptr_t base_address) {
+ for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
+ Elf_Shdr* sh = GetSectionHeader(i);
+ CHECK(sh != nullptr);
+ // 0 implies that the section will not exist in the memory of the process
+ if (sh->sh_addr == 0) {
+ continue;
+ }
+ if (DEBUG_FIXUP) {
+ LOG(INFO) << StringPrintf("In %s moving Elf_Shdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
+ GetFile().GetPath().c_str(), i,
+ static_cast<uint64_t>(sh->sh_addr),
+ static_cast<uint64_t>(sh->sh_addr + base_address));
+ }
+ sh->sh_addr += base_address;
+ }
+ return true;
+}
+
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FixupProgramHeaders(uintptr_t base_address) {
+ // TODO: ELFObjectFile doesn't have give to Elf_Phdr, so we do that ourselves for now.
+ for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
+ Elf_Phdr* ph = GetProgramHeader(i);
+ CHECK(ph != nullptr);
+ CHECK_EQ(ph->p_vaddr, ph->p_paddr) << GetFile().GetPath() << " i=" << i;
+ CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
+ << GetFile().GetPath() << " i=" << i;
+ if (DEBUG_FIXUP) {
+ LOG(INFO) << StringPrintf("In %s moving Elf_Phdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
+ GetFile().GetPath().c_str(), i,
+ static_cast<uint64_t>(ph->p_vaddr),
+ static_cast<uint64_t>(ph->p_vaddr + base_address));
+ }
+ ph->p_vaddr += base_address;
+ ph->p_paddr += base_address;
+ CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
+ << GetFile().GetPath() << " i=" << i;
+ }
+ return true;
+}
+
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FixupSymbols(uintptr_t base_address, bool dynamic) {
+ Elf_Word section_type = dynamic ? SHT_DYNSYM : SHT_SYMTAB;
+ // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile
+ Elf_Shdr* symbol_section = FindSectionByType(section_type);
+ if (symbol_section == nullptr) {
+ // file is missing optional .symtab
+ CHECK(!dynamic) << GetFile().GetPath();
+ return true;
+ }
+ for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
+ Elf_Sym* symbol = GetSymbol(section_type, i);
+ CHECK(symbol != nullptr);
+ if (symbol->st_value != 0) {
+ if (DEBUG_FIXUP) {
+ LOG(INFO) << StringPrintf("In %s moving Elf_Sym[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
+ GetFile().GetPath().c_str(), i,
+ static_cast<uint64_t>(symbol->st_value),
+ static_cast<uint64_t>(symbol->st_value + base_address));
+ }
+ symbol->st_value += base_address;
+ }
+ }
+ return true;
+}
+
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
+ ::FixupRelocations(uintptr_t base_address) {
+ for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
+ Elf_Shdr* sh = GetSectionHeader(i);
+ CHECK(sh != nullptr);
+ if (sh->sh_type == SHT_REL) {
+ for (uint32_t i = 0; i < GetRelNum(*sh); i++) {
+ Elf_Rel& rel = GetRel(*sh, i);
+ if (DEBUG_FIXUP) {
+ LOG(INFO) << StringPrintf("In %s moving Elf_Rel[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
+ GetFile().GetPath().c_str(), i,
+ static_cast<uint64_t>(rel.r_offset),
+ static_cast<uint64_t>(rel.r_offset + base_address));
+ }
+ rel.r_offset += base_address;
+ }
+ } else if (sh->sh_type == SHT_RELA) {
+ for (uint32_t i = 0; i < GetRelaNum(*sh); i++) {
+ Elf_Rela& rela = GetRela(*sh, i);
+ if (DEBUG_FIXUP) {
+ LOG(INFO) << StringPrintf("In %s moving Elf_Rela[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
+ GetFile().GetPath().c_str(), i,
+ static_cast<uint64_t>(rela.r_offset),
+ static_cast<uint64_t>(rela.r_offset + base_address));
+ }
+ rela.r_offset += base_address;
+ }
+ }
+ }
+ return true;
+}
+
+// Explicit instantiations
+template class ElfFileImpl<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Word,
+ Elf32_Sword, Elf32_Addr, Elf32_Sym, Elf32_Rel, Elf32_Rela, Elf32_Dyn, Elf32_Off>;
+template class ElfFileImpl<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Word,
+ Elf64_Sword, Elf64_Addr, Elf64_Sym, Elf64_Rel, Elf64_Rela, Elf64_Dyn, Elf64_Off>;
+
+ElfFile::ElfFile(ElfFileImpl32* elf32) : is_elf64_(false) {
+ CHECK_NE(elf32, static_cast<ElfFileImpl32*>(nullptr));
+ elf_.elf32_ = elf32;
+}
+
+ElfFile::ElfFile(ElfFileImpl64* elf64) : is_elf64_(true) {
+ CHECK_NE(elf64, static_cast<ElfFileImpl64*>(nullptr));
+ elf_.elf64_ = elf64;
+}
+
+ElfFile::~ElfFile() {
+ if (is_elf64_) {
+ CHECK_NE(elf_.elf64_, static_cast<ElfFileImpl64*>(nullptr));
+ delete elf_.elf64_;
+ } else {
+ CHECK_NE(elf_.elf32_, static_cast<ElfFileImpl32*>(nullptr));
+ delete elf_.elf32_;
+ }
+}
+
+ElfFile* ElfFile::Open(File* file, bool writable, bool program_header_only, std::string* error_msg) {
+ if (file->GetLength() < EI_NIDENT) {
+ *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
+ file->GetPath().c_str());
+ return nullptr;
+ }
+ std::unique_ptr<MemMap> map(MemMap::MapFile(EI_NIDENT, PROT_READ, MAP_PRIVATE, file->Fd(), 0,
+ file->GetPath().c_str(), error_msg));
+ if (map == nullptr && map->Size() != EI_NIDENT) {
+ return nullptr;
+ }
+ byte *header = map->Begin();
+ if (header[EI_CLASS] == ELFCLASS64) {
+ ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, writable, program_header_only, error_msg);
+ if (elf_file_impl == nullptr)
+ return nullptr;
+ return new ElfFile(elf_file_impl);
+ } else if (header[EI_CLASS] == ELFCLASS32) {
+ ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, writable, program_header_only, error_msg);
+ if (elf_file_impl == nullptr)
+ return nullptr;
+ return new ElfFile(elf_file_impl);
+ } else {
+ *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
+ ELFCLASS32, ELFCLASS64,
+ file->GetPath().c_str(),
+ header[EI_CLASS]);
+ return nullptr;
+ }
+}
+
+ElfFile* ElfFile::Open(File* file, int mmap_prot, int mmap_flags, std::string* error_msg) {
+ if (file->GetLength() < EI_NIDENT) {
+ *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
+ file->GetPath().c_str());
+ return nullptr;
+ }
+ std::unique_ptr<MemMap> map(MemMap::MapFile(EI_NIDENT, PROT_READ, MAP_PRIVATE, file->Fd(), 0,
+ file->GetPath().c_str(), error_msg));
+ if (map == nullptr && map->Size() != EI_NIDENT) {
+ return nullptr;
+ }
+ byte *header = map->Begin();
+ if (header[EI_CLASS] == ELFCLASS64) {
+ ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, mmap_prot, mmap_flags, error_msg);
+ if (elf_file_impl == nullptr)
+ return nullptr;
+ return new ElfFile(elf_file_impl);
+ } else if (header[EI_CLASS] == ELFCLASS32) {
+ ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, mmap_prot, mmap_flags, error_msg);
+ if (elf_file_impl == nullptr)
+ return nullptr;
+ return new ElfFile(elf_file_impl);
+ } else {
+ *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
+ ELFCLASS32, ELFCLASS64,
+ file->GetPath().c_str(),
+ header[EI_CLASS]);
+ return nullptr;
+ }
+}
+
+#define DELEGATE_TO_IMPL(func, ...) \
+ if (is_elf64_) { \
+ CHECK_NE(elf_.elf64_, static_cast<ElfFileImpl64*>(nullptr)); \
+ return elf_.elf64_->func(__VA_ARGS__); \
+ } else { \
+ CHECK_NE(elf_.elf32_, static_cast<ElfFileImpl32*>(nullptr)); \
+ return elf_.elf32_->func(__VA_ARGS__); \
+ }
+
+bool ElfFile::Load(bool executable, std::string* error_msg) {
+ DELEGATE_TO_IMPL(Load, executable, error_msg);
+}
+
+const byte* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const {
+ DELEGATE_TO_IMPL(FindDynamicSymbolAddress, symbol_name);
+}
+
+size_t ElfFile::Size() const {
+ DELEGATE_TO_IMPL(Size);
+}
+
+byte* ElfFile::Begin() const {
+ DELEGATE_TO_IMPL(Begin);
+}
+
+byte* ElfFile::End() const {
+ DELEGATE_TO_IMPL(End);
+}
+
+const File& ElfFile::GetFile() const {
+ DELEGATE_TO_IMPL(GetFile);
+}
+
+bool ElfFile::GetSectionOffsetAndSize(const char* section_name, uint64_t* offset, uint64_t* size) {
+ if (is_elf64_) {
+ CHECK_NE(elf_.elf64_, static_cast<ElfFileImpl64*>(nullptr));
+
+ Elf64_Shdr *shdr = elf_.elf64_->FindSectionByName(section_name);
+ if (shdr == nullptr)
+ return false;
+
+ if (offset != nullptr)
+ *offset = shdr->sh_offset;
+ if (size != nullptr)
+ *size = shdr->sh_size;
+ return true;
+ } else {
+ CHECK_NE(elf_.elf32_, static_cast<ElfFileImpl32*>(nullptr));
+
+ Elf32_Shdr *shdr = elf_.elf32_->FindSectionByName(section_name);
+ if (shdr == nullptr)
+ return false;
+
+ if (offset != nullptr)
+ *offset = shdr->sh_offset;
+ if (size != nullptr)
+ *size = shdr->sh_size;
+ return true;
+ }
+}
+
+uint64_t ElfFile::FindSymbolAddress(unsigned section_type,
+ const std::string& symbol_name,
+ bool build_map) {
+ DELEGATE_TO_IMPL(FindSymbolAddress, section_type, symbol_name, build_map);
+}
+
+size_t ElfFile::GetLoadedSize() const {
+ DELEGATE_TO_IMPL(GetLoadedSize);
+}
+
+bool ElfFile::Strip(File* file, std::string* error_msg) {
+ std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, error_msg));
+ if (elf_file.get() == nullptr) {
+ return false;
+ }
+
+ if (elf_file->is_elf64_)
+ return elf_file->elf_.elf64_->Strip(error_msg);
+ else
+ return elf_file->elf_.elf32_->Strip(error_msg);
+}
+
+bool ElfFile::Fixup(uintptr_t base_address) {
+ DELEGATE_TO_IMPL(Fixup, base_address);
+}
+
+ElfFileImpl32* ElfFile::GetImpl32() const {
+ CHECK(!is_elf64_);
+ CHECK_NE(elf_.elf32_, static_cast<ElfFileImpl32*>(nullptr));
+ return elf_.elf32_;
+}
+
+ElfFileImpl64* ElfFile::GetImpl64() const {
+ CHECK(is_elf64_);
+ CHECK_NE(elf_.elf64_, static_cast<ElfFileImpl64*>(nullptr));
+ return elf_.elf64_;
+}
+
} // namespace art
diff --git a/runtime/elf_file.h b/runtime/elf_file.h
index 916d693..ea6538b 100644
--- a/runtime/elf_file.h
+++ b/runtime/elf_file.h
@@ -17,24 +17,13 @@
#ifndef ART_RUNTIME_ELF_FILE_H_
#define ART_RUNTIME_ELF_FILE_H_
-#include <map>
-#include <memory>
-#include <vector>
+#include <string>
#include "base/unix_file/fd_file.h"
-#include "globals.h"
-#include "elf_utils.h"
-#include "mem_map.h"
-#include "os.h"
+#include "elf_file_impl.h"
namespace art {
-// Interface to GDB JIT for backtrace information.
-extern "C" {
- struct JITCodeEntry;
-}
-
-
// Used for compile time and runtime for ElfFile access. Because of
// the need for use at runtime, cannot directly use LLVM classes such as
// ELFObjectFile.
@@ -46,162 +35,50 @@
static ElfFile* Open(File* file, int mmap_prot, int mmap_flags, std::string* error_msg);
~ElfFile();
+ const bool is_elf64_;
+
// Load segments into memory based on PT_LOAD program headers
-
- const File& GetFile() const {
- return *file_;
- }
-
- byte* Begin() const {
- return map_->Begin();
- }
-
- byte* End() const {
- return map_->End();
- }
-
- size_t Size() const {
- return map_->Size();
- }
-
- Elf32_Ehdr& GetHeader() const;
-
- Elf32_Word GetProgramHeaderNum() const;
- Elf32_Phdr* GetProgramHeader(Elf32_Word) const;
-
- Elf32_Word GetSectionHeaderNum() const;
- Elf32_Shdr* GetSectionHeader(Elf32_Word) const;
- Elf32_Shdr* FindSectionByType(Elf32_Word type) const;
- Elf32_Shdr* FindSectionByName(const std::string& name) const;
-
- Elf32_Shdr* GetSectionNameStringSection() const;
-
- // Find .dynsym using .hash for more efficient lookup than FindSymbolAddress.
- const byte* FindDynamicSymbolAddress(const std::string& symbol_name) const;
-
- Elf32_Word GetSymbolNum(Elf32_Shdr&) const;
- Elf32_Sym* GetSymbol(Elf32_Word section_type, Elf32_Word i) const;
-
- // Find address of symbol in specified table, returning 0 if it is
- // not found. See FindSymbolByName for an explanation of build_map.
- Elf32_Addr FindSymbolAddress(Elf32_Word section_type,
- const std::string& symbol_name,
- bool build_map);
-
- // Lookup a string given string section and offset. Returns nullptr for
- // special 0 offset.
- const char* GetString(Elf32_Shdr&, Elf32_Word) const;
-
- Elf32_Word GetDynamicNum() const;
- Elf32_Dyn& GetDynamic(Elf32_Word) const;
-
- Elf32_Word GetRelNum(Elf32_Shdr&) const;
- Elf32_Rel& GetRel(Elf32_Shdr&, Elf32_Word) const;
-
- Elf32_Word GetRelaNum(Elf32_Shdr&) const;
- Elf32_Rela& GetRela(Elf32_Shdr&, Elf32_Word) const;
-
- // Returns the expected size when the file is loaded at runtime
- size_t GetLoadedSize() const;
-
- // Load segments into memory based on PT_LOAD program headers.
- // executable is true at run time, false at compile time.
bool Load(bool executable, std::string* error_msg);
- bool FixupDebugSections(off_t base_address_delta);
+ const byte* FindDynamicSymbolAddress(const std::string& symbol_name) const;
+
+ size_t Size() const;
+
+ byte* Begin() const;
+
+ byte* End() const;
+
+ const File& GetFile() const;
+
+ bool GetSectionOffsetAndSize(const char* section_name, uint64_t* offset, uint64_t* size);
+
+ uint64_t FindSymbolAddress(unsigned section_type,
+ const std::string& symbol_name,
+ bool build_map);
+
+ size_t GetLoadedSize() const;
+
+ // Strip an ELF file of unneeded debugging information.
+ // Returns true on success, false on failure.
+ static bool Strip(File* file, std::string* error_msg);
+
+ // Fixup an ELF file so that that oat header will be loaded at oat_begin.
+ // Returns true on success, false on failure.
+ static bool Fixup(File* file, uintptr_t oat_data_begin);
+
+ bool Fixup(uintptr_t base_address);
+
+ ElfFileImpl32* GetImpl32() const;
+ ElfFileImpl64* GetImpl64() const;
private:
- ElfFile(File* file, bool writable, bool program_header_only);
+ explicit ElfFile(ElfFileImpl32* elf32);
+ explicit ElfFile(ElfFileImpl64* elf64);
- bool Setup(int prot, int flags, std::string* error_msg);
-
- bool SetMap(MemMap* map, std::string* error_msg);
-
- byte* GetProgramHeadersStart() const;
- byte* GetSectionHeadersStart() const;
- Elf32_Phdr& GetDynamicProgramHeader() const;
- Elf32_Dyn* GetDynamicSectionStart() const;
- Elf32_Sym* GetSymbolSectionStart(Elf32_Word section_type) const;
- const char* GetStringSectionStart(Elf32_Word section_type) const;
- Elf32_Rel* GetRelSectionStart(Elf32_Shdr&) const;
- Elf32_Rela* GetRelaSectionStart(Elf32_Shdr&) const;
- Elf32_Word* GetHashSectionStart() const;
- Elf32_Word GetHashBucketNum() const;
- Elf32_Word GetHashChainNum() const;
- Elf32_Word GetHashBucket(size_t i, bool* ok) const;
- Elf32_Word GetHashChain(size_t i, bool* ok) const;
-
- typedef std::map<std::string, Elf32_Sym*> SymbolTable;
- SymbolTable** GetSymbolTable(Elf32_Word section_type);
-
- bool ValidPointer(const byte* start) const;
-
- const Elf32_Sym* FindDynamicSymbol(const std::string& symbol_name) const;
-
- // Check that certain sections and their dependencies exist.
- bool CheckSectionsExist(std::string* error_msg) const;
-
- // Check that the link of the first section links to the second section.
- bool CheckSectionsLinked(const byte* source, const byte* target) const;
-
- // Check whether the offset is in range, and set to target to Begin() + offset if OK.
- bool CheckAndSet(Elf32_Off offset, const char* label, byte** target, std::string* error_msg);
-
- // Find symbol in specified table, returning nullptr if it is not found.
- //
- // If build_map is true, builds a map to speed repeated access. The
- // map does not included untyped symbol values (aka STT_NOTYPE)
- // since they can contain duplicates. If build_map is false, the map
- // will be used if it was already created. Typically build_map
- // should be set unless only a small number of symbols will be
- // looked up.
- Elf32_Sym* FindSymbolByName(Elf32_Word section_type,
- const std::string& symbol_name,
- bool build_map);
-
- Elf32_Phdr* FindProgamHeaderByType(Elf32_Word type) const;
-
- Elf32_Dyn* FindDynamicByType(Elf32_Sword type) const;
- Elf32_Word FindDynamicValueByType(Elf32_Sword type) const;
-
- // Lookup a string by section type. Returns nullptr for special 0 offset.
- const char* GetString(Elf32_Word section_type, Elf32_Word) const;
-
- const File* const file_;
- const bool writable_;
- const bool program_header_only_;
-
- // ELF header mapping. If program_header_only_ is false, will
- // actually point to the entire elf file.
- std::unique_ptr<MemMap> map_;
- Elf32_Ehdr* header_;
- std::vector<MemMap*> segments_;
-
- // Pointer to start of first PT_LOAD program segment after Load()
- // when program_header_only_ is true.
- byte* base_address_;
-
- // The program header should always available but use GetProgramHeadersStart() to be sure.
- byte* program_headers_start_;
-
- // Conditionally available values. Use accessors to ensure they exist if they are required.
- byte* section_headers_start_;
- Elf32_Phdr* dynamic_program_header_;
- Elf32_Dyn* dynamic_section_start_;
- Elf32_Sym* symtab_section_start_;
- Elf32_Sym* dynsym_section_start_;
- char* strtab_section_start_;
- char* dynstr_section_start_;
- Elf32_Word* hash_section_start_;
-
- SymbolTable* symtab_symbol_table_;
- SymbolTable* dynsym_symbol_table_;
-
- // Support for GDB JIT
- byte* jit_elf_image_;
- JITCodeEntry* jit_gdb_entry_;
- std::unique_ptr<ElfFile> gdb_file_mapping_;
- void GdbJITSupport();
+ union ElfFileContainer {
+ ElfFileImpl32* elf32_;
+ ElfFileImpl64* elf64_;
+ } elf_;
};
} // namespace art
diff --git a/runtime/elf_file_impl.h b/runtime/elf_file_impl.h
new file mode 100644
index 0000000..942dc291
--- /dev/null
+++ b/runtime/elf_file_impl.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2012 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 ART_RUNTIME_ELF_FILE_IMPL_H_
+#define ART_RUNTIME_ELF_FILE_IMPL_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/unix_file/fd_file.h"
+#include "globals.h"
+#include "elf_utils.h"
+#include "mem_map.h"
+#include "os.h"
+
+namespace art {
+
+extern "C" {
+ struct JITCodeEntry;
+}
+
+template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
+ typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
+ typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
+class ElfFileImpl {
+ public:
+ static ElfFileImpl* Open(File* file, bool writable, bool program_header_only, std::string* error_msg);
+ static ElfFileImpl* Open(File* file, int mmap_prot, int mmap_flags, std::string* error_msg);
+ ~ElfFileImpl();
+
+ const File& GetFile() const {
+ return *file_;
+ }
+
+ byte* Begin() const {
+ return map_->Begin();
+ }
+
+ byte* End() const {
+ return map_->End();
+ }
+
+ size_t Size() const {
+ return map_->Size();
+ }
+
+ Elf_Ehdr& GetHeader() const;
+
+ Elf_Word GetProgramHeaderNum() const;
+ Elf_Phdr* GetProgramHeader(Elf_Word) const;
+
+ Elf_Word GetSectionHeaderNum() const;
+ Elf_Shdr* GetSectionHeader(Elf_Word) const;
+ Elf_Shdr* FindSectionByType(Elf_Word type) const;
+ Elf_Shdr* FindSectionByName(const std::string& name) const;
+
+ Elf_Shdr* GetSectionNameStringSection() const;
+
+ // Find .dynsym using .hash for more efficient lookup than FindSymbolAddress.
+ const byte* FindDynamicSymbolAddress(const std::string& symbol_name) const;
+
+ static bool IsSymbolSectionType(Elf_Word section_type);
+ Elf_Word GetSymbolNum(Elf_Shdr&) const;
+ Elf_Sym* GetSymbol(Elf_Word section_type, Elf_Word i) const;
+
+ // Find address of symbol in specified table, returning 0 if it is
+ // not found. See FindSymbolByName for an explanation of build_map.
+ Elf_Addr FindSymbolAddress(Elf_Word section_type,
+ const std::string& symbol_name,
+ bool build_map);
+
+ // Lookup a string given string section and offset. Returns nullptr for
+ // special 0 offset.
+ const char* GetString(Elf_Shdr&, Elf_Word) const;
+
+ Elf_Word GetDynamicNum() const;
+ Elf_Dyn& GetDynamic(Elf_Word) const;
+
+ Elf_Word GetRelNum(Elf_Shdr&) const;
+ Elf_Rel& GetRel(Elf_Shdr&, Elf_Word) const;
+
+ Elf_Word GetRelaNum(Elf_Shdr&) const;
+ Elf_Rela& GetRela(Elf_Shdr&, Elf_Word) const;
+
+ // Returns the expected size when the file is loaded at runtime
+ size_t GetLoadedSize() const;
+
+ // Load segments into memory based on PT_LOAD program headers.
+ // executable is true at run time, false at compile time.
+ bool Load(bool executable, std::string* error_msg);
+
+ bool Fixup(uintptr_t base_address);
+ bool FixupDynamic(uintptr_t base_address);
+ bool FixupSectionHeaders(uintptr_t base_address);
+ bool FixupProgramHeaders(uintptr_t base_address);
+ bool FixupSymbols(uintptr_t base_address, bool dynamic);
+ bool FixupRelocations(uintptr_t base_address);
+ bool FixupDebugSections(off_t base_address_delta);
+
+ bool Strip(std::string* error_msg);
+
+ private:
+ ElfFileImpl(File* file, bool writable, bool program_header_only);
+
+ bool Setup(int prot, int flags, std::string* error_msg);
+
+ bool SetMap(MemMap* map, std::string* error_msg);
+
+ byte* GetProgramHeadersStart() const;
+ byte* GetSectionHeadersStart() const;
+ Elf_Phdr& GetDynamicProgramHeader() const;
+ Elf_Dyn* GetDynamicSectionStart() const;
+ Elf_Sym* GetSymbolSectionStart(Elf_Word section_type) const;
+ const char* GetStringSectionStart(Elf_Word section_type) const;
+ Elf_Rel* GetRelSectionStart(Elf_Shdr&) const;
+ Elf_Rela* GetRelaSectionStart(Elf_Shdr&) const;
+ Elf_Word* GetHashSectionStart() const;
+ Elf_Word GetHashBucketNum() const;
+ Elf_Word GetHashChainNum() const;
+ Elf_Word GetHashBucket(size_t i, bool* ok) const;
+ Elf_Word GetHashChain(size_t i, bool* ok) const;
+
+ typedef std::map<std::string, Elf_Sym*> SymbolTable;
+ SymbolTable** GetSymbolTable(Elf_Word section_type);
+
+ bool ValidPointer(const byte* start) const;
+
+ const Elf_Sym* FindDynamicSymbol(const std::string& symbol_name) const;
+
+ // Check that certain sections and their dependencies exist.
+ bool CheckSectionsExist(std::string* error_msg) const;
+
+ // Check that the link of the first section links to the second section.
+ bool CheckSectionsLinked(const byte* source, const byte* target) const;
+
+ // Check whether the offset is in range, and set to target to Begin() + offset if OK.
+ bool CheckAndSet(Elf32_Off offset, const char* label, byte** target, std::string* error_msg);
+
+ // Find symbol in specified table, returning nullptr if it is not found.
+ //
+ // If build_map is true, builds a map to speed repeated access. The
+ // map does not included untyped symbol values (aka STT_NOTYPE)
+ // since they can contain duplicates. If build_map is false, the map
+ // will be used if it was already created. Typically build_map
+ // should be set unless only a small number of symbols will be
+ // looked up.
+ Elf_Sym* FindSymbolByName(Elf_Word section_type,
+ const std::string& symbol_name,
+ bool build_map);
+
+ Elf_Phdr* FindProgamHeaderByType(Elf_Word type) const;
+
+ Elf_Dyn* FindDynamicByType(Elf_Sword type) const;
+ Elf_Word FindDynamicValueByType(Elf_Sword type) const;
+
+ // Lookup a string by section type. Returns nullptr for special 0 offset.
+ const char* GetString(Elf_Word section_type, Elf_Word) const;
+
+ const File* const file_;
+ const bool writable_;
+ const bool program_header_only_;
+
+ // ELF header mapping. If program_header_only_ is false, will
+ // actually point to the entire elf file.
+ std::unique_ptr<MemMap> map_;
+ Elf_Ehdr* header_;
+ std::vector<MemMap*> segments_;
+
+ // Pointer to start of first PT_LOAD program segment after Load()
+ // when program_header_only_ is true.
+ byte* base_address_;
+
+ // The program header should always available but use GetProgramHeadersStart() to be sure.
+ byte* program_headers_start_;
+
+ // Conditionally available values. Use accessors to ensure they exist if they are required.
+ byte* section_headers_start_;
+ Elf_Phdr* dynamic_program_header_;
+ Elf_Dyn* dynamic_section_start_;
+ Elf_Sym* symtab_section_start_;
+ Elf_Sym* dynsym_section_start_;
+ char* strtab_section_start_;
+ char* dynstr_section_start_;
+ Elf_Word* hash_section_start_;
+
+ SymbolTable* symtab_symbol_table_;
+ SymbolTable* dynsym_symbol_table_;
+
+ // Support for GDB JIT
+ byte* jit_elf_image_;
+ JITCodeEntry* jit_gdb_entry_;
+ std::unique_ptr<ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
+ Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel,
+ Elf_Rela, Elf_Dyn, Elf_Off>> gdb_file_mapping_;
+ void GdbJITSupport();
+};
+
+// Explicitly instantiated in elf_file.cc
+typedef ElfFileImpl<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Word, Elf32_Sword,
+ Elf32_Addr, Elf32_Sym, Elf32_Rel, Elf32_Rela, Elf32_Dyn, Elf32_Off> ElfFileImpl32;
+typedef ElfFileImpl<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Word, Elf64_Sword,
+ Elf64_Addr, Elf64_Sym, Elf64_Rel, Elf64_Rela, Elf64_Dyn, Elf64_Off> ElfFileImpl64;
+
+} // namespace art
+
+#endif // ART_RUNTIME_ELF_FILE_IMPL_H_
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index a896f3e..a8a8307 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -47,9 +47,11 @@
std::string* error_msg) {
std::unique_ptr<OatFile> oat_file(new OatFile(location, false));
oat_file->elf_file_.reset(elf_file);
- Elf32_Shdr* hdr = elf_file->FindSectionByName(".rodata");
- oat_file->begin_ = elf_file->Begin() + hdr->sh_offset;
- oat_file->end_ = elf_file->Begin() + hdr->sh_size + hdr->sh_offset;
+ uint64_t offset, size;
+ bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
+ CHECK(has_section);
+ oat_file->begin_ = elf_file->Begin() + offset;
+ oat_file->end_ = elf_file->Begin() + size + offset;
return oat_file->Setup(error_msg) ? oat_file.release() : nullptr;
}
diff --git a/test/005-annotations/build b/test/005-annotations/build
index 1690213..2474055 100644
--- a/test/005-annotations/build
+++ b/test/005-annotations/build
@@ -23,5 +23,6 @@
${JAVAC} -d classes `find src -name '*.java'`
# ...but not at run time.
-rm classes/android/test/anno/MissingAnnotation.class
+rm 'classes/android/test/anno/MissingAnnotation.class'
+rm 'classes/android/test/anno/ClassWithInnerAnnotationClass$MissingInnerAnnotationClass.class'
${DX} -JXmx256m --debug --dex --output=$TEST_NAME.jar classes
diff --git a/test/005-annotations/src/android/test/anno/ClassWithInnerAnnotationClass.java b/test/005-annotations/src/android/test/anno/ClassWithInnerAnnotationClass.java
new file mode 100644
index 0000000..c69e01a
--- /dev/null
+++ b/test/005-annotations/src/android/test/anno/ClassWithInnerAnnotationClass.java
@@ -0,0 +1,8 @@
+package android.test.anno;
+
+import java.lang.annotation.*;
+
+public class ClassWithInnerAnnotationClass {
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MissingInnerAnnotationClass {}
+}
diff --git a/test/005-annotations/src/android/test/anno/TestAnnotations.java b/test/005-annotations/src/android/test/anno/TestAnnotations.java
index 4eabb12..1deff33 100644
--- a/test/005-annotations/src/android/test/anno/TestAnnotations.java
+++ b/test/005-annotations/src/android/test/anno/TestAnnotations.java
@@ -149,26 +149,24 @@
testArrays();
testArrayProblem();
- //System.exit(0);
System.out.println(
"AnnoSimpleField " + AnnoSimpleField.class.isAnnotation() +
", SimplyNoted " + SimplyNoted.class.isAnnotation());
- Class clazz;
- clazz = SimplyNoted.class;
- printAnnotations(clazz);
- clazz = INoted.class;
- printAnnotations(clazz);
- clazz = SubNoted.class;
- printAnnotations(clazz);
- clazz = FullyNoted.class;
- printAnnotations(clazz);
+ printAnnotations(SimplyNoted.class);
+ printAnnotations(INoted.class);
+ printAnnotations(SubNoted.class);
+ printAnnotations(FullyNoted.class);
- Annotation anno;
+ try {
+ ClassWithInnerAnnotationClass.class.getDeclaredClasses();
+ throw new AssertionError();
+ } catch (NoClassDefFoundError expected) {
+ }
// this is expected to be non-null
- anno = SimplyNoted.class.getAnnotation(AnnoSimpleType.class);
+ Annotation anno = SimplyNoted.class.getAnnotation(AnnoSimpleType.class);
System.out.println("SimplyNoted.get(AnnoSimpleType) = " + anno);
// this is non-null if the @Inherited tag is present
anno = SubNoted.class.getAnnotation(AnnoSimpleType.class);
diff --git a/test/115-native-bridge/src/NativeBridgeMain.java b/test/115-native-bridge/src/NativeBridgeMain.java
index a531f92..2405627 100644
--- a/test/115-native-bridge/src/NativeBridgeMain.java
+++ b/test/115-native-bridge/src/NativeBridgeMain.java
@@ -15,6 +15,7 @@
*/
import java.lang.reflect.Method;
+import java.lang.System;
// This is named Main as it is a copy of JniTest, so that we can re-use the native implementations
// from libarttest.
@@ -29,6 +30,7 @@
testShortMethod();
testBooleanMethod();
testCharMethod();
+ testEnvironment();
}
public static native void testFindClassOnAttachedNativeThread();
@@ -147,6 +149,24 @@
}
}
}
+
+ private static void testEnvironment() {
+ String osArch = System.getProperty("os.arch");
+ if (!"os.arch".equals(osArch)) {
+ throw new AssertionError("unexpected value for os.arch: " + osArch);
+ }
+ // TODO: improve the build script to get these running as well.
+ // if (!"cpu_abi".equals(Build.CPU_ABI)) {
+ // throw new AssertionError("unexpected value for cpu_abi");
+ // }
+ // if (!"cpu_abi2".equals(Build.CPU_ABI2)) {
+ // throw new AssertionError("unexpected value for cpu_abi2");
+ // }
+ // String[] expectedSupportedAbis = {"supported1", "supported2", "supported3"};
+ // if (Arrays.equals(expectedSupportedAbis, Build.SUPPORTED_ABIS)) {
+ // throw new AssertionError("unexpected value for supported_abis");
+ // }
+ }
}
public class NativeBridgeMain {
diff --git a/test/123-compiler-regressions-mt/expected.txt b/test/123-compiler-regressions-mt/expected.txt
new file mode 100644
index 0000000..a11e5bf
--- /dev/null
+++ b/test/123-compiler-regressions-mt/expected.txt
@@ -0,0 +1,2 @@
+b17689750TestVolatile passed.
+b17689750TestMonitor passed.
diff --git a/test/123-compiler-regressions-mt/info.txt b/test/123-compiler-regressions-mt/info.txt
new file mode 100644
index 0000000..cac7e75
--- /dev/null
+++ b/test/123-compiler-regressions-mt/info.txt
@@ -0,0 +1,6 @@
+This is a test for bad optimizations affecting multi-threaded program
+behavior.
+
+This test covers fixed AOT/JIT bugs to prevent regressions.
+
+17689750 GVN assigns the same value names across MONITOR_ENTER and volatile reads.
diff --git a/test/123-compiler-regressions-mt/src/Main.java b/test/123-compiler-regressions-mt/src/Main.java
new file mode 100644
index 0000000..11fa021
--- /dev/null
+++ b/test/123-compiler-regressions-mt/src/Main.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Test for Jit regressions.
+ */
+public class Main {
+ public static void main(String args[]) throws Exception {
+ b17689750TestVolatile();
+ b17689750TestMonitor();
+ }
+
+ static void b17689750TestVolatile() {
+ final B17689750TestVolatile test = new B17689750TestVolatile();
+ new Thread() {
+ public void run() {
+ test.thread1();
+ }
+ }.start();
+ try {
+ test.thread2();
+ } catch (NullPointerException expected) {
+ System.out.println("b17689750TestVolatile passed.");
+ }
+ }
+
+ static void b17689750TestMonitor() {
+ final B17689750TestMonitor test = new B17689750TestMonitor();
+ new Thread() {
+ public void run() {
+ test.thread1();
+ }
+ }.start();
+ try {
+ test.thread2();
+ } catch (NullPointerException expected) {
+ System.out.println("b17689750TestMonitor passed.");
+ }
+ }
+}
+
+class B17689750TestVolatile {
+ private volatile int state = 0;
+ private int[] values = { 42 };
+
+ void thread1() {
+ while (state != 1) { } // Busy loop.
+ values = null;
+ state = 2;
+ }
+
+ void thread2() {
+ int[] vs1 = values;
+ state = 1;
+ while (state != 2) { } // Busy loop.
+ int[] vs2 = values;
+ int v1 = vs1[0];
+ int v2 = vs2[0];
+ System.out.println("b17689750TestVolatile failed: " + v1 + ", " + v2);
+ }
+}
+
+class B17689750TestMonitor {
+ private int state = 0;
+ private Object lock = new Object();
+ private int[] values = { 42 };
+
+ void thread1() {
+ int s;
+ do {
+ synchronized (lock) {
+ s = state;
+ }
+ } while (s != 1); // Busy loop.
+
+ synchronized (lock) {
+ values = null;
+ state = 2;
+ }
+ }
+
+ void thread2() {
+ int[] vs1;
+ synchronized (lock) {
+ vs1 = values;
+ state = 1;
+ }
+
+ int s;
+ do {
+ synchronized (lock) {
+ s = state;
+ }
+ } while (s != 2); // Busy loop.
+
+ int[] vs2 = values;
+ int v1 = vs1[0];
+ int v2 = vs2[0];
+ System.out.println("b17689750TestMonitor failed: " + v1 + ", " + v2);
+ }
+}
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 302db38..ae5b08f 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -526,7 +526,7 @@
$(call define-test-art-run-test-group,test-art-$(target)-run-test-$(test),$(ART_RUN_TEST_$(call name-to-var,$(target))_$(call name-to-var,$(test))_RULES)))))
$(foreach target, $(TARGET_TYPES), \
$(foreach address_size, $(ADDRESS_SIZES_$(call name-to-var,$(target))), $(eval \
- $(call define-test-art-run-test-group,test-art-$(target)-run-test-$(address_size),$(ART_RUN_TEST_$(address_size)_RULES)))))
+ $(call define-test-art-run-test-group,test-art-$(target)-run-test$(address_size),$(ART_RUN_TEST_$(call name-to-var,$(target))_$(address_size)_RULES)))))
# Clear variables now we're finished with them.
$(foreach target, $(TARGET_TYPES), $(eval ART_RUN_TEST_$(call name-to-var,$(target))_RULES :=))
diff --git a/test/run-test b/test/run-test
index 4f1cbab..f9f45fc 100755
--- a/test/run-test
+++ b/test/run-test
@@ -93,6 +93,7 @@
elif [ "x$1" = "x--jvm" ]; then
target_mode="no"
runtime="jvm"
+ prebuild_mode="no"
NEED_DEX="false"
shift
elif [ "x$1" = "x-O" ]; then