blob: 3dde18c2c5c665ab72b11e9e70e14dfb994d13a4 [file] [log] [blame]
//===- ClasspathVMClassLoader.cpp - GNU classpath java/lang/VMClassLoader -===//
//
// JnJVM
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <string.h>
#include "llvm/Type.h"
#include "types.h"
#include "JavaAccess.h"
#include "JavaArray.h"
#include "JavaClass.h"
#include "JavaConstantPool.h"
#include "JavaJIT.h"
#include "JavaObject.h"
#include "JavaString.h"
#include "JavaTypes.h"
#include "JavaThread.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
#include "NativeUtil.h"
#include "Reader.h"
#include <execinfo.h>
using namespace jnjvm;
extern "C" int backtrace_fp(int** ips, int size, int**);
extern "C" JavaMethod* ip_to_meth(int* ip);
extern "C" {
JNIEXPORT jobject JNICALL Java_java_lang_VMThrowable_fillInStackTrace(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
jobject throwable) {
//int** fp = (int**)__builtin_frame_address(0);
int** stack = (int**)alloca(sizeof(int*) * 100);
int real_size = backtrace((void**)stack, 100);
ArrayUInt32* obj = ArrayUInt32::acons(real_size, JavaArray::ofInt);
memcpy(obj->elements, stack, real_size * sizeof(int));
JavaObject* vmThrowable = (*Classpath::newVMThrowable)();
Classpath::initVMThrowable->invokeIntSpecial(vmThrowable);
(*Classpath::vmDataVMThrowable)(vmThrowable, obj);
return (jobject)vmThrowable;
}
JavaObject* consStackElement(JavaMethod* meth, int* ip) {
Jnjvm* vm = JavaThread::get()->isolate;
JavaObject* methodName = vm->UTF8ToStr(meth->name);
Class* cl = meth->classDef;
JavaObject* className = vm->UTF8ToStr(cl->name->internalToJava(vm, 0, cl->name->size));
JavaObject* sourceName = 0;
Attribut* sourceAtt = Attribut::lookup(&cl->attributs,
Attribut::sourceFileAttribut);
if (sourceAtt) {
Reader* reader = sourceAtt->toReader(cl->bytes, sourceAtt);
uint16 index = reader->readU2();
sourceName = vm->UTF8ToStr(cl->ctpInfo->UTF8At(index));
}
bool native = isNative(meth->access);
JavaObject* res = (*Classpath::newStackTraceElement)();
Classpath::initStackTraceElement->invokeIntSpecial(res, sourceName, (int)ip, className, methodName, native);
return res;
}
ArrayObject* recGetStackTrace(int** stack, uint32 size, uint32 first, uint32 rec) {
if (size != first) {
int *begIp = (int*)gc::begOf(stack[first]);
JavaMethod* meth = ip_to_meth(begIp);
if (meth) {
ArrayObject* res = recGetStackTrace(stack, size, first + 1, rec + 1);
res->setAt(rec, consStackElement(meth, stack[first]));
return res;
} else {
return recGetStackTrace(stack, size, first + 1, rec);
}
} else {
return ArrayObject::acons(rec, JavaArray::ofObject);
}
}
JNIEXPORT jobject JNICALL Java_java_lang_VMThrowable_getStackTrace(
#ifdef NATIVE_JNI
JNIEnv *env,
#endif
jobject vmthrow, jobject throwable) {
ArrayUInt32* array = (ArrayUInt32*)(*Classpath::vmDataVMThrowable)((JavaObject*)vmthrow).PointerVal;
uint32* stack = array->elements;
CommonClass* cl = ((JavaObject*)throwable)->classOf;
uint32 first = 0;
sint32 i = 0;
while (i < array->size) {
int *begIp = (int*)gc::begOf((void*)stack[i++]);
JavaMethod* meth = ip_to_meth(begIp);
if (meth && meth->classDef == cl) {
first = i;
break;
}
}
return (jobject)recGetStackTrace((int**)(uint32**)stack, array->size, first, 0);
}
}