diff options
Diffstat (limited to 'compiler/oat_writer.cc')
-rw-r--r-- | compiler/oat_writer.cc | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 04f0db657..2c3f98240 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -105,9 +105,9 @@ class OatWriter::NoRelativePatcher FINAL : public RelativePatcher { DISALLOW_COPY_AND_ASSIGN(NoRelativePatcher); }; -class OatWriter::X86RelativePatcher FINAL : public RelativePatcher { +class OatWriter::X86BaseRelativePatcher : public RelativePatcher { public: - X86RelativePatcher() { } + X86BaseRelativePatcher() { } uint32_t ReserveSpace(uint32_t offset, const CompiledMethod* compiled_method ATTRIBUTE_UNUSED) OVERRIDE { @@ -129,19 +129,42 @@ class OatWriter::X86RelativePatcher FINAL : public RelativePatcher { reinterpret_cast<unaligned_int32_t*>(&(*code)[literal_offset])[0] = displacement; } + protected: + // PC displacement from patch location; the base address of x86/x86-64 relative + // calls and x86-64 RIP-relative addressing is the PC of the next instruction and + // the patch location is 4 bytes earlier. + static constexpr int32_t kPcDisplacement = 4; + + private: + DISALLOW_COPY_AND_ASSIGN(X86BaseRelativePatcher); +}; + +class OatWriter::X86RelativePatcher FINAL : public X86BaseRelativePatcher { + public: + X86RelativePatcher() { } + virtual void PatchDexCacheReference(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, const LinkerPatch& patch ATTRIBUTE_UNUSED, uint32_t patch_offset ATTRIBUTE_UNUSED, uint32_t target_offset ATTRIBUTE_UNUSED) { LOG(FATAL) << "Unexpected relative dex cache array patch."; } +}; - private: - // PC displacement from patch location; x86 PC for relative calls points to the next - // instruction and the patch location is 4 bytes earlier. - static constexpr int32_t kPcDisplacement = 4; +class OatWriter::X86_64RelativePatcher FINAL : public X86BaseRelativePatcher { + public: + X86_64RelativePatcher() { } + + virtual void PatchDexCacheReference(std::vector<uint8_t>* code, const LinkerPatch& patch, + uint32_t patch_offset, uint32_t target_offset) { + DCHECK_LE(patch.LiteralOffset() + 4u, code->size()); + // Unsigned arithmetic with its well-defined overflow behavior is just fine here. + uint32_t displacement = target_offset - patch_offset; + displacement -= kPcDisplacement; // The base PC is at the end of the 4-byte patch. - DISALLOW_COPY_AND_ASSIGN(X86RelativePatcher); + typedef __attribute__((__aligned__(1))) int32_t unaligned_int32_t; + reinterpret_cast<unaligned_int32_t*>(&(*code)[patch.LiteralOffset()])[0] = displacement; + } }; class OatWriter::ArmBaseRelativePatcher : public RelativePatcher { @@ -706,9 +729,11 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, switch (compiler_driver_->GetInstructionSet()) { case kX86: - case kX86_64: relative_patcher_.reset(new X86RelativePatcher); break; + case kX86_64: + relative_patcher_.reset(new X86_64RelativePatcher); + break; case kArm: // Fall through: we generate Thumb2 code for "arm". case kThumb2: |