Skip to content

Commit

Permalink
probably fix #5867. for some reason, debug info of libjulia-debug is …
Browse files Browse the repository at this point in the history
…broken for me right now, so this only works for libjulia-release
  • Loading branch information
vtjnash authored and Julia Windows Test Machine committed Mar 29, 2014
1 parent 2ff18f0 commit 9f68899
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 21 deletions.
46 changes: 40 additions & 6 deletions src/debuginfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
struct FuncInfo{
const Function* func;
size_t lengthAdr;
#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
PRUNTIME_FUNCTION fnentry;
#endif
std::vector<JITEvent_EmittedFunctionDetails::LineStart> lines;
};

#ifdef _OS_WINDOWS_
#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
#include <dbghelp.h>
extern "C" EXCEPTION_DISPOSITION _seh_exception_handler(PEXCEPTION_RECORD ExceptionRecord,void *EstablisherFrame, PCONTEXT ContextRecord, void *DispatcherContext);
extern volatile int jl_in_stackwalk;

This comment has been minimized.

Copy link
@tkelman

tkelman Mar 31, 2014

Contributor

Shouldn't this also be extern "C" since the value is set in task.c?

This comment has been minimized.

Copy link
@ivarne

ivarne Mar 31, 2014

Member

I think extern "C" is for functions because C++ does name mangling to encode the types of the argument into the function name. Variables can't be overloaded, so that should not be needed.

This comment has been minimized.

Copy link
@tkelman

tkelman Mar 31, 2014

Contributor

Seems not to matter with GCC, but MSVC mangles extern global variables in C++.
error LNK2001: unresolved external symbol "int volatile jl_in_stackwalk" (?jl_in_stackwalk@@3HC)

I'll put this in as part of #6230

This comment has been minimized.

Copy link
@StefanKarpinski

StefanKarpinski Mar 31, 2014

Member

Yikes. Well, I guess the extern can't hurt, right? I wonder why MSVC mangles global variable names?

This comment has been minimized.

Copy link
@ivarne

ivarne Mar 31, 2014

Member

Well, I stand corrected.

This comment has been minimized.

Copy link
@tkelman

tkelman Mar 31, 2014

Contributor

Dunno. Seems ok according to Travis? https://travis-ci.org/JuliaLang/julia/builds/21940217

Hopefully no adverse backtrace consequences of extern "C" on it.

This comment has been minimized.

Copy link
@ivarne

ivarne Mar 31, 2014

Member

Not that you should listen to me after being wrong on the first statement, but there should not be. It is not uncommon to declare a whole header file as extern "C", when using a C library from C++.

This comment has been minimized.

Copy link
@tkelman

tkelman Mar 31, 2014

Contributor

Heh. e7955dd

#endif

