blob: 9ab83eeb0f74db0c3a526a9da2762d79ce8f33f5 [file] [log] [blame]
//===---------- JavaBacktrace.cpp - Backtrace utilities -------------------===//
//
// JnJVM
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdio.h>
#include <dlfcn.h>
#include "llvm/Function.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "mvm/JIT.h"
#include "mvm/Method.h"
#include "mvm/Object.h"
#include "JavaClass.h"
#include "JavaJIT.h"
#include "JavaThread.h"
#include "Jnjvm.h"
#include "JnjvmModuleProvider.h"
using namespace jnjvm;
extern "C" int** get_frame_pointer() {
/*
int** fp = 0;
#if defined (__PPC__)
asm volatile("1:\n"
" mr %0, 1\n"
: "=&r"(fp));
#else
asm volatile("1:\n"
" movl %%ebp, %0\n"
: "=&r"(fp));
#endif
return fp;
*/
return (int**)__builtin_frame_address(0);
}
extern "C" int *debug_frame_ip(int **fp) {
#if defined(__MACH__) && !defined(__i386__)
return fp[2];
#else
return fp[1];
#endif
}
extern "C" int **debug_frame_caller_fp(int **fp) {
return (int**)fp[0];
}
extern "C" int **debug_frame_caller_from_first_fp(int **fp) {
#if defined (__PPC__)
return fp;
#else
return fp;
#endif
}
extern "C" bool frame_end(int **fp) {
#if defined(__PPC__)
return fp == 0;
#else
return fp == 0;
#endif
}
extern "C" JavaMethod* ip_to_meth(int* begIp) {
if (begIp) {
const llvm::GlobalValue * glob =
mvm::jit::executionEngine->getGlobalValueAtAddress(begIp + 1);
if (glob) {
if (llvm::isa<llvm::Function>(glob)) {
mvm::Code* c = (mvm::Code*)begIp;
mvm::Method* m = c->method();
JavaMethod* meth = (JavaMethod*)m->definition();
if (meth && meth->getVirtualTable() == JavaMethod::VT) {
return meth;
}
}
}
}
return 0;
}
#if 0
extern "C" int backtrace(void** ips, int size) {
int** fp = get_frame_pointer();
fp = debug_frame_caller_from_first_fp(fp);
int i = 0;
while ((!frame_end(fp)) && (debug_frame_ip(fp) != 0) && i < size) {
int * ip = debug_frame_ip(fp);
ips[i++] = (void*)ip;
fp = debug_frame_caller_fp(fp);
}
return i;
}
#else
#include <execinfo.h>
#endif
extern "C" int backtrace_fp(int** ips, int size, int** fp) {
fp = debug_frame_caller_from_first_fp(fp);
int i = 0;
while ((!frame_end(fp)) && (debug_frame_ip(fp) != 0) && i < size) {
int * ip = debug_frame_ip(fp);
ips[i++] = ip;
fp = debug_frame_caller_fp(fp);
}
return i;
}
extern "C" void debug_backtrace(int **fp) {
fp = debug_frame_caller_from_first_fp(fp);
while ((!frame_end(fp)) && (debug_frame_ip(fp) != 0)) {
int * ip = debug_frame_ip(fp);
int *begIp = (int*)gc::begOf(ip);
if (begIp) {
const llvm::GlobalValue * glob =
mvm::jit::executionEngine->getGlobalValueAtAddress(begIp + 1);
if (glob) {
if (llvm::isa<llvm::Function>(glob)) {
printf("; 0x%08x in %s\n", (uint32) ip,
((llvm::Function*)glob)->getNameStr().c_str());
} else JavaThread::get()->isolate->unknownError("in global variable?");
} else printf("; 0x%08x in stub\n", (uint32) ip);
} else {
Dl_info info;
int res = dladdr(begIp, &info);
if (res != 0) {
printf("; 0x%08x in %s\n", (uint32) ip, info.dli_fname);
}
}
fp = debug_frame_caller_fp(fp);
}
}
void JavaJIT::printBacktrace() {
int* ips[100];
int real_size = backtrace((void**)(void*)ips, 100);
int n = 0;
while (n < real_size) {
int *begIp = (int*)gc::begOf(ips[n++]);
if (begIp) {
const llvm::GlobalValue * glob =
mvm::jit::executionEngine->getGlobalValueAtAddress(begIp + 1);
if (glob) {
if (llvm::isa<llvm::Function>(glob)) {
mvm::Code* c = (mvm::Code*)begIp;
mvm::Method* m = c->method();
JavaMethod* meth = (JavaMethod*)m->definition();
if (meth)
printf("; 0x%08x in %s\n", (uint32) ips[n - 1], meth->printString());
else
printf("; 0x%08x in %s\n", (uint32) ips[n - 1], ((llvm::Function*)glob)->getNameStr().c_str());
} else JavaThread::get()->isolate->unknownError("in global variable?");
} else printf("; 0x%08x in stub\n", (uint32) ips[n - 1]);
} else {
Dl_info info;
int res = dladdr(begIp, &info);
if (res != 0) {
printf("; 0x%08x in %s\n", (uint32) ips[n - 1], info.dli_fname);
} else {
printf("; 0x%08x in Unknown\n", (uint32) ips[n - 1]);
}
}
}
}
Class* JavaJIT::getCallingClass() {
int* ips[10];
int real_size = backtrace((void**)(void*)ips, 10);
int n = 0;
int i = 0;
while (n < real_size) {
int *begIp = (int*)gc::begOf(ips[n++]);
if (begIp) {
const llvm::GlobalValue * glob =
mvm::jit::executionEngine->getGlobalValueAtAddress(begIp + 1);
if (glob) {
if (llvm::isa<llvm::Function>(glob)) {
mvm::Code* c = (mvm::Code*)begIp;
mvm::Method* m = c->method();
JavaMethod* meth = (JavaMethod*)m->definition();
if (meth && i == 1) return meth->classDef;
else ++i;
} else {
JavaThread::get()->isolate->unknownError("in global variable?");
}
}
}
}
return 0;
}
Class* JavaJIT::getCallingClassWalker() {
int* ips[10];
int real_size = backtrace((void**)(void*)ips, 10);
int n = 0;
int i = 0;
while (n < real_size) {
int *begIp = (int*)gc::begOf(ips[n++]);
if (begIp) {
const llvm::GlobalValue * glob =
mvm::jit::executionEngine->getGlobalValueAtAddress(begIp + 1);
if (glob) {
if (llvm::isa<llvm::Function>(glob)) {
mvm::Code* c = (mvm::Code*)begIp;
mvm::Method* m = c->method();
JavaMethod* meth = (JavaMethod*)m->definition();
if (meth && i == 1) {
return meth->classDef;
} else ++i;
} else {
JavaThread::get()->isolate->unknownError("in global variable?");
}
}
}
}
return 0;
}
JavaObject* JavaJIT::getCallingClassLoader() {
Class* cl = getCallingClassWalker();
if (!cl) return 0;
else return cl->classLoader;
}