From 378f7086b7099bf4b46c7af5f979545a7565693f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 7 Dec 2010 15:57:11 -0700 Subject: [PATCH] fix return address code offset calculation on ARM We have to be careful about how we calculate return addresses on ARM due to padding introduced by constant pools interspersed with code. When calculating the offset of code where we're inserting a constant pool, we want the offset of the end of the pool for jump targets, but we want the offset just prior to the beginning of the pool (i.e. the offset of the instruction responsible for jumping past the pool) when calculating a return address. --- src/arm.cpp | 15 ++++++++------- src/assembler.h | 2 +- src/compiler.cpp | 5 +++-- src/powerpc.cpp | 2 +- src/x86.cpp | 2 +- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index 46e87a3b23..3d858e9e4d 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -320,8 +320,8 @@ expect(Context* c, bool v) class Offset: public Promise { public: - Offset(Context* c, MyBlock* block, unsigned offset): - c(c), block(block), offset(offset) + Offset(Context* c, MyBlock* block, unsigned offset, bool forTrace): + c(c), block(block), offset(offset), forTrace(forTrace) { } virtual bool resolved() { @@ -332,19 +332,20 @@ class Offset: public Promise { assert(c, resolved()); unsigned o = offset - block->offset; - return block->start + padding(block, o) + o; + return block->start + padding(block, forTrace ? o - BytesPerWord : o) + o; } Context* c; MyBlock* block; unsigned offset; + bool forTrace; }; Promise* -offset(Context* c) +offset(Context* c, bool forTrace = false) { return new (c->zone->allocate(sizeof(Offset))) - Offset(c, c->lastBlock, c->code.length()); + Offset(c, c->lastBlock, c->code.length(), forTrace); } bool @@ -2271,8 +2272,8 @@ class MyAssembler: public Assembler { } } - virtual Promise* offset() { - return ::offset(&c); + virtual Promise* offset(bool forTrace) { + return ::offset(&c, forTrace); } virtual Block* endBlock(bool startNew) { diff --git a/src/assembler.h b/src/assembler.h index 1752de74f2..4c5f67b1a9 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -414,7 +414,7 @@ class Assembler { virtual void writeTo(uint8_t* dst) = 0; - virtual Promise* offset() = 0; + virtual Promise* offset(bool forTrace = false) = 0; virtual Block* endBlock(bool startNew) = 0; diff --git a/src/compiler.cpp b/src/compiler.cpp index 7610d5a79d..b6cf197157 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -3098,7 +3098,8 @@ codePromise(Context* c, Event* e) CodePromise* codePromise(Context* c, Promise* offset) { - return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset); + return new (c->zone->allocate(sizeof(CodePromise))) + CodePromise(c, offset); } void @@ -3357,7 +3358,7 @@ class CallEvent: public Event { apply(c, op, BytesPerWord, address->source, address->source); if (traceHandler) { - traceHandler->handleTrace(codePromise(c, c->assembler->offset()), + traceHandler->handleTrace(codePromise(c, c->assembler->offset(true)), stackArgumentIndex); } diff --git a/src/powerpc.cpp b/src/powerpc.cpp index ff83fbe807..9973ccc544 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -2377,7 +2377,7 @@ class MyAssembler: public Assembler { } } - virtual Promise* offset() { + virtual Promise* offset(bool) { return ::offset(&c); } diff --git a/src/x86.cpp b/src/x86.cpp index 2501ac754c..4c11e8adfe 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -3536,7 +3536,7 @@ class MyAssembler: public Assembler { } } - virtual Promise* offset() { + virtual Promise* offset(bool) { return local::offset(&c); }