struct revcomp {
Expand All @@ -26,9 +31,9 @@ class JuliaJITEventListener: public JITEventListener
virtual void NotifyFunctionEmitted(const Function &F, void *Code,
size_t Size, const EmittedFunctionDetails &Details)
{
FuncInfo tmp = {&F, Size, Details.LineStarts};
if (tmp.lines.size() != 0) info[(size_t)(Code)] = tmp;
#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
assert(!jl_in_stackwalk);
jl_in_stackwalk = 1;
uintptr_t catchjmp = (uintptr_t)Code+Size;
*(uint8_t*)(catchjmp+0) = 0x48;
*(uint8_t*)(catchjmp+1) = 0xb8; // mov RAX, QWORD PTR [...]
Expand All @@ -48,8 +53,24 @@ class JuliaJITEventListener: public JITEventListener
UnwindData[6] = 1; // first instruction
UnwindData[7] = 0x50; // push RBP
*(DWORD*)&UnwindData[8] = (DWORD)(catchjmp-(intptr_t)Code);
RtlAddFunctionTable(tbl,1,(DWORD64)Code);
DWORD mod_size = (DWORD)(size_t)(&UnwindData[8]-(uint8_t*)Code);
if (!SymLoadModuleEx(GetCurrentProcess(), NULL, NULL, NULL, (DWORD64)Code, mod_size, NULL, SLMFLAG_VIRTUAL)) {
JL_PRINTF(JL_STDERR, "WARNING: failed to insert function info for backtrace\n");
}
else {
if (!SymAddSymbol(GetCurrentProcess(), (ULONG64)Code, F.getName().data(), (DWORD64)Code, mod_size, 0)) {
JL_PRINTF(JL_STDERR, "WARNING: failed to insert function name into debug info\n");
}
if (!RtlAddFunctionTable(tbl,1,(DWORD64)Code)) {
JL_PRINTF(JL_STDERR, "WARNING: failed to insert function stack unwind info\n");
}
}
jl_in_stackwalk = 0;
FuncInfo tmp = {&F, Size, tbl, Details.LineStarts};
#else
FuncInfo tmp = {&F, Size, Details.LineStarts};
#endif
if (tmp.lines.size() != 0) info[(size_t)(Code)] = tmp;
}

std::map<size_t, FuncInfo, revcomp>& getMap()
Expand All @@ -60,9 +81,9 @@ class JuliaJITEventListener: public JITEventListener

JuliaJITEventListener *jl_jit_events;

extern "C" void getFunctionInfo(const char **name, int *line, const char **filename,size_t pointer);
extern "C" void jl_getFunctionInfo(const char **name, int *line, const char **filename,size_t pointer);

void getFunctionInfo(const char **name, int *line, const char **filename, size_t pointer)
void jl_getFunctionInfo(const char **name, int *line, const char **filename, size_t pointer)
{
std::map<size_t, FuncInfo, revcomp> &info = jl_jit_events->getMap();
*name = NULL;
Expand Down Expand Up @@ -107,6 +128,19 @@ void getFunctionInfo(const char **name, int *line, const char **filename, size_t
}

#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)

extern "C" void* CALLBACK jl_getUnwindInfo(HANDLE hProcess, ULONG64 AddrBase, ULONG64 UserContext);

void* CALLBACK jl_getUnwindInfo(HANDLE hProcess, ULONG64 AddrBase, ULONG64 UserContext)
{
std::map<size_t, FuncInfo, revcomp> &info = jl_jit_events->getMap();
std::map<size_t, FuncInfo, revcomp>::iterator it = info.lower_bound(AddrBase);
if (it != info.end() && (size_t)(*it).first + (*it).second.lengthAdr >= AddrBase) {
return (void*)(*it).second.fnentry;
}
return NULL;
}

class JITMemoryManagerWin : public JITMemoryManager {
private:
JITMemoryManager *JMM;
Expand Down
10 changes: 8 additions & 2 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ EXCEPTION_DISPOSITION _seh_exception_handler(PEXCEPTION_RECORD ExceptionRecord,

return rval;
}
void* CALLBACK jl_getUnwindInfo(HANDLE hProcess, ULONG64 AddrBase, ULONG64 UserContext);
#endif

#else // #ifdef _OS_WINDOWS_
Expand Down Expand Up @@ -657,10 +658,15 @@ void julia_init(char *imageFile)
if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
GetCurrentProcess(), (PHANDLE)&hMainThread, 0,
TRUE, DUPLICATE_SAME_ACCESS)) {
JL_PRINTF(JL_STDERR, "Couldn't access handle to main thread\n");
JL_PRINTF(JL_STDERR, "WARNING: failed to access handle to main thread\n");
}
SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
SymInitialize(GetCurrentProcess(), NULL, 1);
if (!SymInitialize(GetCurrentProcess(), NULL, 1)) {
JL_PRINTF(JL_STDERR, "WARNING: failed to initalize stack walk info\n");
}
#if defined(_CPU_X86_64_)
if (!SymRegisterFunctionEntryCallback64(GetCurrentProcess(), jl_getUnwindInfo, 0)) JL_PRINTF(JL_STDERR, "WARNING: failed to install backtrace info callback\n");
#endif
needsSymRefreshModuleList = 0;
uv_lib_t jl_dbghelp;
uv_dlopen("dbghelp.dll",&jl_dbghelp);
Expand Down
26 changes: 13 additions & 13 deletions src/task.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <winbase.h>
#include <malloc.h>
#include <dbghelp.h>
static volatile int in_stackwalk = 0;
volatile int jl_in_stackwalk = 0;
#else
#include <unistd.h>
// This gives unwind only local unwinding options ==> faster code
Expand Down Expand Up @@ -451,24 +451,24 @@ static void init_task(jl_task_t *t)
ptrint_t bt_data[MAX_BT_SIZE+1];
size_t bt_size = 0;

void getFunctionInfo(const char **name, int *line, const char **filename, size_t pointer);
void jl_getFunctionInfo(const char **name, int *line, const char **filename, size_t pointer);

static const char* name_unknown = "???";
static int frame_info_from_ip(const char **func_name, int *line_num, const char **file_name, size_t ip, int doCframes)
{
int fromC = 0;

getFunctionInfo(func_name, line_num, file_name, ip);
jl_getFunctionInfo(func_name, line_num, file_name, ip);
if (*func_name == NULL && doCframes) {
fromC = 1;
#if defined(_OS_WINDOWS_)
if (in_stackwalk) {
if (jl_in_stackwalk) {
*func_name = name_unknown;
*file_name = name_unknown;
*line_num = ip;
}
else {
in_stackwalk = 1;
jl_in_stackwalk = 1;
DWORD64 dwDisplacement64 = 0;
DWORD64 dwAddress = ip;

Expand Down Expand Up @@ -504,7 +504,7 @@ static int frame_info_from_ip(const char **func_name, int *line_num, const char
//DWORD error = GetLastError();
//printf("SymGetLineFromAddr64 returned error : %d\n", error);
}
in_stackwalk = 0;
jl_in_stackwalk = 0;
}
#else
Dl_info dlinfo;
Expand Down Expand Up @@ -537,23 +537,23 @@ DLLEXPORT size_t rec_backtrace(ptrint_t *data, size_t maxsize)
{
CONTEXT Context;
memset(&Context, 0, sizeof(Context));
in_stackwalk = 1;
jl_in_stackwalk = 1;
RtlCaptureContext(&Context);
in_stackwalk = 0;
jl_in_stackwalk = 0;
return rec_backtrace_ctx(data, maxsize, &Context);
}
DLLEXPORT size_t rec_backtrace_ctx(ptrint_t *data, size_t maxsize, CONTEXT *Context)
{
if (in_stackwalk) {
if (jl_in_stackwalk) {
return 0;
}
STACKFRAME64 stk;
memset(&stk, 0, sizeof(stk));

if (needsSymRefreshModuleList && hSymRefreshModuleList != 0) {
in_stackwalk = 1;
jl_in_stackwalk = 1;
hSymRefreshModuleList(GetCurrentProcess());
in_stackwalk = 0;
jl_in_stackwalk = 0;
needsSymRefreshModuleList = 0;
}
#if defined(_CPU_X86_64_)
Expand All @@ -576,10 +576,10 @@ DLLEXPORT size_t rec_backtrace_ctx(ptrint_t *data, size_t maxsize, CONTEXT *Cont
size_t n = 0;
intptr_t lastsp = stk.AddrStack.Offset;
while (n < maxsize) {
in_stackwalk = 1;
jl_in_stackwalk = 1;
BOOL result = StackWalk64(MachineType, GetCurrentProcess(), hMainThread,
&stk, Context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL);
in_stackwalk = 0;
jl_in_stackwalk = 0;
data[n++] = (intptr_t)stk.AddrPC.Offset;
intptr_t sp = (intptr_t)stk.AddrStack.Offset;
if (!result || sp == 0 ||
Expand Down

0 comments on commit 9f68899

Please sign in to comment.