handle virtual thunk case in MyProcessor::getStackTrace

If we catch the target thread in a virtual thunk when getting its
stack trace, we must assume its Thread::stack field is garbage and use
the register values instead.  Previously, we treated these thunks as
any other native code, leading to crashes when we tried to use the
garbage pointer.
This commit is contained in:
Joel Dice 2010-07-06 16:13:11 -06:00
parent 0817f4e0da
commit 1f8130f566

View File

@ -7194,6 +7194,9 @@ class SegFaultHandler: public System::SignalHandler {
bool
isThunk(MyThread* t, void* ip);
bool
isVirtualThunk(MyThread* t, void* ip);
bool
isThunkUnsafeStack(MyThread* t, void* ip);
@ -7579,14 +7582,17 @@ class MyProcessor: public Processor {
c.ip = 0;
c.base = 0;
c.stack = 0;
} else if (target->stack and (not isThunkUnsafeStack(t, ip))) {
} else if (target->stack
and (not isThunkUnsafeStack(t, ip))
and (not isVirtualThunk(t, ip)))
{
// we caught the thread in a thunk or native code, and the
// saved stack and base pointers indicate the most recent
// Java frame on the stack
c.ip = t->arch->frameIp(target->stack);
c.base = target->base;
c.stack = target->stack;
} else if (isThunk(t, ip)) {
} else if (isThunk(t, ip) or isVirtualThunk(t, ip)) {
// we caught the thread in a thunk where the stack and base
// registers indicate the most recent Java frame on the
// stack
@ -7822,6 +7828,25 @@ isThunkUnsafeStack(MyProcessor::ThunkCollection* thunks, void* ip)
return false;
}
bool
isVirtualThunk(MyThread* t, void* ip)
{
MyProcessor* p = processor(t);
for (unsigned i = 0; i < wordArrayLength(t, p->virtualThunks); i += 2) {
uintptr_t start = wordArrayBody(t, p->virtualThunks, i);
uintptr_t end = start + wordArrayBody(t, p->virtualThunks, i + 1);
if (reinterpret_cast<uintptr_t>(ip) >= start
and reinterpret_cast<uintptr_t>(ip) < end)
{
return true;
}
}
return false;
}
bool
isThunkUnsafeStack(MyThread* t, void* ip)
{
@ -8138,7 +8163,7 @@ fixupVirtualThunks(MyThread* t, BootImage* image, uint8_t* code)
{
MyProcessor* p = processor(t);
for (unsigned i = 0; i < wordArrayLength(t, p->virtualThunks); ++i) {
for (unsigned i = 0; i < wordArrayLength(t, p->virtualThunks); i += 2) {
if (wordArrayBody(t, p->virtualThunks, i)) {
wordArrayBody(t, p->virtualThunks, i)
= (wordArrayBody(t, p->virtualThunks, i) - image->codeBase)
@ -8531,7 +8556,7 @@ unresolved(MyThread* t, uintptr_t methodAddress)
}
uintptr_t
compileVirtualThunk(MyThread* t, unsigned index)
compileVirtualThunk(MyThread* t, unsigned index, unsigned* size)
{
Context context(t);
Assembler* a = context.assembler;
@ -8548,12 +8573,13 @@ compileVirtualThunk(MyThread* t, unsigned index)
a->endBlock(false)->resolve(0, 0);
uint8_t* start = static_cast<uint8_t*>
(codeAllocator(t)->allocate(a->length()));
*size = a->length();
uint8_t* start = static_cast<uint8_t*>(codeAllocator(t)->allocate(*size));
a->writeTo(start);
logCompile(t, start, a->length(), 0, "virtualThunk", 0);
logCompile(t, start, *size, 0, "virtualThunk", 0);
return reinterpret_cast<uintptr_t>(start);
}
@ -8563,8 +8589,10 @@ virtualThunk(MyThread* t, unsigned index)
{
MyProcessor* p = processor(t);
if (p->virtualThunks == 0 or wordArrayLength(t, p->virtualThunks) <= index) {
object newArray = makeWordArray(t, nextPowerOfTwo(index + 1));
if (p->virtualThunks == 0
or wordArrayLength(t, p->virtualThunks) <= index * 2)
{
object newArray = makeWordArray(t, nextPowerOfTwo((index + 1) * 2));
if (p->virtualThunks) {
memcpy(&wordArrayBody(t, newArray, 0),
&wordArrayBody(t, p->virtualThunks, 0),
@ -8573,16 +8601,18 @@ virtualThunk(MyThread* t, unsigned index)
p->virtualThunks = newArray;
}
if (wordArrayBody(t, p->virtualThunks, index) == 0) {
if (wordArrayBody(t, p->virtualThunks, index * 2) == 0) {
ACQUIRE(t, t->m->classLock);
if (wordArrayBody(t, p->virtualThunks, index) == 0) {
uintptr_t thunk = compileVirtualThunk(t, index);
wordArrayBody(t, p->virtualThunks, index) = thunk;
if (wordArrayBody(t, p->virtualThunks, index * 2) == 0) {
unsigned size;
uintptr_t thunk = compileVirtualThunk(t, index, &size);
wordArrayBody(t, p->virtualThunks, index * 2) = thunk;
wordArrayBody(t, p->virtualThunks, (index * 2) + 1) = size;
}
}
return wordArrayBody(t, p->virtualThunks, index);
return wordArrayBody(t, p->virtualThunks, index * 2);
}
void