Merge "Fix the x86 textrel and remove -Wl,--no-fatal-warnings."
diff --git a/Android.mk b/Android.mk
index 7d31382..14cd0f3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -364,9 +364,9 @@
# "m art-host" for just building the files needed to run the art script
.PHONY: art-host
ifeq ($(HOST_PREFER_32_BIT),true)
-art-host: $(HOST_OUT_EXECUTABLES)/art $(HOST_OUT)/bin/dalvikvm32 $(HOST_OUT)/lib/libart.so $(HOST_OUT)/bin/dex2oat $(HOST_CORE_IMG_OUT) $(HOST_OUT)/lib/libjavacore.so
+art-host: $(HOST_OUT_EXECUTABLES)/art $(HOST_OUT)/bin/dalvikvm32 $(HOST_OUT)/lib/libart.so $(HOST_OUT)/bin/dex2oat $(HOST_CORE_IMG_OUT) $(HOST_OUT)/lib/libjavacore.so $(HOST_OUT)/bin/dalvikvm
else
-art-host: $(HOST_OUT_EXECUTABLES)/art $(HOST_OUT)/bin/dalvikvm64 $(HOST_OUT)/bin/dalvikvm32 $(HOST_OUT)/lib/libart.so $(HOST_OUT)/bin/dex2oat $(HOST_CORE_IMG_OUT) $(HOST_OUT)/lib/libjavacore.so
+art-host: $(HOST_OUT_EXECUTABLES)/art $(HOST_OUT)/bin/dalvikvm64 $(HOST_OUT)/bin/dalvikvm32 $(HOST_OUT)/lib/libart.so $(HOST_OUT)/bin/dex2oat $(HOST_CORE_IMG_OUT) $(HOST_OUT)/lib/libjavacore.so $(HOST_OUT)/bin/dalvikvm
endif
.PHONY: art-host-debug
@@ -400,7 +400,7 @@
use-art-full:
adb root && sleep 3
adb shell stop
- adb shell rm -rf $(ART_DALVIK_CACHE_DIR)/*
+ adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
adb shell setprop dalvik.vm.dex2oat-flags ""
adb shell setprop dalvik.vm.image-dex2oat-flags ""
adb shell setprop persist.sys.dalvik.vm.lib.2 libart.so
@@ -410,7 +410,7 @@
use-artd-full:
adb root && sleep 3
adb shell stop
- adb shell rm -rf $(ART_DALVIK_CACHE_DIR)/*
+ adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
adb shell setprop dalvik.vm.dex2oat-flags ""
adb shell setprop dalvik.vm.image-dex2oat-flags ""
adb shell setprop persist.sys.dalvik.vm.lib.2 libartd.so
@@ -420,7 +420,7 @@
use-art-smart:
adb root && sleep 3
adb shell stop
- adb shell rm -rf $(ART_DALVIK_CACHE_DIR)/*
+ adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
adb shell setprop dalvik.vm.dex2oat-flags "--compiler-filter=interpret-only"
adb shell setprop dalvik.vm.image-dex2oat-flags ""
adb shell setprop persist.sys.dalvik.vm.lib.2 libart.so
@@ -430,7 +430,7 @@
use-art-interpret-only:
adb root && sleep 3
adb shell stop
- adb shell rm -rf $(ART_DALVIK_CACHE_DIR)/*
+ adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
adb shell setprop dalvik.vm.dex2oat-flags "--compiler-filter=interpret-only"
adb shell setprop dalvik.vm.image-dex2oat-flags "--compiler-filter=interpret-only"
adb shell setprop persist.sys.dalvik.vm.lib.2 libart.so
@@ -440,7 +440,7 @@
use-art-verify-none:
adb root && sleep 3
adb shell stop
- adb shell rm -rf $(ART_DALVIK_CACHE_DIR)/*
+ adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
adb shell setprop dalvik.vm.dex2oat-flags "--compiler-filter=verify-none"
adb shell setprop dalvik.vm.image-dex2oat-flags "--compiler-filter=verify-none"
adb shell setprop persist.sys.dalvik.vm.lib.2 libart.so
diff --git a/compiler/dex/quick/arm64/arm64_lir.h b/compiler/dex/quick/arm64/arm64_lir.h
index ac5f33b..b0865f1 100644
--- a/compiler/dex/quick/arm64/arm64_lir.h
+++ b/compiler/dex/quick/arm64/arm64_lir.h
@@ -136,23 +136,23 @@
A64_REGISTER_CODE_LIST(A64_DEFINE_REGISTERS)
#undef A64_DEFINE_REGISTERS
- rwzr = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 0x3f,
rxzr = RegStorage::k64BitSolo | RegStorage::kCoreRegister | 0x3f,
- rwsp = rw31,
+ rwzr = RegStorage::k32BitSolo | RegStorage::kCoreRegister | 0x3f,
rsp = rx31,
- rA64_SUSPEND = rx19,
- rA64_SELF = rx18,
- rA64_SP = rx31,
- rA64_LR = rx30,
+ rwsp = rw31,
+
+ // Aliases which are not defined in "ARM Architecture Reference, register names".
+ rxSUSPEND = rx19,
+ rxSELF = rx18,
+ rxLR = rx30,
/*
* FIXME: It's a bit awkward to define both 32 and 64-bit views of these - we'll only ever use
* the 64-bit view. However, for now we'll define a 32-bit view to keep these from being
* allocated as 32-bit temp registers.
*/
- rA32_SUSPEND = rw19,
- rA32_SELF = rw18,
- rA32_SP = rw31,
- rA32_LR = rw30
+ rwSUSPEND = rw19,
+ rwSELF = rw18,
+ rwLR = rw30,
};
#define A64_DEFINE_REGSTORAGES(nr) \
@@ -163,17 +163,18 @@
A64_REGISTER_CODE_LIST(A64_DEFINE_REGSTORAGES)
#undef A64_DEFINE_REGSTORAGES
-constexpr RegStorage rs_wzr(RegStorage::kValid | rwzr);
constexpr RegStorage rs_xzr(RegStorage::kValid | rxzr);
-constexpr RegStorage rs_rA64_SUSPEND(RegStorage::kValid | rA64_SUSPEND);
-constexpr RegStorage rs_rA64_SELF(RegStorage::kValid | rA64_SELF);
-constexpr RegStorage rs_rA64_SP(RegStorage::kValid | rA64_SP);
-constexpr RegStorage rs_rA64_LR(RegStorage::kValid | rA64_LR);
+constexpr RegStorage rs_wzr(RegStorage::kValid | rwzr);
+// Reserved registers.
+constexpr RegStorage rs_xSUSPEND(RegStorage::kValid | rxSUSPEND);
+constexpr RegStorage rs_xSELF(RegStorage::kValid | rxSELF);
+constexpr RegStorage rs_sp(RegStorage::kValid | rsp);
+constexpr RegStorage rs_xLR(RegStorage::kValid | rxLR);
// TODO: eliminate the need for these.
-constexpr RegStorage rs_rA32_SUSPEND(RegStorage::kValid | rA32_SUSPEND);
-constexpr RegStorage rs_rA32_SELF(RegStorage::kValid | rA32_SELF);
-constexpr RegStorage rs_rA32_SP(RegStorage::kValid | rA32_SP);
-constexpr RegStorage rs_rA32_LR(RegStorage::kValid | rA32_LR);
+constexpr RegStorage rs_wSUSPEND(RegStorage::kValid | rwSUSPEND);
+constexpr RegStorage rs_wSELF(RegStorage::kValid | rwSELF);
+constexpr RegStorage rs_wsp(RegStorage::kValid | rwsp);
+constexpr RegStorage rs_wLR(RegStorage::kValid | rwLR);
// RegisterLocation templates return values (following the hard-float calling convention).
const RegLocation arm_loc_c_return =
diff --git a/compiler/dex/quick/arm64/call_arm64.cc b/compiler/dex/quick/arm64/call_arm64.cc
index cb126f2..cfdf926 100644
--- a/compiler/dex/quick/arm64/call_arm64.cc
+++ b/compiler/dex/quick/arm64/call_arm64.cc
@@ -174,12 +174,12 @@
// Making a call - use explicit registers
FlushAllRegs(); /* Everything to home location */
LoadValueDirectFixed(rl_src, rs_x0);
- LoadWordDisp(rs_rA64_SELF, QUICK_ENTRYPOINT_OFFSET(8, pHandleFillArrayData).Int32Value(),
- rs_rA64_LR);
+ LoadWordDisp(rs_xSELF, QUICK_ENTRYPOINT_OFFSET(8, pHandleFillArrayData).Int32Value(),
+ rs_xLR);
// Materialize a pointer to the fill data image
NewLIR3(kA64Adr2xd, rx1, 0, WrapPointer(tab_rec));
ClobberCallerSave();
- LIR* call_inst = OpReg(kOpBlx, rs_rA64_LR);
+ LIR* call_inst = OpReg(kOpBlx, rs_xLR);
MarkSafepointPC(call_inst);
}
@@ -206,7 +206,7 @@
null_check_branch = OpCmpImmBranch(kCondEq, rs_x0, 0, NULL);
}
}
- Load32Disp(rs_rA64_SELF, Thread::ThinLockIdOffset<8>().Int32Value(), rs_w1);
+ Load32Disp(rs_xSELF, Thread::ThinLockIdOffset<8>().Int32Value(), rs_w1);
OpRegRegImm(kOpAdd, rs_x2, rs_x0, mirror::Object::MonitorOffset().Int32Value());
NewLIR2(kA64Ldxr2rX, rw3, rx2);
MarkPossibleNullPointerException(opt_flags);
@@ -221,9 +221,9 @@
}
// TODO: move to a slow path.
// Go expensive route - artLockObjectFromCode(obj);
- LoadWordDisp(rs_rA64_SELF, QUICK_ENTRYPOINT_OFFSET(8, pLockObject).Int32Value(), rs_rA64_LR);
+ LoadWordDisp(rs_xSELF, QUICK_ENTRYPOINT_OFFSET(8, pLockObject).Int32Value(), rs_xLR);
ClobberCallerSave();
- LIR* call_inst = OpReg(kOpBlx, rs_rA64_LR);
+ LIR* call_inst = OpReg(kOpBlx, rs_xLR);
MarkSafepointPC(call_inst);
LIR* success_target = NewLIR0(kPseudoTargetLabel);
@@ -254,7 +254,7 @@
null_check_branch = OpCmpImmBranch(kCondEq, rs_x0, 0, NULL);
}
}
- Load32Disp(rs_rA64_SELF, Thread::ThinLockIdOffset<8>().Int32Value(), rs_w1);
+ Load32Disp(rs_xSELF, Thread::ThinLockIdOffset<8>().Int32Value(), rs_w1);
Load32Disp(rs_x0, mirror::Object::MonitorOffset().Int32Value(), rs_w2);
MarkPossibleNullPointerException(opt_flags);
LIR* slow_unlock_branch = OpCmpBranch(kCondNe, rs_w1, rs_w2, NULL);
@@ -269,9 +269,9 @@
}
// TODO: move to a slow path.
// Go expensive route - artUnlockObjectFromCode(obj);
- LoadWordDisp(rs_rA64_SELF, QUICK_ENTRYPOINT_OFFSET(8, pUnlockObject).Int32Value(), rs_rA64_LR);
+ LoadWordDisp(rs_xSELF, QUICK_ENTRYPOINT_OFFSET(8, pUnlockObject).Int32Value(), rs_xLR);
ClobberCallerSave();
- LIR* call_inst = OpReg(kOpBlx, rs_rA64_LR);
+ LIR* call_inst = OpReg(kOpBlx, rs_xLR);
MarkSafepointPC(call_inst);
LIR* success_target = NewLIR0(kPseudoTargetLabel);
@@ -281,8 +281,8 @@
void Arm64Mir2Lir::GenMoveException(RegLocation rl_dest) {
int ex_offset = Thread::ExceptionOffset<8>().Int32Value();
RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true);
- LoadRefDisp(rs_rA64_SELF, ex_offset, rl_result.reg, kNotVolatile);
- StoreRefDisp(rs_rA64_SELF, ex_offset, rs_xzr, kNotVolatile);
+ LoadRefDisp(rs_xSELF, ex_offset, rl_result.reg, kNotVolatile);
+ StoreRefDisp(rs_xSELF, ex_offset, rs_xzr, kNotVolatile);
StoreValue(rl_dest, rl_result);
}
@@ -293,7 +293,7 @@
RegStorage reg_card_base = AllocTempWide();
RegStorage reg_card_no = AllocTemp();
LIR* branch_over = OpCmpImmBranch(kCondEq, val_reg, 0, NULL);
- LoadWordDisp(rs_rA64_SELF, Thread::CardTableOffset<8>().Int32Value(), reg_card_base);
+ LoadWordDisp(rs_xSELF, Thread::CardTableOffset<8>().Int32Value(), reg_card_base);
OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, gc::accounting::CardTable::kCardShift);
// TODO(Arm64): generate "strb wB, [xB, wC, uxtw]" rather than "strb wB, [xB, xC]"?
StoreBaseIndexed(reg_card_base, As64BitReg(reg_card_no), As32BitReg(reg_card_base),
@@ -341,33 +341,33 @@
if (cu_->compiler_driver->GetCompilerOptions().GetExplicitStackOverflowChecks()) {
if (!large_frame) {
// Load stack limit
- LoadWordDisp(rs_rA64_SELF, Thread::StackEndOffset<8>().Int32Value(), rs_x9);
+ LoadWordDisp(rs_xSELF, Thread::StackEndOffset<8>().Int32Value(), rs_x9);
}
} else {
// TODO(Arm64) Implement implicit checks.
// Implicit stack overflow check.
// Generate a load from [sp, #-framesize]. If this is in the stack
// redzone we will get a segmentation fault.
- // Load32Disp(rs_rA64_SP, -Thread::kStackOverflowReservedBytes, rs_wzr);
+ // Load32Disp(rs_wSP, -Thread::kStackOverflowReservedBytes, rs_wzr);
// MarkPossibleStackOverflowException();
LOG(FATAL) << "Implicit stack overflow checks not implemented.";
}
}
if (frame_size_ > 0) {
- OpRegImm64(kOpSub, rs_rA64_SP, spill_size);
+ OpRegImm64(kOpSub, rs_sp, spill_size);
}
/* Need to spill any FP regs? */
if (fp_spill_mask_) {
int spill_offset = spill_size - kArm64PointerSize*(num_fp_spills_ + num_core_spills_);
- SpillFPRegs(rs_rA64_SP, spill_offset, fp_spill_mask_);
+ SpillFPRegs(rs_sp, spill_offset, fp_spill_mask_);
}
/* Spill core callee saves. */
if (core_spill_mask_) {
int spill_offset = spill_size - kArm64PointerSize*num_core_spills_;
- SpillCoreRegs(rs_rA64_SP, spill_offset, core_spill_mask_);
+ SpillCoreRegs(rs_sp, spill_offset, core_spill_mask_);
}
if (!skip_overflow_check) {
@@ -383,11 +383,11 @@
m2l_->ResetDefTracking();
GenerateTargetLabel(kPseudoThrowTarget);
// Unwinds stack.
- m2l_->OpRegImm(kOpAdd, rs_rA64_SP, sp_displace_);
+ m2l_->OpRegImm(kOpAdd, rs_sp, sp_displace_);
m2l_->ClobberCallerSave();
ThreadOffset<8> func_offset = QUICK_ENTRYPOINT_OFFSET(8, pThrowStackOverflow);
m2l_->LockTemp(rs_x8);
- m2l_->LoadWordDisp(rs_rA64_SELF, func_offset.Int32Value(), rs_x8);
+ m2l_->LoadWordDisp(rs_xSELF, func_offset.Int32Value(), rs_x8);
m2l_->NewLIR1(kA64Br1x, rs_x8.GetReg());
m2l_->FreeTemp(rs_x8);
}
@@ -399,26 +399,26 @@
if (large_frame) {
// Compare Expected SP against bottom of stack.
// Branch to throw target if there is not enough room.
- OpRegRegImm(kOpSub, rs_x9, rs_rA64_SP, frame_size_without_spills);
- LoadWordDisp(rs_rA64_SELF, Thread::StackEndOffset<8>().Int32Value(), rs_x8);
+ OpRegRegImm(kOpSub, rs_x9, rs_sp, frame_size_without_spills);
+ LoadWordDisp(rs_xSELF, Thread::StackEndOffset<8>().Int32Value(), rs_x8);
LIR* branch = OpCmpBranch(kCondUlt, rs_x9, rs_x8, nullptr);
AddSlowPath(new(arena_)StackOverflowSlowPath(this, branch, spill_size));
- OpRegCopy(rs_rA64_SP, rs_x9); // Establish stack after checks.
+ OpRegCopy(rs_sp, rs_x9); // Establish stack after checks.
} else {
/*
* If the frame is small enough we are guaranteed to have enough space that remains to
* handle signals on the user stack.
* Establishes stack before checks.
*/
- OpRegRegImm(kOpSub, rs_rA64_SP, rs_rA64_SP, frame_size_without_spills);
- LIR* branch = OpCmpBranch(kCondUlt, rs_rA64_SP, rs_x9, nullptr);
+ OpRegRegImm(kOpSub, rs_sp, rs_sp, frame_size_without_spills);
+ LIR* branch = OpCmpBranch(kCondUlt, rs_sp, rs_x9, nullptr);
AddSlowPath(new(arena_)StackOverflowSlowPath(this, branch, frame_size_));
}
} else {
- OpRegImm(kOpSub, rs_rA64_SP, frame_size_without_spills);
+ OpRegImm(kOpSub, rs_sp, frame_size_without_spills);
}
} else {
- OpRegImm(kOpSub, rs_rA64_SP, frame_size_without_spills);
+ OpRegImm(kOpSub, rs_sp, frame_size_without_spills);
}
FlushIns(ArgLocs, rl_method);
@@ -448,14 +448,14 @@
/* Need to restore any FP callee saves? */
if (fp_spill_mask_) {
int spill_offset = frame_size_ - kArm64PointerSize*(num_fp_spills_ + num_core_spills_);
- UnSpillFPRegs(rs_rA64_SP, spill_offset, fp_spill_mask_);
+ UnSpillFPRegs(rs_sp, spill_offset, fp_spill_mask_);
}
if (core_spill_mask_) {
int spill_offset = frame_size_ - kArm64PointerSize*num_core_spills_;
- UnSpillCoreRegs(rs_rA64_SP, spill_offset, core_spill_mask_);
+ UnSpillCoreRegs(rs_sp, spill_offset, core_spill_mask_);
}
- OpRegImm64(kOpAdd, rs_rA64_SP, frame_size_);
+ OpRegImm64(kOpAdd, rs_sp, frame_size_);
NewLIR0(kA64Ret);
}
diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc
index ac32f6e..56fb2dd 100644
--- a/compiler/dex/quick/arm64/int_arm64.cc
+++ b/compiler/dex/quick/arm64/int_arm64.cc
@@ -599,9 +599,7 @@
// Test suspend flag, return target of taken suspend branch
LIR* Arm64Mir2Lir::OpTestSuspend(LIR* target) {
- // FIXME: Define rA64_SUSPEND as w19, when we do not need two copies of reserved register.
- // Note: The opcode is not set as wide, so actually we are using the 32-bit version register.
- NewLIR3(kA64Subs3rRd, rA64_SUSPEND, rA64_SUSPEND, 1);
+ NewLIR3(kA64Subs3rRd, rwSUSPEND, rwSUSPEND, 1);
return OpCondBranch((target == NULL) ? kCondEq : kCondNe, target);
}
diff --git a/compiler/dex/quick/arm64/target_arm64.cc b/compiler/dex/quick/arm64/target_arm64.cc
index 0ebcefb..6105837 100644
--- a/compiler/dex/quick/arm64/target_arm64.cc
+++ b/compiler/dex/quick/arm64/target_arm64.cc
@@ -48,9 +48,9 @@
rs_d16, rs_d17, rs_d18, rs_d19, rs_d20, rs_d21, rs_d22, rs_d23,
rs_d24, rs_d25, rs_d26, rs_d27, rs_d28, rs_d29, rs_d30, rs_d31};
static constexpr RegStorage reserved_regs_arr[] =
- {rs_rA32_SUSPEND, rs_rA32_SELF, rs_rA32_SP, rs_rA32_LR, rs_wzr};
+ {rs_wSUSPEND, rs_wSELF, rs_wsp, rs_wLR, rs_wzr};
static constexpr RegStorage reserved64_regs_arr[] =
- {rs_rA64_SUSPEND, rs_rA64_SELF, rs_rA64_SP, rs_rA64_LR, rs_xzr};
+ {rs_xSUSPEND, rs_xSELF, rs_sp, rs_xLR, rs_xzr};
// TUNING: Are there too many temp registers and too less promote target?
// This definition need to be matched with runtime.cc, quick entry assembly and JNI compiler
// Note: we are not able to call to C function directly if it un-match C ABI.
@@ -107,11 +107,11 @@
RegStorage Arm64Mir2Lir::TargetReg(SpecialTargetRegister reg) {
RegStorage res_reg = RegStorage::InvalidReg();
switch (reg) {
- case kSelf: res_reg = rs_rA64_SELF; break;
- case kSuspend: res_reg = rs_rA64_SUSPEND; break;
- case kLr: res_reg = rs_rA64_LR; break;
+ case kSelf: res_reg = rs_xSELF; break;
+ case kSuspend: res_reg = rs_xSUSPEND; break;
+ case kLr: res_reg = rs_xLR; break;
case kPc: res_reg = RegStorage::InvalidReg(); break;
- case kSp: res_reg = rs_rA64_SP; break;
+ case kSp: res_reg = rs_sp; break;
case kArg0: res_reg = rs_x0; break;
case kArg1: res_reg = rs_x1; break;
case kArg2: res_reg = rs_x2; break;
@@ -130,7 +130,7 @@
case kFArg7: res_reg = rs_f7; break;
case kRet0: res_reg = rs_x0; break;
case kRet1: res_reg = rs_x1; break;
- case kInvokeTgt: res_reg = rs_rA64_LR; break;
+ case kInvokeTgt: res_reg = rs_xLR; break;
case kHiddenArg: res_reg = rs_x12; break;
case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
case kCount: res_reg = RegStorage::InvalidReg(); break;
@@ -644,7 +644,7 @@
*/
void Arm64Mir2Lir::AdjustSpillMask() {
- core_spill_mask_ |= (1 << rs_rA64_LR.GetRegNum());
+ core_spill_mask_ |= (1 << rs_xLR.GetRegNum());
num_core_spills_++;
}
@@ -789,13 +789,13 @@
RegStorage Arm64Mir2Lir::LoadHelper(ThreadOffset<8> offset) {
// TODO(Arm64): use LoadWordDisp instead.
// e.g. LoadWordDisp(rs_rA64_SELF, offset.Int32Value(), rs_rA64_LR);
- LoadBaseDisp(rs_rA64_SELF, offset.Int32Value(), rs_rA64_LR, k64, kNotVolatile);
- return rs_rA64_LR;
+ LoadBaseDisp(rs_xSELF, offset.Int32Value(), rs_xLR, k64, kNotVolatile);
+ return rs_xLR;
}
LIR* Arm64Mir2Lir::CheckSuspendUsingLoad() {
RegStorage tmp = rs_x0;
- LoadWordDisp(rs_rA64_SELF, Thread::ThreadSuspendTriggerOffset<8>().Int32Value(), tmp);
+ LoadWordDisp(rs_xSELF, Thread::ThreadSuspendTriggerOffset<8>().Int32Value(), tmp);
LIR* load2 = LoadWordDisp(tmp, 0, tmp);
return load2;
}
diff --git a/compiler/dex/quick/arm64/utility_arm64.cc b/compiler/dex/quick/arm64/utility_arm64.cc
index c8d45c6..e248410 100644
--- a/compiler/dex/quick/arm64/utility_arm64.cc
+++ b/compiler/dex/quick/arm64/utility_arm64.cc
@@ -554,7 +554,7 @@
/* RegReg operations with SP in first parameter need extended register instruction form.
* Only CMN and CMP instructions are implemented.
*/
- if (r_dest_src1 == rs_rA64_SP) {
+ if (r_dest_src1 == rs_sp) {
return OpRegRegExtend(op, r_dest_src1, r_src2, ENCODE_NO_EXTEND);
} else {
return OpRegRegShift(op, r_dest_src1, r_src2, ENCODE_NO_SHIFT);
@@ -1110,7 +1110,7 @@
// TODO: in future may need to differentiate Dalvik accesses w/ spills
if (mem_ref_type_ == ResourceMask::kDalvikReg) {
- DCHECK(r_base == rs_rA64_SP);
+ DCHECK(r_base == rs_sp);
AnnotateDalvikRegAccess(load, displacement >> 2, true /* is_load */, r_dest.Is64Bit());
}
return load;
@@ -1203,7 +1203,7 @@
// TODO: In future, may need to differentiate Dalvik & spill accesses.
if (mem_ref_type_ == ResourceMask::kDalvikReg) {
- DCHECK(r_base == rs_rA64_SP);
+ DCHECK(r_base == rs_sp);
AnnotateDalvikRegAccess(store, displacement >> 2, false /* is_load */, r_src.Is64Bit());
}
return store;
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index fd20a81..481b00c 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -1006,8 +1006,9 @@
RegStorage new_index = index_;
// Move index out of kArg1, either directly to kArg0, or to kArg2.
- if (index_.GetReg() == m2l_->TargetReg(kArg1).GetReg()) {
- if (array_base_.GetReg() == m2l_->TargetReg(kArg0).GetReg()) {
+ // TODO: clean-up to check not a number but with type
+ if (index_.GetRegNum() == m2l_->TargetReg(kArg1).GetRegNum()) {
+ if (array_base_.GetRegNum() == m2l_->TargetReg(kArg0).GetRegNum()) {
m2l_->OpRegCopy(m2l_->TargetReg(kArg2), index_);
new_index = m2l_->TargetReg(kArg2);
} else {
diff --git a/compiler/elf_writer.cc b/compiler/elf_writer.cc
index 4c093c7..55ee18e 100644
--- a/compiler/elf_writer.cc
+++ b/compiler/elf_writer.cc
@@ -43,7 +43,7 @@
size_t& oat_data_offset) {
std::string error_msg;
std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, false, false, &error_msg));
- CHECK(elf_file.get() != NULL) << error_msg;
+ CHECK(elf_file.get() != nullptr) << error_msg;
oat_loaded_size = elf_file->GetLoadedSize();
CHECK_NE(0U, oat_loaded_size);
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 78757ec..e4dcaa7 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -20,6 +20,7 @@
#include "base/unix_file/fd_file.h"
#include "buffered_output_stream.h"
#include "driver/compiler_driver.h"
+#include "dwarf.h"
#include "elf_utils.h"
#include "file_output_stream.h"
#include "globals.h"
@@ -469,9 +470,9 @@
pieces.push_back(ElfFilePiece(".hash", hash_builder_.section_.sh_offset,
hash.data(), hash.size() * sizeof(Elf32_Word)));
pieces.push_back(ElfFilePiece(".rodata", rodata_builder_.section_.sh_offset,
- NULL, rodata_builder_.section_.sh_size));
+ nullptr, rodata_builder_.section_.sh_size));
pieces.push_back(ElfFilePiece(".text", text_builder_.section_.sh_offset,
- NULL, text_builder_.section_.sh_size));
+ nullptr, text_builder_.section_.sh_size));
if (IncludingDebugSymbols()) {
pieces.push_back(ElfFilePiece(".symtab", symtab_builder_.section_.sh_offset,
symtab.data(), symtab.size() * sizeof(Elf32_Sym)));
@@ -547,7 +548,7 @@
if (tag == DT_NULL) {
return;
}
- dynamics_.push_back({NULL, tag, d_un});
+ dynamics_.push_back({nullptr, tag, d_un});
}
void ElfWriterQuick::ElfDynamicBuilder::AddDynamicTag(Elf32_Sword tag, Elf32_Word d_un,
@@ -650,7 +651,7 @@
// Lets say the state is something like this.
// +--------+ +--------+ +-----------+
// | symtab | | bucket | | chain |
- // | NULL | | 1 | | STN_UNDEF |
+ // | nullptr | | 1 | | STN_UNDEF |
// | <sym1> | | 4 | | 2 |
// | <sym2> | | | | 5 |
// | <sym3> | | | | STN_UNDEF |
@@ -821,10 +822,10 @@
bool generateDebugInformation = compiler_driver_->GetCallFrameInformation() != nullptr;
if (generateDebugInformation) {
- ElfRawSectionBuilder debug_info(".debug_info", SHT_PROGBITS, 0, NULL, 0, 1, 0);
- ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, NULL, 0, 1, 0);
- ElfRawSectionBuilder debug_str(".debug_str", SHT_PROGBITS, 0, NULL, 0, 1, 0);
- ElfRawSectionBuilder debug_frame(".debug_frame", SHT_PROGBITS, 0, NULL, 0, 4, 0);
+ ElfRawSectionBuilder debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+ ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+ ElfRawSectionBuilder debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+ ElfRawSectionBuilder debug_frame(".debug_frame", SHT_PROGBITS, 0, nullptr, 0, 4, 0);
debug_frame.SetBuffer(*compiler_driver_->GetCallFrameInformation());
FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
@@ -866,31 +867,6 @@
buf->push_back((data >> 8) & 0xff);
}
-// DWARF constants needed to generate CFI information.
-enum {
- // Tag encodings.
- DW_TAG_compile_unit = 0x11,
- DW_TAG_subprogram = 0X2e,
-
- // Attribute encodings.
- DW_AT_name = 0x03,
- DW_AT_low_pc = 0x11,
- DW_AT_high_pc = 0x12,
- DW_AT_language = 0x13,
-
- // Constant encoding.
- DW_CHILDREN_no = 0x00,
- DW_CHILDREN_yes = 0x01,
-
- // Attribute form encodings.
- DW_FORM_addr = 0x01,
- DW_FORM_data1 = 0x0b,
- DW_FORM_strp = 0x0e,
-
- // Language encoding.
- DW_LANG_Java = 0x000b
-};
-
void ElfWriterQuick::FillInCFIInformation(OatWriter* oat_writer,
std::vector<uint8_t>* dbg_info,
std::vector<uint8_t>* dbg_abbrev,
diff --git a/dalvikvm/Android.mk b/dalvikvm/Android.mk
index 5d838c0..a06b5c5 100644
--- a/dalvikvm/Android.mk
+++ b/dalvikvm/Android.mk
@@ -16,6 +16,8 @@
LOCAL_PATH := $(call my-dir)
+include art/build/Android.common.mk
+
dalvikvm_cflags := -Wall -Werror -Wextra -std=gnu++11
include $(CLEAR_VARS)
@@ -27,6 +29,7 @@
LOCAL_C_INCLUDES := art/runtime
LOCAL_SHARED_LIBRARIES := libdl libnativehelper
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.common.mk
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := dalvikvm32
LOCAL_MODULE_STEM_64 := dalvikvm64
@@ -37,6 +40,10 @@
include $(BUILD_SYSTEM)/executable_prefer_symlink.mk
ART_TARGET_EXECUTABLES += $(TARGET_OUT_EXECUTABLES)/$(LOCAL_MODULE)
+ART_TARGET_EXECUTABLES += $(TARGET_OUT_EXECUTABLES)/$(LOCAL_MODULE)$(ART_PHONY_TEST_TARGET_SUFFIX)
+ifdef 2ND_ART_PHONY_TEST_TARGET_SUFFIX
+ ART_TARGET_EXECUTABLES += $(TARGET_OUT_EXECUTABLES)/$(LOCAL_MODULE)$(2ND_ART_PHONY_TEST_TARGET_SUFFIX)
+endif
include $(CLEAR_VARS)
LOCAL_MODULE := dalvikvm
@@ -48,7 +55,8 @@
LOCAL_C_INCLUDES := art/runtime
LOCAL_SHARED_LIBRARIES := libnativehelper
LOCAL_LDFLAGS := -ldl -lpthread
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
+LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.common.mk
LOCAL_IS_HOST_MODULE := true
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := dalvikvm32
@@ -56,7 +64,11 @@
include external/libcxx/libcxx.mk
include $(BUILD_HOST_EXECUTABLE)
-ART_HOST_EXECUTABLES += $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)32
-ifneq ($(HOST_PREFER_32_BIT),true)
- ART_HOST_EXECUTABLES += $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)64
-endif
\ No newline at end of file
+# Create symlink for the primary version target.
+include $(BUILD_SYSTEM)/executable_prefer_symlink.mk
+
+ART_HOST_EXECUTABLES += $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)
+ART_HOST_EXECUTABLES += $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)$(ART_PHONY_TEST_HOST_SUFFIX)
+ifdef 2ND_ART_PHONY_TEST_HOST_SUFFIX
+ ART_HOST_EXECUTABLES += $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)$(2ND_ART_PHONY_TEST_HOST_SUFFIX)
+endif
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index bf04a54..280f6d0 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -875,6 +875,8 @@
watch_dog_enabled = false;
} else if (option == "--gen-gdb-info") {
generate_gdb_information = true;
+ // Debug symbols are needed for gdb information.
+ include_debug_symbols = true;
} else if (option == "--no-gen-gdb-info") {
generate_gdb_information = false;
} else if (option.starts_with("-j")) {
diff --git a/runtime/dwarf.h b/runtime/dwarf.h
new file mode 100644
index 0000000..370ad95
--- /dev/null
+++ b/runtime/dwarf.h
@@ -0,0 +1,662 @@
+/*
+ * Copyright (C) 2014 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_DWARF_H_
+#define ART_RUNTIME_DWARF_H_
+
+namespace art {
+
+// Based on the Dwarf 4 specification at dwarfstd.com and issues marked
+// for inclusion in Dwarf 5 on same. Values not specified in the Dwarf 4
+// standard might change or be removed in the future and may be different
+// than the values used currently by other implementations for the same trait,
+// use at your own risk.
+
+enum Tag {
+ DW_TAG_array_type = 0x01,
+ DW_TAG_class_type = 0x02,
+ DW_TAG_entry_point = 0x03,
+ DW_TAG_enumeration_type = 0x04,
+ DW_TAG_formal_parameter = 0x05,
+ DW_TAG_imported_declaration = 0x08,
+ DW_TAG_label = 0x0a,
+ DW_TAG_lexical_block = 0x0b,
+ DW_TAG_member = 0x0d,
+ DW_TAG_pointer_type = 0x0f,
+ DW_TAG_reference_type = 0x10,
+ DW_TAG_compile_unit = 0x11,
+ DW_TAG_string_type = 0x12,
+ DW_TAG_structure_type = 0x13,
+ DW_TAG_subroutine_type = 0x15,
+ DW_TAG_typedef = 0x16,
+ DW_TAG_union_type = 0x17,
+ DW_TAG_unspecified_parameters = 0x18,
+ DW_TAG_variant = 0x19,
+ DW_TAG_common_block = 0x1a,
+ DW_TAG_common_inclusion = 0x1b,
+ DW_TAG_inheritance = 0x1c,
+ DW_TAG_inlined_subroutine = 0x1d,
+ DW_TAG_module = 0x1e,
+ DW_TAG_ptr_to_member_type = 0x1f,
+ DW_TAG_set_type = 0x20,
+ DW_TAG_subrange_type = 0x21,
+ DW_TAG_with_stmt = 0x22,
+ DW_TAG_access_declaration = 0x23,
+ DW_TAG_base_type = 0x24,
+ DW_TAG_catch_block = 0x25,
+ DW_TAG_const_type = 0x26,
+ DW_TAG_constant = 0x27,
+ DW_TAG_enumerator = 0x28,
+ DW_TAG_file_type = 0x29,
+ DW_TAG_friend = 0x2a,
+ DW_TAG_namelist = 0x2b,
+ DW_TAG_namelist_item = 0x2c,
+ DW_TAG_packed_type = 0x2d,
+ DW_TAG_subprogram = 0x2e,
+ DW_TAG_template_type_parameter = 0x2f,
+ DW_TAG_template_value_parameter = 0x30,
+ DW_TAG_thrown_type = 0x31,
+ DW_TAG_try_block = 0x32,
+ DW_TAG_variant_part = 0x33,
+ DW_TAG_variable = 0x34,
+ DW_TAG_volatile_type = 0x35,
+ DW_TAG_dwarf_procedure = 0x36,
+ DW_TAG_restrict_type = 0x37,
+ DW_TAG_interface_type = 0x38,
+ DW_TAG_namespace = 0x39,
+ DW_TAG_imported_module = 0x3a,
+ DW_TAG_unspecified_type = 0x3b,
+ DW_TAG_partial_unit = 0x3c,
+ DW_TAG_imported_unit = 0x3d,
+ DW_TAG_condition = 0x3f,
+ DW_TAG_shared_type = 0x40,
+ DW_TAG_type_unit = 0x41,
+ DW_TAG_rvalue_reference_type = 0x42,
+ DW_TAG_template_alias = 0x43,
+#ifdef INCLUDE_DWARF5_VALUES
+ // Values to be added in Dwarf 5. Final value not yet specified. Values listed
+ // may be different than other implementations. Use with caution.
+ // TODO Update these values when Dwarf 5 is released.
+ DW_TAG_coarray_type = 0x44,
+ DW_TAG_call_site = 0x45,
+ DW_TAG_call_site_parameter = 0x46,
+ DW_TAG_generic_subrange = 0x47,
+ DW_TAG_atomic_type = 0x48,
+ DW_TAG_dynamic_type = 0x49,
+ DW_TAG_aligned_type = 0x50,
+#endif
+ DW_TAG_lo_user = 0x4080,
+ DW_TAG_hi_user = 0xffff
+};
+
+enum Children : uint8_t {
+ DW_CHILDREN_no = 0x00,
+ DW_CHILDREN_yes = 0x01
+};
+
+enum Attribute {
+ DW_AT_sibling = 0x01,
+ DW_AT_location = 0x02,
+ DW_AT_name = 0x03,
+ DW_AT_ordering = 0x09,
+ DW_AT_byte_size = 0x0b,
+ DW_AT_bit_offset = 0x0c,
+ DW_AT_bit_size = 0x0d,
+ DW_AT_stmt_list = 0x10,
+ DW_AT_low_pc = 0x11,
+ DW_AT_high_pc = 0x12,
+ DW_AT_language = 0x13,
+ DW_AT_discr = 0x15,
+ DW_AT_discr_value = 0x16,
+ DW_AT_visibility = 0x17,
+ DW_AT_import = 0x18,
+ DW_AT_string_length = 0x19,
+ DW_AT_common_reference = 0x1a,
+ DW_AT_comp_dir = 0x1b,
+ DW_AT_const_value = 0x1c,
+ DW_AT_containing_type = 0x1d,
+ DW_AT_default_value = 0x1e,
+ DW_AT_inline = 0x20,
+ DW_AT_is_optional = 0x21,
+ DW_AT_lower_bound = 0x22,
+ DW_AT_producer = 0x25,
+ DW_AT_prototyped = 0x27,
+ DW_AT_return_addr = 0x2a,
+ DW_AT_start_scope = 0x2c,
+ DW_AT_bit_stride = 0x2e,
+ DW_AT_upper_bound = 0x2f,
+ DW_AT_abstract_origin = 0x31,
+ DW_AT_accessibility = 0x32,
+ DW_AT_address_class = 0x33,
+ DW_AT_artificial = 0x34,
+ DW_AT_base_types = 0x35,
+ DW_AT_calling_convention = 0x36,
+ DW_AT_count = 0x37,
+ DW_AT_data_member_location = 0x38,
+ DW_AT_decl_column = 0x39,
+ DW_AT_decl_file = 0x3a,
+ DW_AT_decl_line = 0x3b,
+ DW_AT_declaration = 0x3c,
+ DW_AT_discr_list = 0x3d,
+ DW_AT_encoding = 0x3e,
+ DW_AT_external = 0x3f,
+ DW_AT_frame_base = 0x40,
+ DW_AT_friend = 0x41,
+ DW_AT_identifier_case = 0x42,
+ DW_AT_macro_info = 0x43,
+ DW_AT_namelist_item = 0x44,
+ DW_AT_priority = 0x45,
+ DW_AT_segment = 0x46,
+ DW_AT_specification = 0x47,
+ DW_AT_static_link = 0x48,
+ DW_AT_type = 0x49,
+ DW_AT_use_location = 0x4a,
+ DW_AT_variable_parameter = 0x4b,
+ DW_AT_virtuality = 0x4c,
+ DW_AT_vtable_elem_location = 0x4d,
+ DW_AT_allocated = 0x4e,
+ DW_AT_associated = 0x4f,
+ DW_AT_data_location = 0x50,
+ DW_AT_byte_stride = 0x51,
+ DW_AT_entry_pc = 0x52,
+ DW_AT_use_UTF8 = 0x53,
+ DW_AT_extension = 0x54,
+ DW_AT_ranges = 0x55,
+ DW_AT_trampoline = 0x56,
+ DW_AT_call_column = 0x57,
+ DW_AT_call_file = 0x58,
+ DW_AT_call_line = 0x59,
+ DW_AT_description = 0x5a,
+ DW_AT_binary_scale = 0x5b,
+ DW_AT_decimal_scale = 0x5c,
+ DW_AT_small = 0x5d,
+ DW_AT_decimal_sign = 0x5e,
+ DW_AT_digit_count = 0x5f,
+ DW_AT_picture_string = 0x60,
+ DW_AT_mutable = 0x61,
+ DW_AT_threads_scaled = 0x62,
+ DW_AT_explicit = 0x63,
+ DW_AT_object_pointer = 0x64,
+ DW_AT_endianity = 0x65,
+ DW_AT_elemental = 0x66,
+ DW_AT_pure = 0x67,
+ DW_AT_recursive = 0x68,
+ DW_AT_signature = 0x69,
+ DW_AT_main_subprogram = 0x6a,
+ DW_AT_data_bit_offset = 0x6b,
+ DW_AT_const_expr = 0x6c,
+ DW_AT_enum_class = 0x6d,
+#ifdef INCLUDE_DWARF5_VALUES
+ // Values to be added in Dwarf 5. Final value not yet specified. Values listed
+ // may be different than other implementations. Use with caution.
+ // TODO Update these values when Dwarf 5 is released.
+ DW_AT_linkage_name = 0x6e,
+ DW_AT_call_site_value = 0x6f,
+ DW_AT_call_site_data_value = 0x70,
+ DW_AT_call_site_target = 0x71,
+ DW_AT_call_site_target_clobbered = 0x72,
+ DW_AT_tail_call = 0x73,
+ DW_AT_all_tail_call_sites = 0x74,
+ DW_AT_all_call_sites = 0x75,
+ DW_AT_all_source_call_sites = 0x76,
+ DW_AT_call_site_parameter = 0x77,
+ DW_AT_tail_call = 0x78,
+ DW_AT_all_tail_call_sites = 0x79,
+ DW_AT_all_call_sites = 0x7a,
+ DW_AT_all_source_call_sites = 0x7b,
+ DW_AT_rank = 0x7c,
+ DW_AT_string_bitsize = 0x7d,
+ DW_AT_string_byte_size = 0x7e,
+ DW_AT_reference = 0x7f,
+ DW_AT_rvalue_reference = 0x80,
+ DW_AT_noreturn = 0x81,
+ DW_AT_alignment = 0x82,
+#endif
+ DW_AT_lo_user = 0x2000,
+ DW_AT_hi_user = 0xffff
+};
+
+enum Form : uint8_t {
+ DW_FORM_addr = 0x01,
+ DW_FORM_block2 = 0x03,
+ DW_FORM_block4 = 0x04,
+ DW_FORM_data2 = 0x05,
+ DW_FORM_data4 = 0x06,
+ DW_FORM_data8 = 0x07,
+ DW_FORM_string = 0x08,
+ DW_FORM_block = 0x09,
+ DW_FORM_block1 = 0x0a,
+ DW_FORM_data1 = 0x0b,
+ DW_FORM_flag = 0x0c,
+ DW_FORM_sdata = 0x0d,
+ DW_FORM_strp = 0x0e,
+ DW_FORM_udata = 0x0f,
+ DW_FORM_ref_addr = 0x10,
+ DW_FORM_ref1 = 0x11,
+ DW_FORM_ref2 = 0x12,
+ DW_FORM_ref4 = 0x13,
+ DW_FORM_ref8 = 0x14,
+ DW_FORM_ref_udata = 0x15,
+ DW_FORM_indirect = 0x16,
+ DW_FORM_sec_offset = 0x17,
+ DW_FORM_exprloc = 0x18,
+ DW_FORM_flag_present = 0x19,
+ DW_FORM_ref_sig8 = 0x20
+};
+
+enum Operation : uint16_t {
+ DW_OP_addr = 0x03,
+ DW_OP_deref = 0x06,
+ DW_OP_const1u = 0x08,
+ DW_OP_const1s = 0x09,
+ DW_OP_const2u = 0x0a,
+ DW_OP_const2s = 0x0b,
+ DW_OP_const4u = 0x0c,
+ DW_OP_const4s = 0x0d,
+ DW_OP_const8u = 0x0e,
+ DW_OP_const8s = 0x0f,
+ DW_OP_constu = 0x10,
+ DW_OP_consts = 0x11,
+ DW_OP_dup = 0x12,
+ DW_OP_drop = 0x13,
+ DW_OP_over = 0x14,
+ DW_OP_pick = 0x15,
+ DW_OP_swap = 0x16,
+ DW_OP_rot = 0x17,
+ DW_OP_xderef = 0x18,
+ DW_OP_abs = 0x19,
+ DW_OP_and = 0x1a,
+ DW_OP_div = 0x1b,
+ DW_OP_minus = 0x1c,
+ DW_OP_mod = 0x1d,
+ DW_OP_mul = 0x1e,
+ DW_OP_neg = 0x1f,
+ DW_OP_not = 0x20,
+ DW_OP_or = 0x21,
+ DW_OP_plus = 0x22,
+ DW_OP_plus_uconst = 0x23,
+ DW_OP_shl = 0x24,
+ DW_OP_shr = 0x25,
+ DW_OP_shra = 0x26,
+ DW_OP_xor = 0x27,
+ DW_OP_skip = 0x2f,
+ DW_OP_bra = 0x28,
+ DW_OP_eq = 0x29,
+ DW_OP_ge = 0x2a,
+ DW_OP_gt = 0x2b,
+ DW_OP_le = 0x2c,
+ DW_OP_lt = 0x2d,
+ DW_OP_ne = 0x2e,
+ DW_OP_lit0 = 0x30,
+ DW_OP_lit1 = 0x31,
+ DW_OP_lit2 = 0x32,
+ DW_OP_lit3 = 0x33,
+ DW_OP_lit4 = 0x34,
+ DW_OP_lit5 = 0x35,
+ DW_OP_lit6 = 0x36,
+ DW_OP_lit7 = 0x37,
+ DW_OP_lit8 = 0x38,
+ DW_OP_lit9 = 0x39,
+ DW_OP_lit10 = 0x3a,
+ DW_OP_lit11 = 0x3b,
+ DW_OP_lit12 = 0x3c,
+ DW_OP_lit13 = 0x3d,
+ DW_OP_lit14 = 0x3e,
+ DW_OP_lit15 = 0x3f,
+ DW_OP_lit16 = 0x40,
+ DW_OP_lit17 = 0x41,
+ DW_OP_lit18 = 0x42,
+ DW_OP_lit19 = 0x43,
+ DW_OP_lit20 = 0x44,
+ DW_OP_lit21 = 0x45,
+ DW_OP_lit22 = 0x46,
+ DW_OP_lit23 = 0x47,
+ DW_OP_lit24 = 0x48,
+ DW_OP_lit25 = 0x49,
+ DW_OP_lit26 = 0x4a,
+ DW_OP_lit27 = 0x4b,
+ DW_OP_lit28 = 0x4c,
+ DW_OP_lit29 = 0x4d,
+ DW_OP_lit30 = 0x4e,
+ DW_OP_lit31 = 0x4f,
+ DW_OP_reg0 = 0x50,
+ DW_OP_reg1 = 0x51,
+ DW_OP_reg2 = 0x52,
+ DW_OP_reg3 = 0x53,
+ DW_OP_reg4 = 0x54,
+ DW_OP_reg5 = 0x55,
+ DW_OP_reg6 = 0x56,
+ DW_OP_reg7 = 0x57,
+ DW_OP_reg8 = 0x58,
+ DW_OP_reg9 = 0x59,
+ DW_OP_reg10 = 0x5a,
+ DW_OP_reg11 = 0x5b,
+ DW_OP_reg12 = 0x5c,
+ DW_OP_reg13 = 0x5d,
+ DW_OP_reg14 = 0x5e,
+ DW_OP_reg15 = 0x5f,
+ DW_OP_reg16 = 0x60,
+ DW_OP_reg17 = 0x61,
+ DW_OP_reg18 = 0x62,
+ DW_OP_reg19 = 0x63,
+ DW_OP_reg20 = 0x64,
+ DW_OP_reg21 = 0x65,
+ DW_OP_reg22 = 0x66,
+ DW_OP_reg23 = 0x67,
+ DW_OP_reg24 = 0x68,
+ DW_OP_reg25 = 0x69,
+ DW_OP_reg26 = 0x6a,
+ DW_OP_reg27 = 0x6b,
+ DW_OP_reg28 = 0x6c,
+ DW_OP_reg29 = 0x6d,
+ DW_OP_reg30 = 0x6e,
+ DW_OP_reg31 = 0x6f,
+ DW_OP_breg0 = 0x50,
+ DW_OP_breg1 = 0x51,
+ DW_OP_breg2 = 0x52,
+ DW_OP_breg3 = 0x53,
+ DW_OP_breg4 = 0x54,
+ DW_OP_breg5 = 0x55,
+ DW_OP_breg6 = 0x56,
+ DW_OP_breg7 = 0x57,
+ DW_OP_breg8 = 0x58,
+ DW_OP_breg9 = 0x59,
+ DW_OP_breg10 = 0x5a,
+ DW_OP_breg11 = 0x5b,
+ DW_OP_breg12 = 0x5c,
+ DW_OP_breg13 = 0x5d,
+ DW_OP_breg14 = 0x5e,
+ DW_OP_breg15 = 0x5f,
+ DW_OP_breg16 = 0x60,
+ DW_OP_breg17 = 0x61,
+ DW_OP_breg18 = 0x62,
+ DW_OP_breg19 = 0x63,
+ DW_OP_breg20 = 0x64,
+ DW_OP_breg21 = 0x65,
+ DW_OP_breg22 = 0x66,
+ DW_OP_breg23 = 0x67,
+ DW_OP_breg24 = 0x68,
+ DW_OP_breg25 = 0x69,
+ DW_OP_breg26 = 0x6a,
+ DW_OP_breg27 = 0x6b,
+ DW_OP_breg28 = 0x6c,
+ DW_OP_breg29 = 0x6d,
+ DW_OP_breg30 = 0x6e,
+ DW_OP_breg31 = 0x6f,
+ DW_OP_regx = 0x90,
+ DW_OP_fbreg = 0x91,
+ DW_OP_bregx = 0x92,
+ DW_OP_piece = 0x93,
+ DW_OP_deref_size = 0x94,
+ DW_OP_xderef_size = 0x95,
+ DW_OP_nop = 0x96,
+ DW_OP_push_object_address = 0x97,
+ DW_OP_call2 = 0x98,
+ DW_OP_call4 = 0x99,
+ DW_OP_call_ref = 0x9a,
+ DW_OP_form_tls_address = 0x9b,
+ DW_OP_call_frame_cfa = 0x9c,
+ DW_OP_bit_piece = 0x9d,
+ DW_OP_implicit_value = 0x9e,
+ DW_OP_stack_value = 0x9f,
+#ifdef INCLUDE_DWARF5_VALUES
+ // Values to be added in Dwarf 5. Final value not yet specified. Values listed
+ // may be different than other implementations. Use with caution.
+ // TODO Update these values when Dwarf 5 is released.
+ DW_OP_entry_value = 0xa0,
+ DW_OP_const_type = 0xa1,
+ DW_OP_regval_type = 0xa2,
+ DW_OP_deref_type = 0xa3,
+ DW_OP_xderef_type = 0xa4,
+ DW_OP_convert = 0xa5,
+ DW_OP_reinterpret = 0xa6,
+#endif
+ DW_OP_lo_user = 0xe0,
+ DW_OP_hi_user = 0xff
+};
+
+enum BaseTypeEncoding : uint8_t {
+ DW_ATE_address = 0x01,
+ DW_ATE_boolean = 0x02,
+ DW_ATE_complex_float = 0x03,
+ DW_ATE_float = 0x04,
+ DW_ATE_signed = 0x05,
+ DW_ATE_signed_char = 0x06,
+ DW_ATE_unsigned = 0x07,
+ DW_ATE_unsigned_char = 0x08,
+ DW_ATE_imaginary_float = 0x09,
+ DW_ATE_packed_decimal = 0x0a,
+ DW_ATE_numeric_string = 0x0b,
+ DW_ATE_edited = 0x0c,
+ DW_ATE_signed_fixed = 0x0d,
+ DW_ATE_unsigned_fixed = 0x0e,
+ DW_ATE_decimal_float = 0x0f,
+ DW_ATE_UTF = 0x10,
+ DW_ATE_lo_user = 0x80,
+ DW_ATE_hi_user = 0xff
+};
+
+enum DecimalSign : uint8_t {
+ DW_DS_unsigned = 0x01,
+ DW_DS_leading_overpunch = 0x02,
+ DW_DS_trailing_overpunch = 0x03,
+ DW_DS_leading_separate = 0x04,
+ DW_DS_trailing_separate = 0x05
+};
+
+enum Endianity : uint8_t {
+ DW_END_default = 0x00,
+ DW_END_big = 0x01,
+ DW_END_little = 0x02,
+ DW_END_lo_user = 0x40,
+ DW_END_hi_user = 0xff
+};
+
+enum Accessibility : uint8_t {
+ DW_ACCESS_public = 0x01,
+ DW_ACCESS_protected = 0x02,
+ DW_ACCESS_private = 0x03
+};
+
+enum Visibility : uint8_t {
+ DW_VIS_local = 0x01,
+ DW_VIS_exported = 0x02,
+ DW_VIS_qualified = 0x03
+};
+
+enum Virtuality : uint8_t {
+ DW_VIRTUALITY_none = 0x00,
+ DW_VIRTUALITY_virtual = 0x01,
+ DW_VIRTUALITY_pure_virtual = 0x02
+};
+
+enum Language {
+ DW_LANG_C89 = 0x01,
+ DW_LANG_C = 0x02,
+ DW_LANG_Ada83 = 0x03,
+ DW_LANG_C_plus_plus = 0x04,
+ DW_LANG_Cobol74 = 0x05,
+ DW_LANG_Cobol85 = 0x06,
+ DW_LANG_Fortran77 = 0x07,
+ DW_LANG_Fortran90 = 0x08,
+ DW_LANG_Pascal83 = 0x09,
+ DW_LANG_Modula2 = 0x0a,
+ DW_LANG_Java = 0x0b,
+ DW_LANG_C99 = 0x0c,
+ DW_LANG_Ada95 = 0x0d,
+ DW_LANG_Fortran95 = 0x0e,
+ DW_LANG_PLI = 0x0f,
+ DW_LANG_ObjC = 0x10,
+ DW_LANG_ObjC_plus_plus = 0x11,
+ DW_LANG_UPC = 0x12,
+ DW_LANG_D = 0x13,
+ DW_LANG_Python = 0x14,
+#ifdef INCLUDE_DWARF5_VALUES
+ // Values to be added in Dwarf 5. Final value not yet specified. Values listed
+ // may be different than other implementations. Use with caution.
+ // TODO Update these values when Dwarf 5 is released.
+ DW_LANG_OpenCL = 0x15,
+ DW_LANG_Go = 0x16,
+ DW_LANG_Modula3 = 0x17,
+ DW_LANG_Haskell = 0x18,
+ DW_LANG_C_plus_plus_03 = 0x19,
+ DW_LANG_C_plus_plus_11 = 0x1a,
+ DW_LANG_OCaml = 0x1b,
+ DW_LANG_Rust = 0x1c,
+ DW_LANG_C11 = 0x1d,
+ DW_LANG_Swift = 0x1e,
+ DW_LANG_Julia = 0x1f,
+#endif
+ DW_LANG_lo_user = 0x8000,
+ DW_LANG_hi_user = 0xffff
+};
+
+enum Identifier : uint8_t {
+ DW_ID_case_sensitive = 0x00,
+ DW_ID_up_case = 0x01,
+ DW_ID_down_case = 0x02,
+ DW_ID_case_insensitive = 0x03
+};
+
+enum CallingConvention : uint8_t {
+ DW_CC_normal = 0x01,
+ DW_CC_program = 0x02,
+ DW_CC_nocall = 0x03,
+ DW_CC_lo_user = 0x40,
+ DW_CC_hi_user = 0xff
+};
+
+enum Inline : uint8_t {
+ DW_INL_not_inlined = 0x00,
+ DW_INL_inlined = 0x01,
+ DW_INL_declared_not_inlined = 0x02,
+ DW_INL_declared_inlined = 0x03
+};
+
+enum ArrayOrdering : uint8_t {
+ DW_ORD_row_major = 0x00,
+ DW_ORD_col_major = 0x01
+};
+
+enum DiscriminantList : uint8_t {
+ DW_DSC_label = 0x00,
+ DW_DSC_range = 0x01
+};
+
+enum LineNumberOpcode : uint8_t {
+ DW_LNS_copy = 0x01,
+ DW_LNS_advance_pc = 0x02,
+ DW_LNS_advance_line = 0x03,
+ DW_LNS_set_file = 0x04,
+ DW_LNS_set_column = 0x05,
+ DW_LNS_negate_stmt = 0x06,
+ DW_LNS_set_basic_block = 0x07,
+ DW_LNS_const_add_pc = 0x08,
+ DW_LNS_fixed_advance_pc = 0x09,
+ DW_LNS_set_prologue_end = 0x0a,
+ DW_LNS_set_epilogue_begin = 0x0b,
+ DW_LNS_set_isa = 0x0c
+};
+
+enum LineNumberExtendedOpcode : uint8_t {
+ DW_LNE_end_sequence = 0x01,
+ DW_LNE_set_address = 0x02,
+ DW_LNE_define_file = 0x03,
+ DW_LNE_set_discriminator = 0x04,
+ DW_LNE_lo_user = 0x80,
+ DW_LNE_hi_user = 0xff
+};
+
+#ifdef INCLUDE_DWARF5_VALUES
+enum LineNumberFormat : uint8_t {
+ // Values to be added in Dwarf 5. Final value not yet specified. Values listed
+ // may be different than other implementations. Use with caution.
+ // TODO Update these values when Dwarf 5 is released.
+ //
+ DW_LNF_path = 0x1,
+ DW_LNF_include_index = 0x2,
+ DW_LNF_timestamp = 0x3,
+ DW_LNF_size = 0x4,
+ DW_LNF_MD5 = 0x5,
+ DW_LNF_lo_user = 0x2000,
+ DW_LNF_hi_user = 0x3fff
+};
+#endif
+
+enum MacroInfo : uint8_t {
+ DW_MACINFO_define = 0x01,
+ DW_MACINFO_undef = 0x02,
+ DW_MACINFO_start_file = 0x03,
+ DW_MACINFO_end_file = 0x04,
+ DW_MACINFO_vendor_ext = 0xff
+};
+
+#ifdef INCLUDE_DWARF5_VALUES
+enum Macro : uint8_t {
+ // Values to be added in Dwarf 5. Final value not yet specified. Values listed
+ // may be different than other implementations. Use with caution.
+ // TODO Update these values when Dwarf 5 is released.
+ DW_MACRO_define = 0x01,
+ DW_MACRO_undef = 0x02,
+ DW_MACRO_start_file = 0x03,
+ DW_MACRO_end_file = 0x04,
+ DW_MACRO_define_indirect = 0x05,
+ DW_MACRO_undef_indirect = 0x06,
+ DW_MACRO_transparent_include = 0x07,
+ DW_MACRO_define_indirectx = 0x0b,
+ DW_MACRO_undef_indirectx = 0x0c,
+ DW_MACRO_lo_user = 0xe0,
+ DW_MACRO_hi_user = 0xff
+};
+#endif
+
+const uint32_t CIE_ID_32 = 0xffffffff;
+const uint64_t CIE_ID_64 = 0xffffffffffffffff;
+
+enum CallFrameInstruction : uint8_t {
+ DW_CFA_advance_loc = 0x40,
+ DW_CFA_offset = 0x80,
+ DW_CFA_restore = 0xc0,
+ DW_CFA_nop = 0x00,
+ DW_CFA_set_loc = 0x01,
+ DW_CFA_advance_loc1 = 0x02,
+ DW_CFA_advance_loc2 = 0x03,
+ DW_CFA_advance_loc4 = 0x04,
+ DW_CFA_offset_extended = 0x05,
+ DW_CFA_restore_extended = 0x06,
+ DW_CFA_undefined = 0x07,
+ DW_CFA_same_value = 0x08,
+ DW_CFA_register = 0x09,
+ DW_CFA_remember_state = 0x0a,
+ DW_CFA_restore_state = 0x0b,
+ DW_CFA_def_cfa = 0x0c,
+ DW_CFA_def_cfa_register = 0x0d,
+ DW_CFA_def_cfa_offset = 0x0e,
+ DW_CFA_def_cfa_expression = 0x0f,
+ DW_CFA_expression = 0x10,
+ DW_CFA_offset_extended_sf = 0x11,
+ DW_CFA_def_cfa_sf = 0x12,
+ DW_CFA_def_cfa_offset_sf = 0x13,
+ DW_CFA_val_offset = 0x14,
+ DW_CFA_val_offset_sf = 0x15,
+ DW_CFA_val_expression = 0x16,
+ DW_CFA_lo_user = 0x1c,
+ DW_CFA_hi_user = 0x3f
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_DWARF_H_
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 0df8211..bb33978 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -22,6 +22,8 @@
#include "base/logging.h"
#include "base/stringprintf.h"
#include "base/stl_util.h"
+#include "dwarf.h"
+#include "leb128.h"
#include "utils.h"
#include "instruction_set.h"
@@ -108,43 +110,51 @@
: file_(file),
writable_(writable),
program_header_only_(program_header_only),
- header_(NULL),
- base_address_(NULL),
- program_headers_start_(NULL),
- section_headers_start_(NULL),
- dynamic_program_header_(NULL),
- dynamic_section_start_(NULL),
- symtab_section_start_(NULL),
- dynsym_section_start_(NULL),
- strtab_section_start_(NULL),
- dynstr_section_start_(NULL),
- hash_section_start_(NULL),
- symtab_symbol_table_(NULL),
- dynsym_symbol_table_(NULL),
- jit_elf_image_(NULL),
- jit_gdb_entry_(NULL) {
- CHECK(file != NULL);
+ header_(nullptr),
+ base_address_(nullptr),
+ program_headers_start_(nullptr),
+ section_headers_start_(nullptr),
+ dynamic_program_header_(nullptr),
+ dynamic_section_start_(nullptr),
+ symtab_section_start_(nullptr),
+ dynsym_section_start_(nullptr),
+ strtab_section_start_(nullptr),
+ dynstr_section_start_(nullptr),
+ hash_section_start_(nullptr),
+ symtab_symbol_table_(nullptr),
+ dynsym_symbol_table_(nullptr),
+ jit_elf_image_(nullptr),
+ jit_gdb_entry_(nullptr) {
+ 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));
- if (!elf_file->Setup(error_msg)) {
- return nullptr;
- }
- return elf_file.release();
-}
-
-bool ElfFile::Setup(std::string* error_msg) {
int prot;
int flags;
- if (writable_) {
+ if (writable) {
prot = PROT_READ | PROT_WRITE;
flags = MAP_SHARED;
} else {
prot = PROT_READ;
flags = MAP_PRIVATE;
}
+ if (!elf_file->Setup(prot, flags, error_msg)) {
+ return nullptr;
+ }
+ 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));
+ 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) {
int64_t temp_file_length = file_->GetLength();
if (temp_file_length < 0) {
errno = -temp_file_length;
@@ -201,7 +211,7 @@
// Find .dynamic section info from program header
dynamic_program_header_ = FindProgamHeaderByType(PT_DYNAMIC);
- if (dynamic_program_header_ == NULL) {
+ if (dynamic_program_header_ == nullptr) {
*error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
file_->GetPath().c_str());
return false;
@@ -263,14 +273,14 @@
}
bool ElfFile::SetMap(MemMap* map, std::string* error_msg) {
- if (map == NULL) {
+ if (map == nullptr) {
// MemMap::Open should have already set an error.
DCHECK(!error_msg->empty());
return false;
}
map_.reset(map);
- CHECK(map_.get() != NULL) << file_->GetPath();
- CHECK(map_->Begin() != NULL) << file_->GetPath();
+ CHECK(map_.get() != nullptr) << file_->GetPath();
+ CHECK(map_->Begin() != nullptr) << file_->GetPath();
header_ = reinterpret_cast<Elf32_Ehdr*>(map_->Begin());
if ((ELFMAG0 != header_->e_ident[EI_MAG0])
@@ -397,27 +407,27 @@
Elf32_Ehdr& ElfFile::GetHeader() const {
- CHECK(header_ != NULL);
+ CHECK(header_ != nullptr);
return *header_;
}
byte* ElfFile::GetProgramHeadersStart() const {
- CHECK(program_headers_start_ != NULL);
+ CHECK(program_headers_start_ != nullptr);
return program_headers_start_;
}
byte* ElfFile::GetSectionHeadersStart() const {
- CHECK(section_headers_start_ != NULL);
+ CHECK(section_headers_start_ != nullptr);
return section_headers_start_;
}
Elf32_Phdr& ElfFile::GetDynamicProgramHeader() const {
- CHECK(dynamic_program_header_ != NULL);
+ CHECK(dynamic_program_header_ != nullptr);
return *dynamic_program_header_;
}
Elf32_Dyn* ElfFile::GetDynamicSectionStart() const {
- CHECK(dynamic_section_start_ != NULL);
+ CHECK(dynamic_section_start_ != nullptr);
return dynamic_section_start_;
}
@@ -435,10 +445,10 @@
}
default: {
LOG(FATAL) << section_type;
- symbol_section_start = NULL;
+ symbol_section_start = nullptr;
}
}
- CHECK(symbol_section_start != NULL);
+ CHECK(symbol_section_start != nullptr);
return symbol_section_start;
}
@@ -456,17 +466,17 @@
}
default: {
LOG(FATAL) << section_type;
- string_section_start = NULL;
+ string_section_start = nullptr;
}
}
- CHECK(string_section_start != NULL);
+ CHECK(string_section_start != nullptr);
return string_section_start;
}
const char* ElfFile::GetString(Elf32_Word section_type, Elf32_Word i) const {
CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
if (i == 0) {
- return NULL;
+ return nullptr;
}
const char* string_section_start = GetStringSectionStart(section_type);
const char* string = string_section_start + i;
@@ -474,7 +484,7 @@
}
Elf32_Word* ElfFile::GetHashSectionStart() const {
- CHECK(hash_section_start_ != NULL);
+ CHECK(hash_section_start_ != nullptr);
return hash_section_start_;
}
@@ -516,7 +526,7 @@
return &program_header;
}
}
- return NULL;
+ return nullptr;
}
Elf32_Word ElfFile::GetSectionHeaderNum() const {
@@ -543,7 +553,7 @@
return §ion_header;
}
}
- return NULL;
+ return nullptr;
}
// from bionic
@@ -565,6 +575,15 @@
}
const byte* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const {
+ const Elf32_Sym* sym = FindDynamicSymbol(symbol_name);
+ if (sym != nullptr) {
+ return base_address_ + sym->st_value;
+ } else {
+ return nullptr;
+ }
+}
+
+const Elf32_Sym* ElfFile::FindDynamicSymbol(const std::string& symbol_name) const {
Elf32_Word hash = elfhash(symbol_name.c_str());
Elf32_Word bucket_index = hash % GetHashBucketNum();
Elf32_Word symbol_and_chain_index = GetHashBucket(bucket_index);
@@ -572,11 +591,11 @@
Elf32_Sym& symbol = GetSymbol(SHT_DYNSYM, symbol_and_chain_index);
const char* name = GetString(SHT_DYNSYM, symbol.st_name);
if (symbol_name == name) {
- return base_address_ + symbol.st_value;
+ return &symbol;
}
symbol_and_chain_index = GetHashChain(symbol_and_chain_index);
}
- return NULL;
+ return nullptr;
}
bool ElfFile::IsSymbolSectionType(Elf32_Word section_type) {
@@ -606,7 +625,7 @@
}
default: {
LOG(FATAL) << section_type;
- return NULL;
+ return nullptr;
}
}
}
@@ -618,12 +637,12 @@
CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
SymbolTable** symbol_table = GetSymbolTable(section_type);
- if (*symbol_table != NULL || build_map) {
- if (*symbol_table == NULL) {
+ if (*symbol_table != nullptr || build_map) {
+ if (*symbol_table == nullptr) {
DCHECK(build_map);
*symbol_table = new SymbolTable;
Elf32_Shdr* symbol_section = FindSectionByType(section_type);
- CHECK(symbol_section != NULL) << file_->GetPath();
+ CHECK(symbol_section != nullptr) << file_->GetPath();
Elf32_Shdr& string_section = GetSectionHeader(symbol_section->sh_link);
for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Elf32_Sym& symbol = GetSymbol(section_type, i);
@@ -632,7 +651,7 @@
continue;
}
const char* name = GetString(string_section, symbol.st_name);
- if (name == NULL) {
+ if (name == nullptr) {
continue;
}
std::pair<SymbolTable::iterator, bool> result =
@@ -647,36 +666,36 @@
}
}
}
- CHECK(*symbol_table != NULL);
+ CHECK(*symbol_table != nullptr);
SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name);
if (it == (*symbol_table)->end()) {
- return NULL;
+ return nullptr;
}
return it->second;
}
// Fall back to linear search
Elf32_Shdr* symbol_section = FindSectionByType(section_type);
- CHECK(symbol_section != NULL) << file_->GetPath();
+ CHECK(symbol_section != nullptr) << file_->GetPath();
Elf32_Shdr& string_section = GetSectionHeader(symbol_section->sh_link);
for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Elf32_Sym& symbol = GetSymbol(section_type, i);
const char* name = GetString(string_section, symbol.st_name);
- if (name == NULL) {
+ if (name == nullptr) {
continue;
}
if (symbol_name == name) {
return &symbol;
}
}
- return NULL;
+ 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);
- if (symbol == NULL) {
+ if (symbol == nullptr) {
return 0;
}
return symbol->st_value;
@@ -688,7 +707,7 @@
CHECK_EQ(static_cast<Elf32_Word>(SHT_STRTAB), string_section.sh_type) << file_->GetPath();
CHECK_LT(i, string_section.sh_size) << file_->GetPath();
if (i == 0) {
- return NULL;
+ return nullptr;
}
byte* strings = Begin() + string_section.sh_offset;
byte* string = strings + i;
@@ -846,7 +865,7 @@
std::string reservation_name("ElfFile reservation for ");
reservation_name += file_->GetPath();
std::unique_ptr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
- NULL, GetLoadedSize(), PROT_NONE, false,
+ nullptr, GetLoadedSize(), PROT_NONE, false,
error_msg));
if (reserve.get() == nullptr) {
*error_msg = StringPrintf("Failed to allocate %s: %s",
@@ -970,29 +989,323 @@
return false;
}
-static bool check_section_name(ElfFile& file, int section_num, const char *name) {
- Elf32_Shdr& section_header = file.GetSectionHeader(section_num);
- const char *section_name = file.GetString(SHT_SYMTAB, section_header.sh_name);
- return strcmp(name, section_name) == 0;
+
+Elf32_Shdr* ElfFile::FindSectionByName(const std::string& name) const {
+ CHECK(!program_header_only_);
+ Elf32_Shdr& shstrtab_sec = GetSectionNameStringSection();
+ for (uint32_t i = 0; i < GetSectionHeaderNum(); i++) {
+ Elf32_Shdr& shdr = GetSectionHeader(i);
+ const char* sec_name = GetString(shstrtab_sec, shdr.sh_name);
+ if (sec_name == nullptr) {
+ continue;
+ }
+ if (name == sec_name) {
+ return &shdr;
+ }
+ }
+ return nullptr;
}
-static void IncrementUint32(byte *p, uint32_t increment) {
- uint32_t *u = reinterpret_cast<uint32_t *>(p);
- *u += increment;
+struct PACKED(1) FDE {
+ uint32_t raw_length_;
+ uint32_t GetLength() {
+ return raw_length_ + sizeof(raw_length_);
+ }
+ uint32_t CIE_pointer;
+ uint32_t initial_location;
+ uint32_t address_range;
+ uint8_t instructions[0];
+};
+
+static FDE* NextFDE(FDE* frame) {
+ byte* fde_bytes = reinterpret_cast<byte*>(frame);
+ fde_bytes += frame->GetLength();
+ return reinterpret_cast<FDE*>(fde_bytes);
}
-static void RoundAndClear(byte *image, uint32_t& offset, int pwr2) {
- uint32_t mask = pwr2 - 1;
- while (offset & mask) {
- image[offset++] = 0;
+static bool IsFDE(FDE* frame) {
+ // TODO This seems to be the constant everyone uses (for the .debug_frame
+ // section at least), however we should investigate this further.
+ const uint32_t kDwarfCIE_id = 0xffffffff;
+ const uint32_t kReservedLengths[] = {0xffffffff, 0xfffffff0};
+ return frame->CIE_pointer != kDwarfCIE_id &&
+ frame->raw_length_ != kReservedLengths[0] && frame->raw_length_ != kReservedLengths[1];
+}
+
+// TODO This only works for 32-bit Elf Files.
+static bool FixupDebugFrame(uintptr_t text_start, byte* dbg_frame, size_t dbg_frame_size) {
+ FDE* last_frame = reinterpret_cast<FDE*>(dbg_frame + dbg_frame_size);
+ FDE* frame = NextFDE(reinterpret_cast<FDE*>(dbg_frame));
+ for (; frame < last_frame; frame = NextFDE(frame)) {
+ if (!IsFDE(frame)) {
+ return false;
+ }
+ frame->initial_location += text_start;
+ }
+ return true;
+}
+
+struct PACKED(1) DebugInfoHeader {
+ uint32_t unit_length; // TODO 32-bit specific size
+ uint16_t version;
+ uint32_t debug_abbrev_offset; // TODO 32-bit specific size
+ uint8_t address_size;
+};
+
+// Returns -1 if it is variable length, which we will just disallow for now.
+static int32_t FormLength(uint32_t att) {
+ switch (att) {
+ case DW_FORM_data1:
+ case DW_FORM_flag:
+ case DW_FORM_flag_present:
+ case DW_FORM_ref1:
+ return 1;
+
+ case DW_FORM_data2:
+ case DW_FORM_ref2:
+ return 2;
+
+ case DW_FORM_addr: // TODO 32-bit only
+ case DW_FORM_ref_addr: // TODO 32-bit only
+ case DW_FORM_sec_offset: // TODO 32-bit only
+ case DW_FORM_strp: // TODO 32-bit only
+ case DW_FORM_data4:
+ case DW_FORM_ref4:
+ return 4;
+
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
+ return 8;
+
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ case DW_FORM_exprloc:
+ case DW_FORM_indirect:
+ case DW_FORM_ref_udata:
+ case DW_FORM_sdata:
+ case DW_FORM_string:
+ case DW_FORM_udata:
+ default:
+ return -1;
}
}
-// Simple macro to bump a point to a section header to the next one.
-#define BUMP_SHENT(sp) \
- sp = reinterpret_cast<Elf32_Shdr *> (\
- reinterpret_cast<byte*>(sp) + elf_hdr.e_shentsize);\
- offset += elf_hdr.e_shentsize
+class DebugTag {
+ public:
+ const uint32_t index_;
+ ~DebugTag() {}
+ // Creates a new tag and moves data pointer up to the start of the next one.
+ // nullptr means error.
+ static DebugTag* Create(const byte** data_pointer) {
+ const byte* data = *data_pointer;
+ uint32_t index = DecodeUnsignedLeb128(&data);
+ std::unique_ptr<DebugTag> tag(new DebugTag(index));
+ tag->size_ = static_cast<uint32_t>(
+ reinterpret_cast<uintptr_t>(data) - reinterpret_cast<uintptr_t>(*data_pointer));
+ // skip the abbrev
+ tag->tag_ = DecodeUnsignedLeb128(&data);
+ tag->has_child_ = (*data == 0);
+ data++;
+ while (true) {
+ uint32_t attr = DecodeUnsignedLeb128(&data);
+ uint32_t form = DecodeUnsignedLeb128(&data);
+ if (attr == 0 && form == 0) {
+ break;
+ } else if (attr == 0 || form == 0) {
+ // Bad abbrev.
+ return nullptr;
+ }
+ int32_t size = FormLength(form);
+ if (size == -1) {
+ return nullptr;
+ }
+ tag->AddAttribute(attr, static_cast<uint32_t>(size));
+ }
+ *data_pointer = data;
+ return tag.release();
+ }
+
+ uint32_t GetSize() const {
+ return size_;
+ }
+
+ bool HasChild() {
+ return has_child_;
+ }
+
+ uint32_t GetTagNumber() {
+ return tag_;
+ }
+
+ // Gets the offset of a particular attribute in this tag structure.
+ // Interpretation of the data is left to the consumer. 0 is returned if the
+ // tag does not contain the attribute.
+ uint32_t GetOffsetOf(uint32_t dwarf_attribute) const {
+ auto it = off_map_.find(dwarf_attribute);
+ if (it == off_map_.end()) {
+ return 0;
+ } else {
+ return it->second;
+ }
+ }
+
+ // Gets the size of attribute
+ uint32_t GetAttrSize(uint32_t dwarf_attribute) const {
+ auto it = size_map_.find(dwarf_attribute);
+ if (it == size_map_.end()) {
+ return 0;
+ } else {
+ return it->second;
+ }
+ }
+
+ private:
+ explicit DebugTag(uint32_t index) : index_(index) {}
+ void AddAttribute(uint32_t type, uint32_t attr_size) {
+ off_map_.insert(std::pair<uint32_t, uint32_t>(type, size_));
+ size_map_.insert(std::pair<uint32_t, uint32_t>(type, attr_size));
+ size_ += attr_size;
+ }
+ std::map<uint32_t, uint32_t> off_map_;
+ std::map<uint32_t, uint32_t> size_map_;
+ uint32_t size_;
+ uint32_t tag_;
+ bool has_child_;
+};
+
+class DebugAbbrev {
+ public:
+ ~DebugAbbrev() {}
+ static DebugAbbrev* Create(const byte* dbg_abbrev, size_t dbg_abbrev_size) {
+ std::unique_ptr<DebugAbbrev> abbrev(new DebugAbbrev);
+ const byte* last = dbg_abbrev + dbg_abbrev_size;
+ while (dbg_abbrev < last) {
+ std::unique_ptr<DebugTag> tag(DebugTag::Create(&dbg_abbrev));
+ if (tag.get() == nullptr) {
+ return nullptr;
+ } else {
+ abbrev->tags_.insert(std::pair<uint32_t, uint32_t>(tag->index_, abbrev->tag_list_.size()));
+ abbrev->tag_list_.push_back(std::move(tag));
+ }
+ }
+ return abbrev.release();
+ }
+
+ DebugTag* ReadTag(const byte* entry) {
+ uint32_t tag_num = DecodeUnsignedLeb128(&entry);
+ auto it = tags_.find(tag_num);
+ if (it == tags_.end()) {
+ return nullptr;
+ } else {
+ CHECK_GT(tag_list_.size(), it->second);
+ return tag_list_.at(it->second).get();
+ }
+ }
+
+ private:
+ DebugAbbrev() {}
+ std::map<uint32_t, uint32_t> tags_;
+ std::vector<std::unique_ptr<DebugTag>> tag_list_;
+};
+
+class DebugInfoIterator {
+ public:
+ static DebugInfoIterator* Create(DebugInfoHeader* header, size_t frame_size,
+ DebugAbbrev* abbrev) {
+ std::unique_ptr<DebugInfoIterator> iter(new DebugInfoIterator(header, frame_size, abbrev));
+ if (iter->GetCurrentTag() == nullptr) {
+ return nullptr;
+ } else {
+ return iter.release();
+ }
+ }
+ ~DebugInfoIterator() {}
+
+ // Moves to the next DIE. Returns false if at last entry.
+ // TODO Handle variable length attributes.
+ bool next() {
+ if (current_entry_ == nullptr || current_tag_ == nullptr) {
+ return false;
+ }
+ current_entry_ += current_tag_->GetSize();
+ if (current_entry_ >= last_entry_) {
+ current_entry_ = nullptr;
+ return false;
+ }
+ current_tag_ = abbrev_->ReadTag(current_entry_);
+ if (current_tag_ == nullptr) {
+ current_entry_ = nullptr;
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ const DebugTag* GetCurrentTag() {
+ return const_cast<DebugTag*>(current_tag_);
+ }
+ byte* GetPointerToField(uint8_t dwarf_field) {
+ if (current_tag_ == nullptr || current_entry_ == nullptr || current_entry_ >= last_entry_) {
+ return nullptr;
+ }
+ uint32_t off = current_tag_->GetOffsetOf(dwarf_field);
+ if (off == 0) {
+ // tag does not have that field.
+ return nullptr;
+ } else {
+ DCHECK_LT(off, current_tag_->GetSize());
+ return current_entry_ + off;
+ }
+ }
+
+ private:
+ DebugInfoIterator(DebugInfoHeader* header, size_t frame_size, DebugAbbrev* abbrev)
+ : abbrev_(abbrev),
+ last_entry_(reinterpret_cast<byte*>(header) + frame_size),
+ current_entry_(reinterpret_cast<byte*>(header) + sizeof(DebugInfoHeader)),
+ current_tag_(abbrev_->ReadTag(current_entry_)) {}
+ DebugAbbrev* abbrev_;
+ byte* last_entry_;
+ byte* current_entry_;
+ DebugTag* current_tag_;
+};
+
+static bool FixupDebugInfo(uint32_t text_start, DebugInfoIterator* iter) {
+ do {
+ if (iter->GetCurrentTag()->GetAttrSize(DW_AT_low_pc) != sizeof(int32_t) ||
+ iter->GetCurrentTag()->GetAttrSize(DW_AT_high_pc) != sizeof(int32_t)) {
+ return false;
+ }
+ uint32_t* PC_low = reinterpret_cast<uint32_t*>(iter->GetPointerToField(DW_AT_low_pc));
+ uint32_t* PC_high = reinterpret_cast<uint32_t*>(iter->GetPointerToField(DW_AT_high_pc));
+ if (PC_low != nullptr && PC_high != nullptr) {
+ *PC_low += text_start;
+ *PC_high += text_start;
+ }
+ } while (iter->next());
+ return true;
+}
+
+static bool FixupDebugSections(const byte* dbg_abbrev, size_t dbg_abbrev_size,
+ uintptr_t text_start,
+ byte* dbg_info, size_t dbg_info_size,
+ byte* dbg_frame, size_t dbg_frame_size) {
+ std::unique_ptr<DebugAbbrev> abbrev(DebugAbbrev::Create(dbg_abbrev, dbg_abbrev_size));
+ if (abbrev.get() == nullptr) {
+ return false;
+ }
+ std::unique_ptr<DebugInfoIterator> iter(
+ DebugInfoIterator::Create(reinterpret_cast<DebugInfoHeader*>(dbg_info),
+ dbg_info_size, abbrev.get()));
+ if (iter.get() == nullptr) {
+ return false;
+ }
+ return FixupDebugInfo(text_start, iter.get())
+ && FixupDebugFrame(text_start, dbg_frame, dbg_frame_size);
+}
void ElfFile::GdbJITSupport() {
// We only get here if we only are mapping the program header.
@@ -1000,18 +1313,25 @@
// Well, we need the whole file to do this.
std::string error_msg;
- std::unique_ptr<ElfFile> ptr(Open(const_cast<File*>(file_), false, false, &error_msg));
- ElfFile& all = *ptr;
-
- // Do we have interesting sections?
- // Is this an OAT file with interesting sections?
- if (all.GetSectionHeaderNum() != kExpectedSectionsInOATFile) {
+ // 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));
+ if (all_ptr.get() == nullptr) {
return;
}
- if (!check_section_name(all, 8, ".debug_info") ||
- !check_section_name(all, 9, ".debug_abbrev") ||
- !check_section_name(all, 10, ".debug_frame") ||
- !check_section_name(all, 11, ".debug_str")) {
+ ElfFile& all = *all_ptr;
+
+ // Do we have interesting sections?
+ const Elf32_Shdr* debug_info = all.FindSectionByName(".debug_info");
+ const Elf32_Shdr* debug_abbrev = all.FindSectionByName(".debug_abbrev");
+ const Elf32_Shdr* debug_frame = all.FindSectionByName(".debug_frame");
+ const Elf32_Shdr* debug_str = all.FindSectionByName(".debug_str");
+ const Elf32_Shdr* strtab_sec = all.FindSectionByName(".strtab");
+ const Elf32_Shdr* symtab_sec = all.FindSectionByName(".symtab");
+ Elf32_Shdr* text_sec = all.FindSectionByName(".text");
+ if (debug_info == nullptr || debug_abbrev == nullptr || debug_frame == nullptr ||
+ debug_str == nullptr || text_sec == nullptr || strtab_sec == nullptr || symtab_sec == nullptr) {
return;
}
#ifdef __LP64__
@@ -1019,227 +1339,29 @@
return; // No ELF debug support in 64bit.
}
#endif
- // This is not needed if we have no .text segment.
- uint32_t text_start_addr = 0;
- for (uint32_t i = 0; i < segments_.size(); i++) {
- if (segments_[i]->GetProtect() & PROT_EXEC) {
- // We found the .text section.
- text_start_addr = PointerToLowMemUInt32(segments_[i]->Begin());
- break;
- }
- }
- if (text_start_addr == 0U) {
- return;
- }
-
- // Okay, we are good enough. Fake up an ELF image and tell GDB about it.
- // We need some extra space for the debug and string sections, the ELF header, and the
- // section header.
- uint32_t needed_size = KB;
-
- for (Elf32_Word i = 1; i < all.GetSectionHeaderNum(); i++) {
- Elf32_Shdr& section_header = all.GetSectionHeader(i);
- if (section_header.sh_addr == 0 && section_header.sh_type != SHT_DYNSYM) {
- // Debug section: we need it.
- needed_size += section_header.sh_size;
- } else if (section_header.sh_type == SHT_STRTAB &&
- strcmp(".shstrtab",
- all.GetString(SHT_SYMTAB, section_header.sh_name)) == 0) {
- // We also need the shared string table.
- needed_size += section_header.sh_size;
-
- // We also need the extra strings .symtab\0.strtab\0
- needed_size += 16;
- }
- }
-
- // Start creating our image.
- jit_elf_image_ = new byte[needed_size];
-
- // Create the Elf Header by copying the old one
- Elf32_Ehdr& elf_hdr =
- *reinterpret_cast<Elf32_Ehdr*>(jit_elf_image_);
-
- elf_hdr = all.GetHeader();
+ // 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_hdr.e_entry = 0;
elf_hdr.e_phoff = 0;
elf_hdr.e_phnum = 0;
elf_hdr.e_phentsize = 0;
elf_hdr.e_type = ET_EXEC;
- uint32_t offset = sizeof(Elf32_Ehdr);
+ text_sec->sh_type = SHT_NOBITS;
+ text_sec->sh_offset = 0;
- // Copy the debug sections and string table.
- uint32_t debug_offsets[kExpectedSectionsInOATFile];
- memset(debug_offsets, '\0', sizeof debug_offsets);
- Elf32_Shdr *text_header = nullptr;
- int extra_shstrtab_entries = -1;
- int text_section_index = -1;
- int section_index = 1;
- for (Elf32_Word i = 1; i < kExpectedSectionsInOATFile; i++) {
- Elf32_Shdr& section_header = all.GetSectionHeader(i);
- // Round up to multiple of 4, ensuring zero fill.
- RoundAndClear(jit_elf_image_, offset, 4);
- if (section_header.sh_addr == 0 && section_header.sh_type != SHT_DYNSYM) {
- // Debug section: we need it. Unfortunately, it wasn't mapped in.
- debug_offsets[i] = offset;
- // Read it from the file.
- lseek(file_->Fd(), section_header.sh_offset, SEEK_SET);
- read(file_->Fd(), jit_elf_image_ + offset, section_header.sh_size);
- offset += section_header.sh_size;
- section_index++;
- offset += 16;
- } else if (section_header.sh_type == SHT_STRTAB &&
- strcmp(".shstrtab",
- all.GetString(SHT_SYMTAB, section_header.sh_name)) == 0) {
- // We also need the shared string table.
- debug_offsets[i] = offset;
- // Read it from the file.
- lseek(file_->Fd(), section_header.sh_offset, SEEK_SET);
- read(file_->Fd(), jit_elf_image_ + offset, section_header.sh_size);
- offset += section_header.sh_size;
- // We also need the extra strings .symtab\0.strtab\0
- extra_shstrtab_entries = section_header.sh_size;
- memcpy(jit_elf_image_+offset, ".symtab\0.strtab\0", 16);
- offset += 16;
- section_index++;
- } else if (section_header.sh_flags & SHF_EXECINSTR) {
- DCHECK(strcmp(".text", all.GetString(SHT_SYMTAB,
- section_header.sh_name)) == 0);
- text_header = §ion_header;
- text_section_index = section_index++;
- }
- }
- DCHECK(text_header != nullptr);
- DCHECK_NE(extra_shstrtab_entries, -1);
-
- // We now need to update the addresses for debug_info and debug_frame to get to the
- // correct offset within the .text section.
- byte *p = jit_elf_image_+debug_offsets[8];
- byte *end = p + all.GetSectionHeader(8).sh_size;
-
- // For debug_info; patch compilation using low_pc @ offset 13, high_pc at offset 17.
- IncrementUint32(p + 13, text_start_addr);
- IncrementUint32(p + 17, text_start_addr);
-
- // Now fix the low_pc, high_pc for each method address.
- // First method starts at offset 0x15, each subsequent method is 1+3*4 bytes further.
- for (p += 0x15; p < end; p += 1 /* attr# */ + 3 * sizeof(uint32_t) /* addresses */) {
- IncrementUint32(p + 1 + sizeof(uint32_t), text_start_addr);
- IncrementUint32(p + 1 + 2 * sizeof(uint32_t), text_start_addr);
+ if (!FixupDebugSections(
+ all.Begin() + debug_abbrev->sh_offset, debug_abbrev->sh_size, text_sec->sh_addr,
+ all.Begin() + debug_info->sh_offset, debug_info->sh_size,
+ all.Begin() + debug_frame->sh_offset, debug_frame->sh_size)) {
+ LOG(ERROR) << "Failed to load GDB data";
+ return;
}
- // Now we have to handle the debug_frame method start addresses
- p = jit_elf_image_+debug_offsets[10];
- end = p + all.GetSectionHeader(10).sh_size;
-
- // Skip past the CIE.
- p += *reinterpret_cast<uint32_t *>(p) + 4;
-
- // And walk the FDEs.
- for (; p < end; p += *reinterpret_cast<uint32_t *>(p) + sizeof(uint32_t)) {
- IncrementUint32(p + 2 * sizeof(uint32_t), text_start_addr);
- }
-
- // Create the data for the symbol table.
- const int kSymbtabAlignment = 16;
- RoundAndClear(jit_elf_image_, offset, kSymbtabAlignment);
- uint32_t symtab_offset = offset;
-
- // First entry is empty.
- memset(jit_elf_image_+offset, 0, sizeof(Elf32_Sym));
- offset += sizeof(Elf32_Sym);
-
- // Symbol 1 is the real .text section.
- Elf32_Sym& sym_ent = *reinterpret_cast<Elf32_Sym*>(jit_elf_image_+offset);
- sym_ent.st_name = 1; /* .text */
- sym_ent.st_value = text_start_addr;
- sym_ent.st_size = text_header->sh_size;
- SetBindingAndType(&sym_ent, STB_LOCAL, STT_SECTION);
- sym_ent.st_other = 0;
- sym_ent.st_shndx = text_section_index;
- offset += sizeof(Elf32_Sym);
-
- // Create the data for the string table.
- RoundAndClear(jit_elf_image_, offset, kSymbtabAlignment);
- const int kTextStringSize = 7;
- uint32_t strtab_offset = offset;
- memcpy(jit_elf_image_+offset, "\0.text", kTextStringSize);
- offset += kTextStringSize;
-
- // Create the section header table.
- // Round up to multiple of kSymbtabAlignment, ensuring zero fill.
- RoundAndClear(jit_elf_image_, offset, kSymbtabAlignment);
- elf_hdr.e_shoff = offset;
- Elf32_Shdr *sp =
- reinterpret_cast<Elf32_Shdr *>(jit_elf_image_ + offset);
-
- // Copy the first empty index.
- *sp = all.GetSectionHeader(0);
- BUMP_SHENT(sp);
-
- elf_hdr.e_shnum = 1;
- for (Elf32_Word i = 1; i < kExpectedSectionsInOATFile; i++) {
- Elf32_Shdr& section_header = all.GetSectionHeader(i);
- if (section_header.sh_addr == 0 && section_header.sh_type != SHT_DYNSYM) {
- // Debug section: we need it.
- *sp = section_header;
- sp->sh_offset = debug_offsets[i];
- sp->sh_addr = 0;
- elf_hdr.e_shnum++;
- BUMP_SHENT(sp);
- } else if (section_header.sh_type == SHT_STRTAB &&
- strcmp(".shstrtab",
- all.GetString(SHT_SYMTAB, section_header.sh_name)) == 0) {
- // We also need the shared string table.
- *sp = section_header;
- sp->sh_offset = debug_offsets[i];
- sp->sh_size += 16; /* sizeof ".symtab\0.strtab\0" */
- sp->sh_addr = 0;
- elf_hdr.e_shstrndx = elf_hdr.e_shnum;
- elf_hdr.e_shnum++;
- BUMP_SHENT(sp);
- }
- }
-
- // Add a .text section for the matching code section.
- *sp = *text_header;
- sp->sh_type = SHT_NOBITS;
- sp->sh_offset = 0;
- sp->sh_addr = text_start_addr;
- elf_hdr.e_shnum++;
- BUMP_SHENT(sp);
-
- // .symtab section: Need an empty index and the .text entry
- sp->sh_name = extra_shstrtab_entries;
- sp->sh_type = SHT_SYMTAB;
- sp->sh_flags = 0;
- sp->sh_addr = 0;
- sp->sh_offset = symtab_offset;
- sp->sh_size = 2 * sizeof(Elf32_Sym);
- sp->sh_link = elf_hdr.e_shnum + 1; // Link to .strtab section.
- sp->sh_info = 0;
- sp->sh_addralign = 16;
- sp->sh_entsize = sizeof(Elf32_Sym);
- elf_hdr.e_shnum++;
- BUMP_SHENT(sp);
-
- // .strtab section: Enough for .text\0.
- sp->sh_name = extra_shstrtab_entries + 8;
- sp->sh_type = SHT_STRTAB;
- sp->sh_flags = 0;
- sp->sh_addr = 0;
- sp->sh_offset = strtab_offset;
- sp->sh_size = kTextStringSize;
- sp->sh_link = 0;
- sp->sh_info = 0;
- sp->sh_addralign = 16;
- sp->sh_entsize = 0;
- elf_hdr.e_shnum++;
- BUMP_SHENT(sp);
-
- // We now have enough information to tell GDB about our file.
- jit_gdb_entry_ = CreateCodeEntry(jit_elf_image_, offset);
+ jit_gdb_entry_ = CreateCodeEntry(all.Begin(), all.Size());
+ gdb_file_mapping_.reset(all_ptr.release());
}
} // namespace art
diff --git a/runtime/elf_file.h b/runtime/elf_file.h
index 6650acd..496690b 100644
--- a/runtime/elf_file.h
+++ b/runtime/elf_file.h
@@ -41,6 +41,9 @@
class ElfFile {
public:
static ElfFile* Open(File* file, bool writable, bool program_header_only, std::string* error_msg);
+ // Open with specific mmap flags, Always maps in the whole file, not just the
+ // program header sections.
+ static ElfFile* Open(File* file, int mmap_prot, int mmap_flags, std::string* error_msg);
~ElfFile();
// Load segments into memory based on PT_LOAD program headers
@@ -70,17 +73,19 @@
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;
+ const Elf32_Sym* FindDynamicSymbol(const std::string& symbol_name) const;
static bool IsSymbolSectionType(Elf32_Word section_type);
Elf32_Word GetSymbolNum(Elf32_Shdr&) const;
Elf32_Sym& GetSymbol(Elf32_Word section_type, Elf32_Word i) const;
- // Find symbol in specified table, returning NULL if it is not found.
+ // 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)
@@ -98,11 +103,11 @@
const std::string& symbol_name,
bool build_map);
- // Lookup a string given string section and offset. Returns NULL for
+ // Lookup a string given string section and offset. Returns nullptr for
// special 0 offset.
const char* GetString(Elf32_Shdr&, Elf32_Word) const;
- // Lookup a string by section type. Returns NULL for special 0 offset.
+ // Lookup a string by section type. Returns nullptr for special 0 offset.
const char* GetString(Elf32_Word section_type, Elf32_Word) const;
Elf32_Word GetDynamicNum() const;
@@ -125,7 +130,7 @@
private:
ElfFile(File* file, bool writable, bool program_header_only);
- bool Setup(std::string* error_msg);
+ bool Setup(int prot, int flags, std::string* error_msg);
bool SetMap(MemMap* map, std::string* error_msg);
@@ -181,9 +186,8 @@
// Support for GDB JIT
byte* jit_elf_image_;
JITCodeEntry* jit_gdb_entry_;
+ std::unique_ptr<ElfFile> gdb_file_mapping_;
void GdbJITSupport();
- // Is this an OAT file with debug information in it?
- static constexpr uint32_t kExpectedSectionsInOATFile = 12;
};
} // namespace art
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 65799cd..43bdf49 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -168,8 +168,7 @@
template<typename T>
inline PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
- DCHECK(array_class_ != NULL);
- Array* raw_array = Array::Alloc<true>(self, array_class_, length, sizeof(T),
+ Array* raw_array = Array::Alloc<true>(self, GetArrayClass(), length, sizeof(T),
Runtime::Current()->GetHeap()->GetCurrentAllocator());
return down_cast<PrimitiveArray<T>*>(raw_array);
}
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 64e2317..25a4535 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -20,6 +20,7 @@
#include "gc/allocator_type.h"
#include "object.h"
#include "object_callbacks.h"
+#include "read_barrier.h"
namespace art {
@@ -160,9 +161,10 @@
array_class_ = array_class;
}
- static Class* GetArrayClass() {
+ static Class* GetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(array_class_ != nullptr);
- return array_class_;
+ return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(
+ &array_class_);
}
static void ResetArrayClass() {
diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h
index 4858613..502cec7 100644
--- a/runtime/mirror/art_field.h
+++ b/runtime/mirror/art_field.h
@@ -23,6 +23,7 @@
#include "modifiers.h"
#include "object.h"
#include "object_callbacks.h"
+#include "read_barrier.h"
namespace art {
@@ -121,9 +122,11 @@
template<bool kTransactionActive>
void SetObj(Object* object, Object* new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static Class* GetJavaLangReflectArtField() {
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+ static Class* GetJavaLangReflectArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(java_lang_reflect_ArtField_ != nullptr);
- return java_lang_reflect_ArtField_;
+ return ReadBarrier::BarrierForRoot<mirror::Class, kReadBarrierOption>(
+ &java_lang_reflect_ArtField_);
}
static void SetClass(Class* java_lang_reflect_ArtField);
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 1c21b81..a55c48b 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -24,6 +24,7 @@
#include "object.h"
#include "object_callbacks.h"
#include "quick/quick_method_frame_info.h"
+#include "read_barrier.h"
namespace art {
@@ -409,9 +410,11 @@
static void SetClass(Class* java_lang_reflect_ArtMethod);
- static Class* GetJavaLangReflectArtMethod() {
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+ static Class* GetJavaLangReflectArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(java_lang_reflect_ArtMethod_ != nullptr);
- return java_lang_reflect_ArtMethod_;
+ return ReadBarrier::BarrierForRoot<mirror::Class, kReadBarrierOption>(
+ &java_lang_reflect_ArtMethod_);
}
static void ResetClass();
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 6205f70..451235c 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -511,12 +511,14 @@
VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
}
+template<ReadBarrierOption kReadBarrierOption>
inline bool Class::IsArtFieldClass() const {
- return this == ArtField::GetJavaLangReflectArtField();
+ return this == ArtField::GetJavaLangReflectArtField<kReadBarrierOption>();
}
+template<ReadBarrierOption kReadBarrierOption>
inline bool Class::IsArtMethodClass() const {
- return this == ArtMethod::GetJavaLangReflectArtMethod();
+ return this == ArtMethod::GetJavaLangReflectArtMethod<kReadBarrierOption>();
}
template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index c798180..c6472c6 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -40,7 +40,9 @@
Class* Class::java_lang_Class_ = nullptr;
void Class::SetClassClass(Class* java_lang_Class) {
- CHECK(java_lang_Class_ == nullptr) << java_lang_Class_ << " " << java_lang_Class;
+ CHECK(java_lang_Class_ == nullptr)
+ << ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(&java_lang_Class_)
+ << " " << java_lang_Class;
CHECK(java_lang_Class != nullptr);
java_lang_Class_ = java_lang_Class;
}
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index c83f411..e735c45 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -24,6 +24,7 @@
#include "object.h"
#include "object_callbacks.h"
#include "primitive.h"
+#include "read_barrier.h"
/*
* A magic value for refOffsets. Ignore the bits and walk the super
@@ -376,8 +377,10 @@
bool IsThrowableClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
bool IsArtFieldClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
bool IsArtMethodClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static MemberOffset ComponentTypeOffset() {
@@ -845,13 +848,14 @@
SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), type_idx);
}
- static Class* GetJavaLangClass() {
+ static Class* GetJavaLangClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(java_lang_Class_ != NULL);
- return java_lang_Class_;
+ return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(
+ &java_lang_Class_);
}
// Can't call this SetClass or else gets called instead of Object::SetClass in places.
- static void SetClassClass(Class* java_lang_Class);
+ static void SetClassClass(Class* java_lang_Class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static void ResetClass();
static void VisitRoots(RootCallback* callback, void* arg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 15ecd3c..62c1162 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -218,7 +218,8 @@
template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline bool Object::IsArtField() {
- return GetClass<kVerifyFlags, kReadBarrierOption>()->IsArtFieldClass();
+ return GetClass<kVerifyFlags, kReadBarrierOption>()->
+ template IsArtFieldClass<kReadBarrierOption>();
}
template<VerifyObjectFlags kVerifyFlags>
@@ -229,7 +230,8 @@
template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline bool Object::IsArtMethod() {
- return GetClass<kVerifyFlags, kReadBarrierOption>()->IsArtMethodClass();
+ return GetClass<kVerifyFlags, kReadBarrierOption>()->
+ template IsArtMethodClass<kReadBarrierOption>();
}
template<VerifyObjectFlags kVerifyFlags>
diff --git a/runtime/mirror/stack_trace_element.h b/runtime/mirror/stack_trace_element.h
index e094e8b..abecbc5 100644
--- a/runtime/mirror/stack_trace_element.h
+++ b/runtime/mirror/stack_trace_element.h
@@ -19,6 +19,7 @@
#include "object.h"
#include "object_callbacks.h"
+#include "read_barrier.h"
namespace art {
@@ -55,9 +56,10 @@
static void ResetClass();
static void VisitRoots(RootCallback* callback, void* arg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static Class* GetStackTraceElement() {
+ static Class* GetStackTraceElement() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(java_lang_StackTraceElement_ != NULL);
- return java_lang_StackTraceElement_;
+ return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(
+ &java_lang_StackTraceElement_);
}
private:
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index 6c3015f..b8acede 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -21,6 +21,7 @@
#include "class.h"
#include "object_callbacks.h"
+#include "read_barrier.h"
namespace art {
@@ -102,9 +103,10 @@
int32_t CompareTo(String* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static Class* GetJavaLangString() {
+ static Class* GetJavaLangString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(java_lang_String_ != NULL);
- return java_lang_String_;
+ return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(
+ &java_lang_String_);
}
static void SetClass(Class* java_lang_String);
diff --git a/runtime/mirror/throwable.h b/runtime/mirror/throwable.h
index c4127e0..cf54ad6 100644
--- a/runtime/mirror/throwable.h
+++ b/runtime/mirror/throwable.h
@@ -19,6 +19,7 @@
#include "object.h"
#include "object_callbacks.h"
+#include "read_barrier.h"
#include "string.h"
namespace art {
@@ -45,9 +46,10 @@
void SetStackState(Object* state) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsCheckedException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static Class* GetJavaLangThrowable() {
+ static Class* GetJavaLangThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(java_lang_Throwable_ != NULL);
- return java_lang_Throwable_;
+ return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(
+ &java_lang_Throwable_);
}
static void SetClass(Class* java_lang_Throwable);
diff --git a/runtime/profiler.cc b/runtime/profiler.cc
index cecd86f..7a7a92a 100644
--- a/runtime/profiler.cc
+++ b/runtime/profiler.cc
@@ -752,9 +752,9 @@
// Bad summary info. It should be count/nullcount/bootcount
return;
}
- previous_num_samples_ = atoi(summary_info[0].c_str());
- previous_num_null_methods_ = atoi(summary_info[1].c_str());
- previous_num_boot_methods_ = atoi(summary_info[2].c_str());
+ previous_num_samples_ = strtoul(summary_info[0].c_str(), nullptr, 10);
+ previous_num_null_methods_ = strtoul(summary_info[1].c_str(), nullptr, 10);
+ previous_num_boot_methods_ = strtoul(summary_info[2].c_str(), nullptr, 10);
// Now read each line until the end of file. Each line consists of 3 or 4 fields separated by /
while (true) {
@@ -768,8 +768,8 @@
break;
}
std::string methodname = info[0];
- uint32_t total_count = atoi(info[1].c_str());
- uint32_t size = atoi(info[2].c_str());
+ uint32_t total_count = strtoul(info[1].c_str(), nullptr, 10);
+ uint32_t size = strtoul(info[2].c_str(), nullptr, 10);
PreviousContextMap* context_map = nullptr;
if (type == kProfilerBoundedStack && info.size() == 4) {
context_map = new PreviousContextMap();
@@ -781,13 +781,13 @@
Split(context_count_pairs[i], ':', context_count);
if (context_count.size() == 2) {
// Handles the situtation when the profile file doesn't contain context information.
- uint32_t dexpc = atoi(context_count[0].c_str());
- uint32_t count = atoi(context_count[1].c_str());
+ uint32_t dexpc = strtoul(context_count[0].c_str(), nullptr, 10);
+ uint32_t count = strtoul(context_count[1].c_str(), nullptr, 10);
(*context_map)[std::make_pair(dexpc, "")] = count;
} else {
// Handles the situtation when the profile file contains context information.
- uint32_t dexpc = atoi(context_count[0].c_str());
- uint32_t count = atoi(context_count[1].c_str());
+ uint32_t dexpc = strtoul(context_count[0].c_str(), nullptr, 10);
+ uint32_t count = strtoul(context_count[1].c_str(), nullptr, 10);
std::string context = context_count[2];
(*context_map)[std::make_pair(dexpc, context)] = count;
}
@@ -830,7 +830,7 @@
return false;
}
// This is the number of hits in all profiled methods (without nullptr or boot methods)
- uint32_t total_count = atoi(summary_info[0].c_str());
+ uint32_t total_count = strtoul(summary_info[0].c_str(), nullptr, 10);
// Now read each line until the end of file. Each line consists of 3 fields separated by '/'.
// Store the info in descending order given by the most used methods.
@@ -857,7 +857,7 @@
for (ProfileSet::iterator it = countSet.begin(); it != end ; it++) {
const std::string& methodname = it->second[0];
uint32_t count = -it->first;
- uint32_t size = atoi(it->second[2].c_str());
+ uint32_t size = strtoul(it->second[2].c_str(), nullptr, 10);
double usedPercent = (count * 100.0) / total_count;
curTotalCount += count;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 8aa7ea1..53ddcca 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -241,16 +241,22 @@
}
void DumpAllThreads(std::ostream& os, Thread* self) NO_THREAD_SAFETY_ANALYSIS {
- bool tll_already_held = Locks::thread_list_lock_->IsExclusiveHeld(self);
- bool ml_already_held = Locks::mutator_lock_->IsSharedHeld(self);
- if (!tll_already_held || !ml_already_held) {
- os << "Dumping all threads without appropriate locks held:"
- << (!tll_already_held ? " thread list lock" : "")
- << (!ml_already_held ? " mutator lock" : "")
- << "\n";
+ Runtime* runtime = Runtime::Current();
+ if (runtime != nullptr) {
+ ThreadList* thread_list = runtime->GetThreadList();
+ if (thread_list != nullptr) {
+ bool tll_already_held = Locks::thread_list_lock_->IsExclusiveHeld(self);
+ bool ml_already_held = Locks::mutator_lock_->IsSharedHeld(self);
+ if (!tll_already_held || !ml_already_held) {
+ os << "Dumping all threads without appropriate locks held:"
+ << (!tll_already_held ? " thread list lock" : "")
+ << (!ml_already_held ? " mutator lock" : "")
+ << "\n";
+ }
+ os << "All threads:\n";
+ thread_list->DumpLocked(os);
+ }
}
- os << "All threads:\n";
- Runtime::Current()->GetThreadList()->DumpLocked(os);
}
};