Permalink
Browse files

added preliminary support for backtracing/symbolication

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@2562 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information...
1 parent f04bc1d commit 2541db33e6c4c12e3c92db0f2a3545e266755352 @lrz lrz committed Sep 18, 2009
Showing with 92 additions and 12 deletions.
  1. +14 −0 compiler.cpp
  2. +19 −0 compiler.h
  3. +57 −11 vm.cpp
  4. +2 −1 vm.h
View
@@ -20,9 +20,13 @@
extern "C" const char *ruby_node_name(int node);
+// Will be set later, in vm.cpp.
llvm::Module *RoxorCompiler::module = NULL;
RoxorCompiler *RoxorCompiler::shared = NULL;
+AnnotationID RoxorFunctionAnnotation::id =
+ AnnotationManager::getID("RoxorFunction");
+
RoxorCompiler::RoxorCompiler(void)
{
fname = NULL;
@@ -128,6 +132,8 @@ RoxorCompiler::RoxorCompiler(void)
setCurrentClassFunc = NULL;
getCacheFunc = NULL;
+ func_annotation = NULL;
+
#if __LP64__
RubyObjTy = IntTy = Type::Int64Ty;
#else
@@ -730,6 +736,9 @@ RoxorCompiler::compile_dispatch_call(std::vector<Value *> &params)
(module->getOrInsertFunction("rb_vm_dispatch", ft));
}
+ assert(func_annotation != NULL);
+ func_annotation->dispatch_lines.push_back(current_line);
+
return compile_protected_call(dispatcherFunc, params);
}
@@ -2944,6 +2953,7 @@ RoxorCompiler::compile_node(NODE *node)
}
printf("... %s\n", ruby_node_name(nd_type(node)));
#endif
+ current_line = nd_line(node);
switch (nd_type(node)) {
case NODE_SCOPE:
@@ -2985,6 +2995,9 @@ RoxorCompiler::compile_node(NODE *node)
Function *f = Function::Create(ft, GlobalValue::PrivateLinkage,
"", module);
+ RoxorFunctionAnnotation *old_func_annotation = func_annotation;
+ func_annotation = new RoxorFunctionAnnotation(f, fname);
+
BasicBlock *old_rescue_bb = rescue_bb;
BasicBlock *old_entry_bb = entry_bb;
BasicBlock *old_bb = bb;
@@ -3205,6 +3218,7 @@ RoxorCompiler::compile_node(NODE *node)
rescue_bb->eraseFromParent();
}
+ func_annotation = old_func_annotation;
bb = old_bb;
entry_bb = old_entry_bb;
lvars = old_lvars;
View
@@ -27,6 +27,23 @@
#define DEFINED_SUPER 6
#define DEFINED_METHOD 7
+class RoxorFunctionAnnotation : public Annotation {
+ public:
+ static AnnotationID id;
+ std::string path;
+ std::vector<unsigned int> dispatch_lines;
+
+ RoxorFunctionAnnotation(Function *function, const char *_path)
+ : Annotation(RoxorFunctionAnnotation::id), path(_path) {
+ function->addAnnotation(this);
+ }
+
+ static RoxorFunctionAnnotation *from_function(Function *function) {
+ return (RoxorFunctionAnnotation *)
+ function->getAnnotation(RoxorFunctionAnnotation::id);
+ }
+};
+
class RoxorCompiler {
public:
static llvm::Module *module;
@@ -81,6 +98,7 @@ class RoxorCompiler {
# define DEBUG_LEVEL_DEC()
#endif
+ unsigned int current_line;
BasicBlock *bb;
BasicBlock *entry_bb;
ID current_mid;
@@ -108,6 +126,7 @@ class RoxorCompiler {
int return_from_block;
int return_from_block_ids;
PHINode *ensure_pn;
+ RoxorFunctionAnnotation *func_annotation;
Function *dispatcherFunc;
Function *fastPlusFunc;
View
68 vm.cpp
@@ -406,8 +406,8 @@ RoxorCore::interpret(Function *func)
}
bool
-RoxorCore::symbolize_call_address(void *addr, void **startp, unsigned long *ln,
- char *name, size_t name_len)
+RoxorCore::symbolize_call_address(void *addr, void **startp, char *path,
+ size_t path_len, unsigned long *ln, char *name, size_t name_len)
{
void *start = NULL;
@@ -429,7 +429,7 @@ RoxorCore::symbolize_call_address(void *addr, void **startp, unsigned long *ln,
*startp = start;
}
- if (name != NULL || ln != NULL) {
+ if (name != NULL || path != NULL || ln != NULL) {
std::map<IMP, rb_vm_method_node_t *>::iterator iter =
ruby_imps.find((IMP)start);
if (iter == ruby_imps.end()) {
@@ -438,11 +438,56 @@ RoxorCore::symbolize_call_address(void *addr, void **startp, unsigned long *ln,
}
rb_vm_method_node_t *node = iter->second;
-#if 0 // TODO
+
+ RoxorFunctionAnnotation *annotation = f == NULL
+ ? NULL
+ : RoxorFunctionAnnotation::from_function(f->f);
if (ln != NULL) {
- *ln = nd_line(node->node);
- }
+ if (annotation != NULL) {
+#if __LP64__
+ // So, we need to determine here which call to the dispatcher
+ // we are exactly, so that we can retrieve the appropriate
+ // line number from the annotation.
+ // Unfortunately, the only way to achieve that seems to scan
+ // the current function's machine code.
+ // This code has only been tested on x86_64 but could be
+ // easily ported to i386.
+ const uint32_t sym = *(uint32_t *)((unsigned char *)addr - 8);
+ const int sentinel = sym & 0xff;
+
+ unsigned char *p = f->start;
+ unsigned int i = 0;
+ while ((p = (unsigned char *)memchr(p, sentinel,
+ (unsigned char *)addr - p)) != NULL) {
+ if (*(uint32_t *)p == sym) {
+ i++;
+ }
+ p++;
+ }
+
+ if (i > 0 && i - 1 < annotation->dispatch_lines.size()) {
+ *ln = annotation->dispatch_lines[i - 1];
+ }
+ else {
+ *ln = 0;
+ }
+#else
+ // TODO 32-bit hack...
+ *ln = 0;
#endif
+ }
+ else {
+ *ln = 0;
+ }
+ }
+ if (path != NULL) {
+ if (annotation != NULL) {
+ strncpy(path, annotation->path.c_str(), path_len);
+ }
+ else {
+ strncpy(path, "core", path_len);
+ }
+ }
if (name != NULL) {
strncpy(name, sel_getName(node->sel), name_len);
}
@@ -2329,7 +2374,7 @@ rb_vm_super_lookup(VALUE klass, SEL sel)
for (int i = callstack_n - 1; i >= 0; i--) {
void *start = NULL;
if (GET_CORE()->symbolize_call_address(callstack[i],
- &start, NULL, NULL, 0)) {
+ &start, NULL, 0, NULL, NULL, 0)) {
start = (void *)objc_imp((IMP)start);
if (start == (void *)self) {
skip = false;
@@ -4507,13 +4552,14 @@ rb_vm_backtrace(int level)
VALUE ary = rb_ary_new();
for (int i = 0; i < callstack_n; i++) {
+ char path[PATH_MAX];
char name[100];
unsigned long ln = 0;
- if (GET_CORE()->symbolize_call_address(callstack[i], NULL, &ln, name,
- sizeof name)) {
- char entry[100];
- snprintf(entry, sizeof entry, "%ld:in `%s'", ln, name);
+ if (GET_CORE()->symbolize_call_address(callstack[i], NULL,
+ path, sizeof path, &ln, name, sizeof name)) {
+ char entry[PATH_MAX];
+ snprintf(entry, sizeof entry, "%s:%ld:in `%s'", path, ln, name);
rb_ary_push(ary, rb_str_new2(entry));
}
}
View
3 vm.h
@@ -670,7 +670,8 @@ class RoxorCore {
}
bool symbolize_call_address(void *addr, void **startp,
- unsigned long *ln, char *name, size_t name_len);
+ char *path, size_t path_len, unsigned long *ln,
+ char *name, size_t name_len);
struct mcache *method_cache_get(SEL sel, bool super);
rb_vm_method_node_t *method_node_get(IMP imp);

0 comments on commit 2541db3

Please sign in to comment.