summaryrefslogtreecommitdiffstats
path: root/compiler/oat_writer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/oat_writer.cc')
-rw-r--r--compiler/oat_writer.cc41
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: