Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dump EmittedFunctionDetails to sysimage #6490

Merged
merged 2 commits into from
Apr 16, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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