Skip to content

Commit

Permalink
Merge pull request #6490 from ihnorton/dump_linedebug
Browse files Browse the repository at this point in the history
Dump EmittedFunctionDetails to sysimage
  • Loading branch information
ihnorton committed Apr 16, 2014
2 parents eeb6ab1 + 05a5109 commit c77e098
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 14 deletions.
109 changes: 101 additions & 8 deletions src/debuginfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
struct FuncInfo{
const Function* func;
size_t lengthAdr;
std::string name;
std::string filename;
#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
PRUNTIME_FUNCTION fnentry;
#endif
Expand Down Expand Up @@ -66,9 +68,10 @@ class JuliaJITEventListener: public JITEventListener
}
}
jl_in_stackwalk = 0;
FuncInfo tmp = {&F, Size, tbl, Details.LineStarts};

FuncInfo tmp = {&F, Size, std::string(), std::string(), tbl, Details.LineStarts};
#else
FuncInfo tmp = {&F, Size, Details.LineStarts};
FuncInfo tmp = {&F, Size, std::string(), std::string(), Details.LineStarts};
#endif
if (tmp.lines.size() != 0) info[(size_t)(Code)] = tmp;
}
Expand Down Expand Up @@ -104,12 +107,17 @@ void jl_getFunctionInfo(const char **name, int *line, const char **filename, siz
std::vector<JITEvent_EmittedFunctionDetails::LineStart>::iterator vit = (*it).second.lines.begin();
JITEvent_EmittedFunctionDetails::LineStart prev = *vit;

DISubprogram debugscope =
DISubprogram(prev.Loc.getScope((*it).second.func->getContext()));
*filename = debugscope.getFilename().data();
// the DISubprogram has the un-mangled name, so use that if
// available.
*name = debugscope.getName().data();
if ((*it).second.func) {
DISubprogram debugscope =
DISubprogram(prev.Loc.getScope((*it).second.func->getContext()));
*filename = debugscope.getFilename().data();
// the DISubprogram has the un-mangled name, so use that if
// available.
*name = debugscope.getName().data();
} else {
*name = (*it).second.name.c_str();
*filename = (*it).second.filename.c_str();
}

vit++;

Expand Down Expand Up @@ -249,3 +257,88 @@ extern "C" void jl_write_coverage_data(void)
}
}
}

#ifndef _OS_WINDOWS_
typedef std::map<size_t, FuncInfo, revcomp> FuncInfoMap;
extern "C" void jl_dump_linedebug_info() {
FuncInfoMap info = jl_jit_events->getMap();
FuncInfoMap::iterator infoiter = info.begin();
std::vector<JITEvent_EmittedFunctionDetails::LineStart>::iterator lineiter = (*infoiter).second.lines.begin();

Type *li_types[2] = {T_size, T_size};
StructType *T_lineinfo = StructType::get(jl_LLVMContext, ArrayRef<Type *>(std::vector<Type *>(li_types, li_types+2)), true);

std::vector<Constant *> funcinfo_array;
funcinfo_array.push_back( ConstantInt::get(T_size, 0) );

for (; infoiter != info.end(); infoiter++) {
std::vector<Constant*> functionlines;

// get the base address for offset calculation
size_t fptr = (size_t)(*infoiter).first;

lineiter = (*infoiter).second.lines.begin();
JITEvent_EmittedFunctionDetails::LineStart prev = *lineiter;

// loop over the EmittedFunctionDetails vector
while (lineiter != (*infoiter).second.lines.end()) {
// store the individual {offset, line} entries
Constant* tmpline[2] = { ConstantInt::get(T_size, (*lineiter).Address - fptr),
ConstantInt::get(T_size, (*lineiter).Loc.getLine()) };
Constant *lineinfo = ConstantStruct::get(T_lineinfo, makeArrayRef(tmpline));
functionlines.push_back(lineinfo);
lineiter++;
}

DISubprogram debugscope =
DISubprogram(prev.Loc.getScope((*infoiter).second.func->getContext()));

Constant *info_data[6] = { ConstantExpr::getBitCast( const_cast<Function *>((*infoiter).second.func), T_psize),
ConstantDataArray::getString( jl_LLVMContext, StringRef(debugscope.getName().str())),
ConstantDataArray::getString( jl_LLVMContext, StringRef(debugscope.getFilename().str())),
ConstantInt::get(T_size, (*infoiter).second.lengthAdr),
ConstantInt::get(T_size, functionlines.size()),
ConstantArray::get(ArrayType::get(T_lineinfo, functionlines.size()), ArrayRef<Constant *>(functionlines))
};
Constant *st = ConstantStruct::getAnon(jl_LLVMContext, ArrayRef<Constant *>(info_data), true);
funcinfo_array.push_back( st );
}
// set first element to the total number of FuncInfo entries
funcinfo_array[0] = ConstantInt::get(T_size, funcinfo_array.size() - 1);
Constant *st_lineinfo = ConstantStruct::getAnon( jl_LLVMContext, ArrayRef<Constant*>(funcinfo_array), true );
new GlobalVariable(
*jl_Module,
st_lineinfo->getType(),
true,
GlobalVariable::ExternalLinkage,
st_lineinfo,
"jl_linedebug_info");
}

