mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
fix ARM stack unwinding
We can't rely on the C++ compiler to save the return address in a known location on entry to each function we might call from Java (although GCC 4.5 seems to do so consistently, which is why I hadn't realized the unwinding code was relying on that assumption), so we must store it explicitly in MyThread::ip in each thunk. For PowerPC and x86, we continue saving it on the stack as always, since the calling convention guarantees its location relative to the stack pointer.
This commit is contained in:
parent
b2268143f5
commit
8a88c6ee3c
@ -2126,7 +2126,11 @@ class MyAssembler: public Assembler {
|
||||
&handlerConstant);
|
||||
}
|
||||
|
||||
virtual void saveFrame(unsigned stackOffset) {
|
||||
virtual void saveFrame(unsigned stackOffset, unsigned ipOffset) {
|
||||
Register link(LinkRegister);
|
||||
Memory linkDst(ThreadRegister, ipOffset);
|
||||
moveRM(&c, BytesPerWord, &link, BytesPerWord, &linkDst);
|
||||
|
||||
Register stack(StackRegister);
|
||||
Memory stackDst(ThreadRegister, stackOffset);
|
||||
moveRM(&c, BytesPerWord, &stack, BytesPerWord, &stackDst);
|
||||
|
@ -397,7 +397,7 @@ class Assembler {
|
||||
|
||||
virtual void checkStackOverflow(uintptr_t handler,
|
||||
unsigned stackLimitOffsetFromThread) = 0;
|
||||
virtual void saveFrame(unsigned stackOffset) = 0;
|
||||
virtual void saveFrame(unsigned stackOffset, unsigned ipOffset) = 0;
|
||||
virtual void pushFrame(unsigned argumentCount, ...) = 0;
|
||||
virtual void allocateFrame(unsigned footprint) = 0;
|
||||
virtual void adjustFrame(unsigned difference) = 0;
|
||||
|
@ -435,6 +435,18 @@ nextFrame(MyThread* t, void** ip, void** sp, object method, object target)
|
||||
// fprintf(stderr, "next frame ip %p sp %p\n", *ip, *sp);
|
||||
}
|
||||
|
||||
void*
|
||||
getIp(MyThread* t)
|
||||
{
|
||||
// Here we use the convention that, if the return address is neither
|
||||
// pushed on to the stack automatically as part of the call nor
|
||||
// stored in the caller's frame, it will be saved in MyThread::ip
|
||||
// instead of on the stack. See the various implementations of
|
||||
// Assembler::saveFrame for details on how this is done.
|
||||
return t->arch->returnAddressOffset() < 0
|
||||
? t->ip : t->arch->frameIp(t->stack);
|
||||
}
|
||||
|
||||
class MyStackWalker: public Processor::StackWalker {
|
||||
public:
|
||||
enum State {
|
||||
@ -475,7 +487,7 @@ class MyStackWalker: public Processor::StackWalker {
|
||||
trace = t->traceContext->trace;
|
||||
continuation = t->traceContext->continuation;
|
||||
} else {
|
||||
ip_ = 0;
|
||||
ip_ = getIp(t);
|
||||
stack = t->stack;
|
||||
trace = t->trace;
|
||||
continuation = t->continuation;
|
||||
@ -1981,7 +1993,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetFrame,
|
||||
stack = t->traceContext->stack;
|
||||
continuation = t->traceContext->continuation;
|
||||
} else {
|
||||
ip = 0;
|
||||
ip = getIp(t);
|
||||
stack = t->stack;
|
||||
continuation = t->continuation;
|
||||
}
|
||||
@ -6669,7 +6681,7 @@ visitArguments(MyThread* t, Heap::Visitor* v, void* stack, object method)
|
||||
void
|
||||
visitStack(MyThread* t, Heap::Visitor* v)
|
||||
{
|
||||
void* ip = t->arch->frameIp(t->stack);
|
||||
void* ip = getIp(t);
|
||||
void* stack = t->stack;
|
||||
|
||||
MyThread::CallTrace* trace = t->trace;
|
||||
@ -8398,7 +8410,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = defaultContext.context.assembler;
|
||||
|
||||
a->saveFrame(difference(&(t->stack), t));
|
||||
a->saveFrame(difference(&(t->stack), t), difference(&(t->ip), t));
|
||||
|
||||
p->thunks.default_.frameSavedOffset = a->length();
|
||||
|
||||
@ -8442,7 +8454,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
a->apply(Move, BytesPerWord, RegisterOperand, &index,
|
||||
BytesPerWord, MemoryOperand, &virtualCallIndex);
|
||||
|
||||
a->saveFrame(difference(&(t->stack), t));
|
||||
a->saveFrame(difference(&(t->stack), t), difference(&(t->ip), t));
|
||||
|
||||
p->thunks.defaultVirtual.frameSavedOffset = a->length();
|
||||
|
||||
@ -8464,7 +8476,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = nativeContext.context.assembler;
|
||||
|
||||
a->saveFrame(difference(&(t->stack), t));
|
||||
a->saveFrame(difference(&(t->stack), t), difference(&(t->ip), t));
|
||||
|
||||
p->thunks.native.frameSavedOffset = a->length();
|
||||
|
||||
@ -8484,7 +8496,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = aioobContext.context.assembler;
|
||||
|
||||
a->saveFrame(difference(&(t->stack), t));
|
||||
a->saveFrame(difference(&(t->stack), t), difference(&(t->ip), t));
|
||||
|
||||
p->thunks.aioob.frameSavedOffset = a->length();
|
||||
|
||||
@ -8501,7 +8513,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = stackOverflowContext.context.assembler;
|
||||
|
||||
a->saveFrame(difference(&(t->stack), t));
|
||||
a->saveFrame(difference(&(t->stack), t), difference(&(t->ip), t));
|
||||
|
||||
p->thunks.stackOverflow.frameSavedOffset = a->length();
|
||||
|
||||
@ -8518,7 +8530,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = tableContext.context.assembler;
|
||||
|
||||
a->saveFrame(difference(&(t->stack), t));
|
||||
a->saveFrame(difference(&(t->stack), t), difference(&(t->ip), t));
|
||||
|
||||
p->thunks.table.frameSavedOffset = a->length();
|
||||
|
||||
|
@ -2253,7 +2253,7 @@ class MyAssembler: public Assembler {
|
||||
&handlerConstant);
|
||||
}
|
||||
|
||||
virtual void saveFrame(unsigned stackOffset) {
|
||||
virtual void saveFrame(unsigned stackOffset, unsigned) {
|
||||
Register returnAddress(0);
|
||||
emit(&c, mflr(returnAddress.low));
|
||||
|
||||
|
@ -3382,7 +3382,7 @@ class MyAssembler: public Assembler {
|
||||
&handlerConstant);
|
||||
}
|
||||
|
||||
virtual void saveFrame(unsigned stackOffset) {
|
||||
virtual void saveFrame(unsigned stackOffset, unsigned) {
|
||||
Register stack(rsp);
|
||||
Memory stackDst(rbx, stackOffset);
|
||||
apply(Move, BytesPerWord, RegisterOperand, &stack,
|
||||
|
Loading…
Reference in New Issue
Block a user