JL_DLLEXPORT jl_value_t *jl_lookup_code_address(void *ip, int skipC) { jl_ptls_t ptls = jl_get_ptls_states(); jl_frame_t *frames = NULL; int8_t gc_state = jl_gc_safe_enter(ptls); int n = jl_getFunctionInfo(&frames, (uintptr_t)ip, skipC, 0); jl_gc_safe_leave(ptls, gc_state); jl_value_t *rs = (jl_value_t*)jl_alloc_svec(n); JL_GC_PUSH1(&rs); for (int i = 0; i < n; i++) { jl_frame_t frame = frames[i]; jl_value_t *r = (jl_value_t*)jl_alloc_svec(7); jl_svecset(rs, i, r); if (frame.func_name) jl_svecset(r, 0, jl_symbol(frame.func_name)); else jl_svecset(r, 0, empty_sym); free(frame.func_name); if (frame.file_name) jl_svecset(r, 1, jl_symbol(frame.file_name)); else jl_svecset(r, 1, empty_sym); free(frame.file_name); jl_svecset(r, 2, jl_box_long(frame.line)); jl_svecset(r, 3, frame.linfo != NULL ? (jl_value_t*)frame.linfo : jl_nothing); jl_svecset(r, 4, jl_box_bool(frame.fromC)); jl_svecset(r, 5, jl_box_bool(frame.inlined)); jl_svecset(r, 6, jl_box_long((intptr_t)ip)); } free(frames); JL_GC_POP(); return rs; }
//for looking up functions from gdb: JL_DLLEXPORT void jl_gdblookup(uintptr_t ip) { // This function is not allowed to reference any TLS variables since // it can be called from an unmanaged thread on OSX. // it means calling getFunctionInfo with noInline = 1 jl_frame_t *frames = NULL; int n = jl_getFunctionInfo(&frames, ip, 0, 0); int i; for (i = 0; i < n; i++) { jl_frame_t frame = frames[i]; if (!frame.func_name) { jl_safe_printf("unknown function (ip: %p)\n", (void*)ip); } else { const char *inlined = frame.inlined ? " [inlined]" : ""; if (frame.line != -1) { jl_safe_printf("%s at %s:%" PRIuPTR "%s\n", frame.func_name, frame.file_name, (uintptr_t)frame.line, inlined); } else { jl_safe_printf("%s at %s (unknown line)%s\n", frame.func_name, frame.file_name, inlined); } free(frame.func_name); free(frame.file_name); } } free(frames); }
// Always Set *func_name and *file_name to malloc'd pointers (non-NULL) static int frame_info_from_ip(char **func_name, char **file_name, size_t *line_num, char **inlinedat_file, size_t *inlinedat_line, jl_lambda_info_t **outer_linfo, size_t ip, int skipC, int skipInline) { // This function is not allowed to reference any TLS variables since // it can be called from an unmanaged thread on OSX. static const char *name_unknown = "???"; int fromC = 0; jl_getFunctionInfo(func_name, file_name, line_num, inlinedat_file, inlinedat_line, outer_linfo, ip, &fromC, skipC, skipInline); if (!*func_name) { *func_name = strdup(name_unknown); *line_num = ip; } if (!*file_name) { *file_name = strdup(name_unknown); } return fromC; }