diff options
author | 2017-09-01 13:35:26 +0100 | |
---|---|---|
committer | 2017-09-18 16:53:30 +0100 | |
commit | 1b404a8b34f6fa80342955cb0a61673503328b51 (patch) | |
tree | df0d83903e77c55dcb476a19961ea9cccc13e616 /compiler/linker | |
parent | fe712a8b9c247d66df013f2b4b6faa6009d745bb (diff) |
Add debug info for link-time generated thunks.
Add debug info for method call thunks (currently unused) and
Baker read barrier thunks. Refactor debug info generation
for trampolines and record their sizes; change their names
to start with upper-case letters, so that they can be easily
generated as `#fn_name`.
This improved debug info must be generated by `dex2oat -g`,
the debug info generated by `oatdump --symbolize` remains
the same as before, except for the renamed trampolines and
an adjustment for "code delta", i.e. the Thumb mode bit.
Cortex-A53 erratum 843419 workaround thunks are not covered
by this CL.
Test: Manual; run-test --gdb -Xcompiler-option -g 160, pull
symbols for gdbclient, break in the introspection
entrypoint, check that gdb knows the new symbols
(and disassembles them) and `backtrace` works when
setting $pc to an address in the thunk.
Bug: 36141117
Change-Id: Id224b72cfa7a0628799c7db65e66e24c8517aabf
Diffstat (limited to 'compiler/linker')
-rw-r--r-- | compiler/linker/arm/relative_patcher_arm_base.cc | 62 | ||||
-rw-r--r-- | compiler/linker/arm/relative_patcher_arm_base.h | 2 | ||||
-rw-r--r-- | compiler/linker/arm/relative_patcher_thumb2.cc | 40 | ||||
-rw-r--r-- | compiler/linker/arm/relative_patcher_thumb2.h | 1 | ||||
-rw-r--r-- | compiler/linker/arm64/relative_patcher_arm64.cc | 29 | ||||
-rw-r--r-- | compiler/linker/arm64/relative_patcher_arm64.h | 1 | ||||
-rw-r--r-- | compiler/linker/mips/relative_patcher_mips.cc | 6 | ||||
-rw-r--r-- | compiler/linker/mips/relative_patcher_mips.h | 1 | ||||
-rw-r--r-- | compiler/linker/mips64/relative_patcher_mips64.cc | 6 | ||||
-rw-r--r-- | compiler/linker/mips64/relative_patcher_mips64.h | 1 | ||||
-rw-r--r-- | compiler/linker/multi_oat_relative_patcher.h | 6 | ||||
-rw-r--r-- | compiler/linker/multi_oat_relative_patcher_test.cc | 7 | ||||
-rw-r--r-- | compiler/linker/relative_patcher.cc | 6 | ||||
-rw-r--r-- | compiler/linker/relative_patcher.h | 7 | ||||
-rw-r--r-- | compiler/linker/x86/relative_patcher_x86_base.cc | 7 | ||||
-rw-r--r-- | compiler/linker/x86/relative_patcher_x86_base.h | 1 |
16 files changed, 182 insertions, 1 deletions
diff --git a/compiler/linker/arm/relative_patcher_arm_base.cc b/compiler/linker/arm/relative_patcher_arm_base.cc index 4ca5afe177..6e63bf8990 100644 --- a/compiler/linker/arm/relative_patcher_arm_base.cc +++ b/compiler/linker/arm/relative_patcher_arm_base.cc @@ -18,6 +18,7 @@ #include "base/stl_util.h" #include "compiled_method.h" +#include "debug/method_debug_info.h" #include "linker/output_stream.h" #include "oat.h" #include "oat_quick_method_header.h" @@ -119,6 +120,25 @@ class ArmBaseRelativePatcher::ThunkData { return offsets_[pending_offset_ - 1u]; } + size_t IndexOfFirstThunkAtOrAfter(uint32_t offset) const { + size_t number_of_thunks = NumberOfThunks(); + for (size_t i = 0; i != number_of_thunks; ++i) { + if (GetThunkOffset(i) >= offset) { + return i; + } + } + return number_of_thunks; + } + + size_t NumberOfThunks() const { + return offsets_.size(); + } + + uint32_t GetThunkOffset(size_t index) const { + DCHECK_LT(index, NumberOfThunks()); + return offsets_[index]; + } + private: std::vector<uint8_t> code_; // The code of the thunk. std::vector<uint32_t> offsets_; // Offsets at which the thunk needs to be written. @@ -203,6 +223,48 @@ uint32_t ArmBaseRelativePatcher::WriteThunks(OutputStream* out, uint32_t offset) return offset; } +std::vector<debug::MethodDebugInfo> ArmBaseRelativePatcher::GenerateThunkDebugInfo( + uint32_t executable_offset) { + // For multi-oat compilation (boot image), `thunks_` records thunks for all oat files. + // To return debug info for the current oat file, we must ignore thunks before the + // `executable_offset` as they are in the previous oat files and this function must be + // called before reserving thunk positions for subsequent oat files. + size_t number_of_thunks = 0u; + for (auto&& entry : thunks_) { + const ThunkData& data = entry.second; + number_of_thunks += data.NumberOfThunks() - data.IndexOfFirstThunkAtOrAfter(executable_offset); + } + std::vector<debug::MethodDebugInfo> result; + result.reserve(number_of_thunks); + for (auto&& entry : thunks_) { + const ThunkKey& key = entry.first; + const ThunkData& data = entry.second; + size_t start = data.IndexOfFirstThunkAtOrAfter(executable_offset); + if (start == data.NumberOfThunks()) { + continue; + } + // Get the base name to use for the first occurrence of the thunk. + std::string base_name = GetThunkDebugName(key); + for (size_t i = start, num = data.NumberOfThunks(); i != num; ++i) { + debug::MethodDebugInfo info = {}; + if (i == 0u) { + info.trampoline_name = base_name; + } else { + // Add a disambiguating tag for subsequent identical thunks. Since the `thunks_` + // keeps records also for thunks in previous oat files, names based on the thunk + // index shall be unique across the whole multi-oat output. + info.trampoline_name = base_name + "_" + std::to_string(i); + } + info.isa = instruction_set_; + info.is_code_address_text_relative = true; + info.code_address = data.GetThunkOffset(i) - executable_offset; + info.code_size = data.CodeSize(); + result.push_back(std::move(info)); + } + } + return result; +} + ArmBaseRelativePatcher::ArmBaseRelativePatcher(RelativePatcherTargetProvider* provider, InstructionSet instruction_set) : provider_(provider), diff --git a/compiler/linker/arm/relative_patcher_arm_base.h b/compiler/linker/arm/relative_patcher_arm_base.h index 5197ce2549..4c2be1e1a7 100644 --- a/compiler/linker/arm/relative_patcher_arm_base.h +++ b/compiler/linker/arm/relative_patcher_arm_base.h @@ -34,6 +34,7 @@ class ArmBaseRelativePatcher : public RelativePatcher { MethodReference method_ref) OVERRIDE; uint32_t ReserveSpaceEnd(uint32_t offset) OVERRIDE; uint32_t WriteThunks(OutputStream* out, uint32_t offset) OVERRIDE; + std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo(uint32_t executable_offset) OVERRIDE; protected: ArmBaseRelativePatcher(RelativePatcherTargetProvider* provider, @@ -94,6 +95,7 @@ class ArmBaseRelativePatcher : public RelativePatcher { uint32_t target_offset); virtual std::vector<uint8_t> CompileThunk(const ThunkKey& key) = 0; + virtual std::string GetThunkDebugName(const ThunkKey& key) = 0; virtual uint32_t MaxPositiveDisplacement(const ThunkKey& key) = 0; virtual uint32_t MaxNegativeDisplacement(const ThunkKey& key) = 0; diff --git a/compiler/linker/arm/relative_patcher_thumb2.cc b/compiler/linker/arm/relative_patcher_thumb2.cc index 2ac2a1d2fc..704feeb387 100644 --- a/compiler/linker/arm/relative_patcher_thumb2.cc +++ b/compiler/linker/arm/relative_patcher_thumb2.cc @@ -281,7 +281,7 @@ void Thumb2RelativePatcher::CompileBakerReadBarrierThunk(arm::ArmVIXLAssembler& Register base_reg(BakerReadBarrierFirstRegField::Decode(encoded_data)); CheckValidReg(base_reg.GetCode()); DCHECK_EQ(kInvalidEncodedReg, BakerReadBarrierSecondRegField::Decode(encoded_data)); - DCHECK(BakerReadBarrierWidth::kWide == BakerReadBarrierWidthField::Decode(encoded_data)); + DCHECK(BakerReadBarrierWidthField::Decode(encoded_data) == BakerReadBarrierWidth::kWide); UseScratchRegisterScope temps(assembler.GetVIXLAssembler()); temps.Exclude(ip); vixl::aarch32::Label slow_path; @@ -379,6 +379,44 @@ std::vector<uint8_t> Thumb2RelativePatcher::CompileThunk(const ThunkKey& key) { return thunk_code; } +std::string Thumb2RelativePatcher::GetThunkDebugName(const ThunkKey& key) { + switch (key.GetType()) { + case ThunkType::kMethodCall: + return "MethodCallThunk"; + + case ThunkType::kBakerReadBarrier: { + uint32_t encoded_data = key.GetCustomValue1(); + BakerReadBarrierKind kind = BakerReadBarrierKindField::Decode(encoded_data); + std::ostringstream oss; + oss << "BakerReadBarrierThunk"; + switch (kind) { + case BakerReadBarrierKind::kField: + oss << "Field"; + if (BakerReadBarrierWidthField::Decode(encoded_data) == BakerReadBarrierWidth::kWide) { + oss << "Wide"; + } + oss << "_r" << BakerReadBarrierFirstRegField::Decode(encoded_data) + << "_r" << BakerReadBarrierSecondRegField::Decode(encoded_data); + break; + case BakerReadBarrierKind::kArray: + oss << "Array_r" << BakerReadBarrierFirstRegField::Decode(encoded_data); + DCHECK_EQ(kInvalidEncodedReg, BakerReadBarrierSecondRegField::Decode(encoded_data)); + DCHECK(BakerReadBarrierWidthField::Decode(encoded_data) == BakerReadBarrierWidth::kWide); + break; + case BakerReadBarrierKind::kGcRoot: + oss << "GcRoot"; + if (BakerReadBarrierWidthField::Decode(encoded_data) == BakerReadBarrierWidth::kWide) { + oss << "Wide"; + } + oss << "_r" << BakerReadBarrierFirstRegField::Decode(encoded_data); + DCHECK_EQ(kInvalidEncodedReg, BakerReadBarrierSecondRegField::Decode(encoded_data)); + break; + } + return oss.str(); + } + } +} + #undef __ uint32_t Thumb2RelativePatcher::MaxPositiveDisplacement(const ThunkKey& key) { diff --git a/compiler/linker/arm/relative_patcher_thumb2.h b/compiler/linker/arm/relative_patcher_thumb2.h index 183e5e6c96..68386c00f4 100644 --- a/compiler/linker/arm/relative_patcher_thumb2.h +++ b/compiler/linker/arm/relative_patcher_thumb2.h @@ -84,6 +84,7 @@ class Thumb2RelativePatcher FINAL : public ArmBaseRelativePatcher { protected: std::vector<uint8_t> CompileThunk(const ThunkKey& key) OVERRIDE; + std::string GetThunkDebugName(const ThunkKey& key) OVERRIDE; uint32_t MaxPositiveDisplacement(const ThunkKey& key) OVERRIDE; uint32_t MaxNegativeDisplacement(const ThunkKey& key) OVERRIDE; diff --git a/compiler/linker/arm64/relative_patcher_arm64.cc b/compiler/linker/arm64/relative_patcher_arm64.cc index 4960f4d856..270ba3c08d 100644 --- a/compiler/linker/arm64/relative_patcher_arm64.cc +++ b/compiler/linker/arm64/relative_patcher_arm64.cc @@ -535,6 +535,35 @@ std::vector<uint8_t> Arm64RelativePatcher::CompileThunk(const ThunkKey& key) { return thunk_code; } +std::string Arm64RelativePatcher::GetThunkDebugName(const ThunkKey& key) { + switch (key.GetType()) { + case ThunkType::kMethodCall: + return "MethodCallThunk"; + + case ThunkType::kBakerReadBarrier: { + uint32_t encoded_data = key.GetCustomValue1(); + BakerReadBarrierKind kind = BakerReadBarrierKindField::Decode(encoded_data); + std::ostringstream oss; + oss << "BakerReadBarrierThunk"; + switch (kind) { + case BakerReadBarrierKind::kField: + oss << "Field_r" << BakerReadBarrierFirstRegField::Decode(encoded_data) + << "_r" << BakerReadBarrierSecondRegField::Decode(encoded_data); + break; + case BakerReadBarrierKind::kArray: + oss << "Array_r" << BakerReadBarrierFirstRegField::Decode(encoded_data); + DCHECK_EQ(kInvalidEncodedReg, BakerReadBarrierSecondRegField::Decode(encoded_data)); + break; + case BakerReadBarrierKind::kGcRoot: + oss << "GcRoot_r" << BakerReadBarrierFirstRegField::Decode(encoded_data); + DCHECK_EQ(kInvalidEncodedReg, BakerReadBarrierSecondRegField::Decode(encoded_data)); + break; + } + return oss.str(); + } + } +} + #undef __ uint32_t Arm64RelativePatcher::MaxPositiveDisplacement(const ThunkKey& key) { diff --git a/compiler/linker/arm64/relative_patcher_arm64.h b/compiler/linker/arm64/relative_patcher_arm64.h index b00dd081b6..8ba59976e7 100644 --- a/compiler/linker/arm64/relative_patcher_arm64.h +++ b/compiler/linker/arm64/relative_patcher_arm64.h @@ -76,6 +76,7 @@ class Arm64RelativePatcher FINAL : public ArmBaseRelativePatcher { protected: std::vector<uint8_t> CompileThunk(const ThunkKey& key) OVERRIDE; + std::string GetThunkDebugName(const ThunkKey& key) OVERRIDE; uint32_t MaxPositiveDisplacement(const ThunkKey& key) OVERRIDE; uint32_t MaxNegativeDisplacement(const ThunkKey& key) OVERRIDE; diff --git a/compiler/linker/mips/relative_patcher_mips.cc b/compiler/linker/mips/relative_patcher_mips.cc index 6c974c308f..408ac22976 100644 --- a/compiler/linker/mips/relative_patcher_mips.cc +++ b/compiler/linker/mips/relative_patcher_mips.cc @@ -17,6 +17,7 @@ #include "linker/mips/relative_patcher_mips.h" #include "compiled_method.h" +#include "debug/method_debug_info.h" namespace art { namespace linker { @@ -90,5 +91,10 @@ void MipsRelativePatcher::PatchBakerReadBarrierBranch(std::vector<uint8_t>* code LOG(FATAL) << "UNIMPLEMENTED"; } +std::vector<debug::MethodDebugInfo> MipsRelativePatcher::GenerateThunkDebugInfo( + uint32_t executable_offset ATTRIBUTE_UNUSED) { + return std::vector<debug::MethodDebugInfo>(); // No thunks added. +} + } // namespace linker } // namespace art diff --git a/compiler/linker/mips/relative_patcher_mips.h b/compiler/linker/mips/relative_patcher_mips.h index d6eda34592..5714a7d1b0 100644 --- a/compiler/linker/mips/relative_patcher_mips.h +++ b/compiler/linker/mips/relative_patcher_mips.h @@ -44,6 +44,7 @@ class MipsRelativePatcher FINAL : public RelativePatcher { void PatchBakerReadBarrierBranch(std::vector<uint8_t>* code, const LinkerPatch& patch, uint32_t patch_offset) OVERRIDE; + std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo(uint32_t executable_offset) OVERRIDE; private: bool is_r6; diff --git a/compiler/linker/mips64/relative_patcher_mips64.cc b/compiler/linker/mips64/relative_patcher_mips64.cc index d9f4758eb1..2bcd98a2b0 100644 --- a/compiler/linker/mips64/relative_patcher_mips64.cc +++ b/compiler/linker/mips64/relative_patcher_mips64.cc @@ -17,6 +17,7 @@ #include "linker/mips64/relative_patcher_mips64.h" #include "compiled_method.h" +#include "debug/method_debug_info.h" namespace art { namespace linker { @@ -88,5 +89,10 @@ void Mips64RelativePatcher::PatchBakerReadBarrierBranch(std::vector<uint8_t>* co LOG(FATAL) << "UNIMPLEMENTED"; } +std::vector<debug::MethodDebugInfo> Mips64RelativePatcher::GenerateThunkDebugInfo( + uint32_t executable_offset ATTRIBUTE_UNUSED) { + return std::vector<debug::MethodDebugInfo>(); // No thunks added. +} + } // namespace linker } // namespace art diff --git a/compiler/linker/mips64/relative_patcher_mips64.h b/compiler/linker/mips64/relative_patcher_mips64.h index f478d7f2ef..6d7c638312 100644 --- a/compiler/linker/mips64/relative_patcher_mips64.h +++ b/compiler/linker/mips64/relative_patcher_mips64.h @@ -42,6 +42,7 @@ class Mips64RelativePatcher FINAL : public RelativePatcher { void PatchBakerReadBarrierBranch(std::vector<uint8_t>* code, const LinkerPatch& patch, uint32_t patch_offset) OVERRIDE; + std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo(uint32_t executable_offset) OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(Mips64RelativePatcher); diff --git a/compiler/linker/multi_oat_relative_patcher.h b/compiler/linker/multi_oat_relative_patcher.h index bdc1ee1d27..1c5c8a09c0 100644 --- a/compiler/linker/multi_oat_relative_patcher.h +++ b/compiler/linker/multi_oat_relative_patcher.h @@ -18,6 +18,7 @@ #define ART_COMPILER_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_ #include "arch/instruction_set.h" +#include "debug/method_debug_info.h" #include "method_reference.h" #include "relative_patcher.h" #include "safe_map.h" @@ -119,6 +120,11 @@ class MultiOatRelativePatcher FINAL { relative_patcher_->PatchBakerReadBarrierBranch(code, patch, patch_offset); } + std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo(size_t executable_offset) { + executable_offset += adjustment_; + return relative_patcher_->GenerateThunkDebugInfo(executable_offset); + } + // Wrappers around RelativePatcher for statistics retrieval. uint32_t CodeAlignmentSize() const; uint32_t RelativeCallThunksSize() const; diff --git a/compiler/linker/multi_oat_relative_patcher_test.cc b/compiler/linker/multi_oat_relative_patcher_test.cc index e96790115a..f89fba698c 100644 --- a/compiler/linker/multi_oat_relative_patcher_test.cc +++ b/compiler/linker/multi_oat_relative_patcher_test.cc @@ -17,6 +17,7 @@ #include "multi_oat_relative_patcher.h" #include "compiled_method.h" +#include "debug/method_debug_info.h" #include "gtest/gtest.h" #include "vector_output_stream.h" @@ -102,6 +103,12 @@ class MultiOatRelativePatcherTest : public testing::Test { LOG(FATAL) << "UNIMPLEMENTED"; } + std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo( + uint32_t executable_offset ATTRIBUTE_UNUSED) { + LOG(FATAL) << "UNIMPLEMENTED"; + UNREACHABLE(); + } + uint32_t last_reserve_offset_ = 0u; MethodReference last_reserve_method_ = kNullMethodRef; uint32_t next_reserve_adjustment_ = 0u; diff --git a/compiler/linker/relative_patcher.cc b/compiler/linker/relative_patcher.cc index ee49453938..dc15bb087e 100644 --- a/compiler/linker/relative_patcher.cc +++ b/compiler/linker/relative_patcher.cc @@ -16,6 +16,7 @@ #include "linker/relative_patcher.h" +#include "debug/method_debug_info.h" #ifdef ART_ENABLE_CODEGEN_arm #include "linker/arm/relative_patcher_thumb2.h" #endif @@ -81,6 +82,11 @@ std::unique_ptr<RelativePatcher> RelativePatcher::Create( LOG(FATAL) << "Unexpected baker read barrier branch patch."; } + std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo( + uint32_t executable_offset ATTRIBUTE_UNUSED) OVERRIDE { + return std::vector<debug::MethodDebugInfo>(); // No thunks added. + } + private: DISALLOW_COPY_AND_ASSIGN(RelativePatcherNone); }; diff --git a/compiler/linker/relative_patcher.h b/compiler/linker/relative_patcher.h index 38c8228422..53a096627f 100644 --- a/compiler/linker/relative_patcher.h +++ b/compiler/linker/relative_patcher.h @@ -31,6 +31,10 @@ class CompiledMethod; class LinkerPatch; class OutputStream; +namespace debug { +struct MethodDebugInfo; +} // namespace debug + namespace linker { /** @@ -114,6 +118,9 @@ class RelativePatcher { const LinkerPatch& patch, uint32_t patch_offset) = 0; + virtual std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo( + uint32_t executable_offset) = 0; + protected: RelativePatcher() : size_code_alignment_(0u), diff --git a/compiler/linker/x86/relative_patcher_x86_base.cc b/compiler/linker/x86/relative_patcher_x86_base.cc index bf3a648218..6a9690d768 100644 --- a/compiler/linker/x86/relative_patcher_x86_base.cc +++ b/compiler/linker/x86/relative_patcher_x86_base.cc @@ -16,6 +16,8 @@ #include "linker/x86/relative_patcher_x86_base.h" +#include "debug/method_debug_info.h" + namespace art { namespace linker { @@ -34,6 +36,11 @@ uint32_t X86BaseRelativePatcher::WriteThunks(OutputStream* out ATTRIBUTE_UNUSED, return offset; // No thunks added; no limit on relative call distance. } +std::vector<debug::MethodDebugInfo> X86BaseRelativePatcher::GenerateThunkDebugInfo( + uint32_t executable_offset ATTRIBUTE_UNUSED) { + return std::vector<debug::MethodDebugInfo>(); // No thunks added. +} + void X86BaseRelativePatcher::PatchCall(std::vector<uint8_t>* code, uint32_t literal_offset, uint32_t patch_offset, diff --git a/compiler/linker/x86/relative_patcher_x86_base.h b/compiler/linker/x86/relative_patcher_x86_base.h index ca83a72f48..6097345657 100644 --- a/compiler/linker/x86/relative_patcher_x86_base.h +++ b/compiler/linker/x86/relative_patcher_x86_base.h @@ -33,6 +33,7 @@ class X86BaseRelativePatcher : public RelativePatcher { uint32_t literal_offset, uint32_t patch_offset, uint32_t target_offset) OVERRIDE; + std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo(uint32_t executable_offset) OVERRIDE; protected: X86BaseRelativePatcher() { } |