Skip to content

Commit

Permalink
test libccalltest.so with split debug info
Browse files Browse the repository at this point in the history
(cherry picked from commit 4083d9b)
ref #17962
  • Loading branch information
vtjnash authored and tkelman committed Aug 20, 2016
1 parent 96ef8f2 commit e5f7f5c
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 10 deletions.
1 change: 1 addition & 0 deletions Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ endif #ARCH
LD := link
endif #USEMSVC
RANLIB := $(CROSS_COMPILE)ranlib
OBJCOPY := $(CROSS_COMPILE)objcopy

# file extensions
ifeq ($(OS), WINNT)
Expand Down
4 changes: 2 additions & 2 deletions base/stacktraces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ immutable StackFrame # this type should be kept platform-agnostic so that profil
"true if the code is from an inlined frame"
inlined::Bool
"representation of the pointer to the execution context as returned by `backtrace`"
pointer::Int64 # Large enough to be read losslessly on 32- and 64-bit machines.
pointer::UInt64 # Large enough to be read losslessly on 32- and 64-bit machines.
end

StackFrame(func, file, line) = StackFrame(func, file, line, Nullable{LambdaInfo}(), false, false, 0)
Expand Down Expand Up @@ -123,7 +123,7 @@ inlined at that point, innermost function first.
"""
function lookup(pointer::Ptr{Void})
infos = ccall(:jl_lookup_code_address, Any, (Ptr{Void}, Cint), pointer - 1, false)
isempty(infos) && return [StackFrame(empty_sym, empty_sym, -1, Nullable{LambdaInfo}(), true, false, convert(Int64, pointer))]
isempty(infos) && return [StackFrame(empty_sym, empty_sym, -1, Nullable{LambdaInfo}(), true, false, convert(UInt64, pointer))]
res = Array{StackFrame}(length(infos))
for i in 1:length(infos)
info = infos[i]
Expand Down
23 changes: 22 additions & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,26 @@ $(BUILDDIR)/%.dbg.obj: $(SRCDIR)/%.cpp $(SRCDIR)/llvm-version.h $(HEADERS) $(LLV
@$(call PRINT_CC, $(CXX) $(shell $(LLVM_CONFIG_HOST) --cxxflags) $(CPPFLAGS) $(CXXFLAGS) $(DEBUGFLAGS) -c $< -o $@)

libccalltest: $(build_shlibdir)/libccalltest.$(SHLIB_EXT)

ifeq ($(OS), Linux)
JULIA_SPLITDEBUG := 1
else
JULIA_SPLITDEBUG := 0
endif
$(build_shlibdir)/libccalltest.$(SHLIB_EXT): $(SRCDIR)/ccalltest.c
@$(call PRINT_CC, $(CC) $(CFLAGS) $(CPPFLAGS) $(DEBUGFLAGS) -O3 $< $(fPIC) -shared -o $@ $(LDFLAGS))
@$(call PRINT_CC, $(CC) $(CFLAGS) $(CPPFLAGS) $(DEBUGFLAGS) -O3 $< $(fPIC) -shared -o $@.tmp $(LDFLAGS))
ifeq ($(JULIA_SPLITDEBUG),1)
@# Create split debug info file for libccalltest stacktraces test
@# packagers should disable this by setting JULIA_SPLITDEBUG=0 if this is already done by your build system
$(OBJCOPY) --only-keep-debug $@.tmp $@.debug
$(OBJCOPY) --strip-debug $@.tmp
$(OBJCOPY) --add-gnu-debuglink=$@.debug $@.tmp
endif
@## clang should have made the dSYM split-debug directory,
@## but we are intentionally not going to give it the correct name
@## because we want to test the non-default debug configuration
@#rm -r $@.dSYM && mv $@.tmp.dSYM $@.dSYM
mv $@.tmp $@

julia_flisp.boot.inc.phony: $(BUILDDIR)/julia_flisp.boot.inc

Expand Down Expand Up @@ -220,9 +238,11 @@ ifneq ($(OS), WINNT)
@ln -sf libjulia-debug.$(JL_MAJOR_MINOR_SHLIB_EXT) $(build_shlibdir)/libjulia-debug.$(SHLIB_EXT)
endif
$(DSYMUTIL) $@

$(BUILDDIR)/libjulia-debug.a: $(SRCDIR)/julia.expmap $(DOBJS) $(BUILDDIR)/flisp/libflisp-debug.a $(BUILDDIR)/support/libsupport-debug.a
rm -f $@
@$(call PRINT_LINK, ar -rcs $@ $(DOBJS))

libjulia-debug: $(build_shlibdir)/libjulia-debug.$(JL_MAJOR_MINOR_SHLIB_EXT)

$(build_shlibdir)/libjulia.$(JL_MAJOR_MINOR_SHLIB_EXT): $(SRCDIR)/julia.expmap $(OBJS) $(BUILDDIR)/flisp/libflisp.a $(BUILDDIR)/support/libsupport.a $(LIBUV)
Expand All @@ -233,6 +253,7 @@ ifneq ($(OS), WINNT)
@ln -sf libjulia.$(JL_MAJOR_MINOR_SHLIB_EXT) $(build_shlibdir)/libjulia.$(SHLIB_EXT)
endif
$(DSYMUTIL) $@

$(BUILDDIR)/libjulia.a: julia.expmap $(OBJS) $(BUILDDIR)/flisp/libflisp.a $(BUILDDIR)/support/libsupport.a
rm -f $@
@$(call PRINT_LINK, ar -rcs $@ $(OBJS))
Expand Down
22 changes: 18 additions & 4 deletions src/debuginfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,10 +666,19 @@ static int lookup_pointer(DIContext *context, jl_frame_t **frames,
// This function is not allowed to reference any TLS variables
// since it can be called from an unmanaged thread on OSX.
if (!context) {
if (demangle && (*frames)[0].func_name != NULL) {
char *oldname = (*frames)[0].func_name;
(*frames)[0].func_name = jl_demangle(oldname);
free(oldname);
if (demangle) {
if ((*frames)[0].func_name != NULL) {
char *oldname = (*frames)[0].func_name;
(*frames)[0].func_name = jl_demangle(oldname);
free(oldname);
}
else {
// We do this to hide the jlcall wrappers when getting julia backtraces,
// but it is still good to have them for regular lookup of C frames.
// Technically not true, but we don't want them
// in julia backtraces, so close enough
(*frames)[0].fromC = 1;
}
}
return 1;
}
Expand All @@ -686,6 +695,9 @@ static int lookup_pointer(DIContext *context, jl_frame_t **frames,

int fromC = (*frames)[0].fromC;
int n_frames = inlineInfo.getNumberOfFrames();
if (n_frames == 0)
// no line number info available in the context, return without the context
return lookup_pointer(NULL, frames, pointer, demangle, noInline);
if (noInline)
n_frames = 1;
if (n_frames > 1) {
Expand Down Expand Up @@ -921,6 +933,7 @@ extern "C" void jl_register_fptrs(uint64_t sysimage_base, void **fptrs, jl_lambd
sysimg_fvars_n = n;
}

extern "C" void jl_refresh_dbg_module_list(void);
bool jl_dylib_DI_for_fptr(size_t pointer, const llvm::object::ObjectFile **obj, llvm::DIContext **context, int64_t *slide, int64_t *section_slide,
bool onlySysImg, bool *isSysImg, void **saddr, char **name, char **filename)
{
Expand All @@ -934,6 +947,7 @@ bool jl_dylib_DI_for_fptr(size_t pointer, const llvm::object::ObjectFile **obj,
#ifdef _OS_WINDOWS_
IMAGEHLP_MODULE64 ModuleInfo;
ModuleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
jl_refresh_dbg_module_list();
jl_in_stackwalk = 1;
bool isvalid = SymGetModuleInfo64(GetCurrentProcess(), (DWORD64)pointer, &ModuleInfo);
jl_in_stackwalk = 0;
Expand Down
10 changes: 7 additions & 3 deletions src/stackwalk.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,17 +194,21 @@ static DWORD64 WINAPI JuliaGetModuleBase64(
#endif
}

// Might be called from unmanaged thread.
int needsSymRefreshModuleList;
BOOL (WINAPI *hSymRefreshModuleList)(HANDLE);
static int jl_unw_init(bt_cursor_t *cursor, bt_context_t *Context)
void jl_refresh_dbg_module_list(void)
{
// Might be called from unmanaged thread.
if (needsSymRefreshModuleList && hSymRefreshModuleList != 0 && !jl_in_stackwalk) {
jl_in_stackwalk = 1;
hSymRefreshModuleList(GetCurrentProcess());
jl_in_stackwalk = 0;
needsSymRefreshModuleList = 0;
}
}
static int jl_unw_init(bt_cursor_t *cursor, bt_context_t *Context)
{
jl_refresh_dbg_module_list();
#if !defined(_CPU_X86_64_)
if (jl_in_stackwalk) {
return 0;
Expand Down Expand Up @@ -372,7 +376,7 @@ JL_DLLEXPORT jl_value_t *jl_lookup_code_address(void *ip, int skipC)
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));
jl_svecset(r, 6, jl_box_voidpointer(ip));
}
free(frames);
JL_GC_POP();
Expand Down
10 changes: 10 additions & 0 deletions test/stacktraces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,13 @@ let li = typeof(getfield).name.mt.cache.func::LambdaInfo,
repr = string(sf)
@test repr == " in getfield(...) at b:3"
end

let ctestptr = cglobal((:ctest, "libccalltest")),
ctest = StackTraces.lookup(ctestptr + 1)

@test length(ctest) == 1
@test ctest[1].func === :ctest
@test isnull(ctest[1].linfo)
@test ctest[1].from_c
@test ctest[1].pointer === UInt64(ctestptr)
end

0 comments on commit e5f7f5c

Please sign in to comment.