extern "C" void jl_restore_linedebug_info(uv_lib_t *handle) {
uintptr_t *infoptr = (uintptr_t*)jl_dlsym(handle, const_cast<char*>("jl_linedebug_info"));
size_t funccount = (size_t)(*infoptr++);

for (size_t i = 0; i < funccount; i++) {
uintptr_t fptr = (*infoptr++);
char *name = (char*)infoptr;
infoptr = (uintptr_t*)(((char*)infoptr) + strlen( (const char*)infoptr) + 1);
char *filename = (char*)infoptr;
infoptr = (uintptr_t*)(((char*)infoptr) + strlen( (const char*)infoptr) + 1);
size_t lengthAdr = (*infoptr++);
size_t numel = (*infoptr++);

std::vector<JITEvent_EmittedFunctionDetails::LineStart> linestarts;

for (size_t j = 0; j < numel; j++) {
// dummy element for the MDNode, which we need so that the DebucLoc keeps info
SmallVector <Value *, 1> tmpelt;
JITEvent_EmittedFunctionDetails::LineStart linestart =
{ (uintptr_t)fptr + (*infoptr++), DebugLoc::get( (*infoptr++), 0, MDNode::get(jl_LLVMContext, tmpelt) ) };
linestarts.push_back(linestart);
}
FuncInfo info = { NULL, lengthAdr, std::string(name), std::string(filename), linestarts };
jl_jit_events->getMap()[(size_t)fptr] = info;
}
}
#endif
17 changes: 11 additions & 6 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,24 +104,25 @@ jl_value_t ***sysimg_gvars = NULL;
extern int globalUnique;
extern void jl_cpuid(int32_t CPUInfo[4], int32_t InfoType);
extern const char *jl_cpu_string;
uv_lib_t *jl_sysimg_handle = NULL;

static void jl_load_sysimg_so(char *fname)
{
// attempt to load the pre-compiled sysimg at fname
// if this succeeds, sysimg_gvars will be a valid array
// otherwise, it will be NULL
uv_lib_t *sysimg_handle = jl_load_dynamic_library_e(fname, JL_RTLD_DEFAULT | JL_RTLD_GLOBAL);
if (sysimg_handle != 0) {
sysimg_gvars = (jl_value_t***)jl_dlsym(sysimg_handle, "jl_sysimg_gvars");
globalUnique = *(size_t*)jl_dlsym(sysimg_handle, "jl_globalUnique");
const char *cpu_target = (const char*)jl_dlsym(sysimg_handle, "jl_sysimg_cpu_target");
jl_sysimg_handle = jl_load_dynamic_library_e(fname, JL_RTLD_DEFAULT | JL_RTLD_GLOBAL);
if (jl_sysimg_handle != 0) {
sysimg_gvars = (jl_value_t***)jl_dlsym(jl_sysimg_handle, "jl_sysimg_gvars");
globalUnique = *(size_t*)jl_dlsym(jl_sysimg_handle, "jl_globalUnique");
const char *cpu_target = (const char*)jl_dlsym(jl_sysimg_handle, "jl_sysimg_cpu_target");
if (strcmp(cpu_target,jl_cpu_string) != 0)
jl_error("Julia and the system image were compiled for different architectures.\n"
"Please delete or regenerate sys.{so,dll,dylib}.");
uint32_t info[4];
jl_cpuid((int32_t*)info, 1);
if (strcmp(cpu_target, "native") == 0) {
uint64_t saved_cpuid = *(uint64_t*)jl_dlsym(sysimg_handle, "jl_sysimg_cpu_cpuid");
uint64_t saved_cpuid = *(uint64_t*)jl_dlsym(jl_sysimg_handle, "jl_sysimg_cpu_cpuid");
if (saved_cpuid != (((uint64_t)info[2])|(((uint64_t)info[3])<<32)))
jl_error("Target architecture mismatch. Please delete or regenerate sys.{so,dll,dylib}.");
}
Expand Down Expand Up @@ -1103,6 +1104,10 @@ void jl_restore_system_image(char *fname)
jl_get_binding_wr(jl_core_module, jl_symbol("JULIA_HOME"))->value =
jl_cstr_to_string(julia_home);
jl_update_all_fptrs();
#ifndef _OS_WINDOWS_
// restore the line information for Julia backtraces
if (jl_sysimg_handle != NULL) jl_restore_linedebug_info(jl_sysimg_handle);
#endif
}

void jl_init_restored_modules()
Expand Down
3 changes: 3 additions & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,9 @@ DLLEXPORT int julia_trampoline(int argc, char **argv, int (*pmain)(int ac,char *
free(build_ji);
char *build_o;
if (asprintf(&build_o, "%s.o",build_path) > 0) {
#ifndef _OS_WINDOWS_
jl_dump_linedebug_info();
#endif
jl_dump_objfile(build_o,0);
free(build_o);
}
Expand Down
5 changes: 5 additions & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ DLLEXPORT size_t rec_backtrace_ctx(ptrint_t *data, size_t maxsize, bt_context_t
size_t rec_backtrace_ctx_dwarf(ptrint_t *data, size_t maxsize, bt_context_t ctx);
#endif

#ifndef _OS_WINDOWS_
DLLEXPORT void jl_dump_linedebug_info();
DLLEXPORT void jl_restore_linedebug_info(uv_lib_t* handle);
#endif

#ifdef __cplusplus
}
#endif
Expand Down

0 comments on commit c77e098

Please sign in to comment.