mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +00:00
fix StackOverflowError stack walking in tails=true builds
The various Architecture::nextFrame implementations were not walking the stack correctly when a StackOverflowError was thrown. The throwStackOverflow thunk is called before the frame of the most recently called method has been fully created, and because tails=true builds use a different calling convention, we need to treat this situation carefully when building a stack trace or unwinding. Otherwise, we will skip past all the java frames to the next native frame, which is what was happening.
This commit is contained in:
parent
73e60adeab
commit
918b7828f1
@ -88,7 +88,7 @@ virtual unsigned alignFrameSize(unsigned sizeInWords) = 0;
|
|||||||
|
|
||||||
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
||||||
void* link, bool mostRecent,
|
void* link, bool mostRecent,
|
||||||
unsigned targetParameterFootprint, void** ip,
|
int targetParameterFootprint, void** ip,
|
||||||
void** stack) = 0;
|
void** stack) = 0;
|
||||||
virtual void* frameIp(void* stack) = 0;
|
virtual void* frameIp(void* stack) = 0;
|
||||||
virtual unsigned frameHeaderSize() = 0;
|
virtual unsigned frameHeaderSize() = 0;
|
||||||
@ -138,4 +138,4 @@ virtual void release() = 0;
|
|||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
|
||||||
#endif // AVIAN_CODEGEN_ARCHITECTURE_H
|
#endif // AVIAN_CODEGEN_ARCHITECTURE_H
|
||||||
|
@ -83,7 +83,7 @@ argumentFootprint(unsigned footprint)
|
|||||||
void
|
void
|
||||||
nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
|
nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
|
||||||
unsigned footprint, void* link, bool,
|
unsigned footprint, void* link, bool,
|
||||||
unsigned targetParameterFootprint UNUSED, void** ip, void** stack)
|
int targetParameterFootprint UNUSED, void** ip, void** stack)
|
||||||
{
|
{
|
||||||
assert(con, *ip >= start);
|
assert(con, *ip >= start);
|
||||||
assert(con, *ip <= start + (size / TargetBytesPerWord));
|
assert(con, *ip <= start + (size / TargetBytesPerWord));
|
||||||
@ -113,13 +113,13 @@ nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TailCalls) {
|
if (TailCalls and targetParameterFootprint >= 0) {
|
||||||
if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) {
|
if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) {
|
||||||
offset += argumentFootprint(targetParameterFootprint)
|
offset += argumentFootprint(targetParameterFootprint)
|
||||||
- StackAlignmentInWords;
|
- StackAlignmentInWords;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for post-non-tail-call stack adjustment of the form "add
|
// check for post-non-tail-call stack adjustment of the form "sub
|
||||||
// sp, sp, #offset":
|
// sp, sp, #offset":
|
||||||
if ((*instruction >> 12) == 0xe24dd) {
|
if ((*instruction >> 12) == 0xe24dd) {
|
||||||
unsigned value = *instruction & 0xff;
|
unsigned value = *instruction & 0xff;
|
||||||
@ -292,7 +292,7 @@ class MyArchitecture: public Architecture {
|
|||||||
|
|
||||||
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
||||||
void* link, bool mostRecent,
|
void* link, bool mostRecent,
|
||||||
unsigned targetParameterFootprint, void** ip,
|
int targetParameterFootprint, void** ip,
|
||||||
void** stack)
|
void** stack)
|
||||||
{
|
{
|
||||||
arm::nextFrame(&con, static_cast<uint32_t*>(start), size, footprint, link,
|
arm::nextFrame(&con, static_cast<uint32_t*>(start), size, footprint, link,
|
||||||
|
@ -191,7 +191,7 @@ argumentFootprint(unsigned footprint)
|
|||||||
void
|
void
|
||||||
nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size,
|
nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size,
|
||||||
unsigned footprint, void* link, bool,
|
unsigned footprint, void* link, bool,
|
||||||
unsigned targetParameterFootprint, void** ip, void** stack)
|
int targetParameterFootprint, void** ip, void** stack)
|
||||||
{
|
{
|
||||||
assert(c, *ip >= start);
|
assert(c, *ip >= start);
|
||||||
assert(c, *ip <= start + (size / BytesPerWord));
|
assert(c, *ip <= start + (size / BytesPerWord));
|
||||||
@ -214,7 +214,7 @@ nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size,
|
|||||||
|
|
||||||
unsigned offset = footprint;
|
unsigned offset = footprint;
|
||||||
|
|
||||||
if (TailCalls) {
|
if (TailCalls and targetParameterFootprint >= 0) {
|
||||||
if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) {
|
if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) {
|
||||||
offset += argumentFootprint(targetParameterFootprint)
|
offset += argumentFootprint(targetParameterFootprint)
|
||||||
- StackAlignmentInWords;
|
- StackAlignmentInWords;
|
||||||
@ -391,7 +391,7 @@ class MyArchitecture: public Architecture {
|
|||||||
|
|
||||||
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
||||||
void* link, bool mostRecent,
|
void* link, bool mostRecent,
|
||||||
unsigned targetParameterFootprint, void** ip,
|
int targetParameterFootprint, void** ip,
|
||||||
void** stack)
|
void** stack)
|
||||||
{
|
{
|
||||||
powerpc::nextFrame(&c, static_cast<int32_t*>(start), size, footprint, link,
|
powerpc::nextFrame(&c, static_cast<int32_t*>(start), size, footprint, link,
|
||||||
|
@ -72,7 +72,7 @@ read4(uint8_t* p)
|
|||||||
void
|
void
|
||||||
nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED,
|
nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED,
|
||||||
unsigned footprint, void*, bool mostRecent,
|
unsigned footprint, void*, bool mostRecent,
|
||||||
unsigned targetParameterFootprint, void** ip, void** stack)
|
int targetParameterFootprint, void** ip, void** stack)
|
||||||
{
|
{
|
||||||
assert(c, *ip >= start);
|
assert(c, *ip >= start);
|
||||||
assert(c, *ip <= start + size);
|
assert(c, *ip <= start + size);
|
||||||
@ -114,13 +114,13 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED,
|
|||||||
|
|
||||||
unsigned offset = footprint + FrameHeaderSize - (mostRecent ? 1 : 0);
|
unsigned offset = footprint + FrameHeaderSize - (mostRecent ? 1 : 0);
|
||||||
|
|
||||||
if (TailCalls) {
|
if (TailCalls and targetParameterFootprint >= 0) {
|
||||||
if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) {
|
if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) {
|
||||||
offset += argumentFootprint(targetParameterFootprint)
|
offset += argumentFootprint(targetParameterFootprint)
|
||||||
- StackAlignmentInWords;
|
- StackAlignmentInWords;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for post-non-tail-call stack adjustment of the form "add
|
// check for post-non-tail-call stack adjustment of the form "sub
|
||||||
// $offset,%rsp":
|
// $offset,%rsp":
|
||||||
if (TargetBytesPerWord == 4) {
|
if (TargetBytesPerWord == 4) {
|
||||||
if ((*instruction == 0x83 or *instruction == 0x81)
|
if ((*instruction == 0x83 or *instruction == 0x81)
|
||||||
@ -141,6 +141,14 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED,
|
|||||||
|
|
||||||
// todo: check for and handle tail calls
|
// todo: check for and handle tail calls
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UseFramePointer and not mostRecent) {
|
||||||
|
assert(c, static_cast<void***>(*stack)[-1] + 1
|
||||||
|
== static_cast<void**>(*stack) + offset);
|
||||||
|
|
||||||
|
assert(c, static_cast<void***>(*stack)[-1][1]
|
||||||
|
== static_cast<void**>(*stack)[offset]);
|
||||||
|
}
|
||||||
|
|
||||||
*ip = static_cast<void**>(*stack)[offset];
|
*ip = static_cast<void**>(*stack)[offset];
|
||||||
*stack = static_cast<void**>(*stack) + offset;
|
*stack = static_cast<void**>(*stack) + offset;
|
||||||
@ -369,7 +377,7 @@ class MyArchitecture: public Architecture {
|
|||||||
|
|
||||||
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
||||||
void* link, bool mostRecent,
|
void* link, bool mostRecent,
|
||||||
unsigned targetParameterFootprint, void** ip,
|
int targetParameterFootprint, void** ip,
|
||||||
void** stack)
|
void** stack)
|
||||||
{
|
{
|
||||||
x86::nextFrame(&c, static_cast<uint8_t*>(start), size, footprint,
|
x86::nextFrame(&c, static_cast<uint8_t*>(start), size, footprint,
|
||||||
|
@ -1,5 +1,17 @@
|
|||||||
public class StackOverflow {
|
public class StackOverflow {
|
||||||
|
private static int add(int[] numbers, int offset, int length) {
|
||||||
|
if (length == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return numbers[offset] + add(numbers, offset + 1, length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static int add(int ... numbers) {
|
||||||
|
return add(numbers, 0, numbers.length);
|
||||||
|
}
|
||||||
|
|
||||||
private static int test1() {
|
private static int test1() {
|
||||||
|
add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
|
||||||
return test1() + 1;
|
return test1() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user