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

Store global variables and function addresses as 32bit offsets #22472

Merged
merged 2 commits into from
Jun 23, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
137 changes: 89 additions & 48 deletions src/debuginfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,85 @@ static inline void ignoreError(T &err)
#endif
}

static void get_function_name_and_base(const object::ObjectFile *object, bool insysimage,
void **saddr, char **name, size_t pointer,
int64_t slide)
{
if (!object)
return;
// Assume we only need base address for sysimg for now
if (!insysimage || !sysimg_fvars)
saddr = nullptr;
// Try platform specific methods first since they are usually faster
if (saddr && !*saddr) {
#if defined(_OS_LINUX_) && !defined(JL_DISABLE_LIBUNWIND)
unw_proc_info_t pip;
if (unw_get_proc_info_by_ip(unw_local_addr_space, pointer, &pip, NULL) == 0) {
*saddr = (void*)pip.start_ip;
}
#endif
#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
DWORD64 ImageBase;
PRUNTIME_FUNCTION fn = RtlLookupFunctionEntry(pointer, &ImageBase, NULL);
if (fn) {
*saddr = (void*)(ImageBase + fn->BeginAddress);
}
#endif
}
if ((saddr && !*saddr) || (name && !*name)) {
size_t distance = (size_t)-1;
SymRef sym_found;
for (auto sym: object->symbols()) {
auto addr = sym.getAddress();
if (!addr)
continue;
size_t symptr = addr.get();
if (symptr > pointer + slide)
continue;
size_t new_dist = pointer + slide - symptr;
if (new_dist > distance)
continue;
distance = new_dist;
sym_found = sym;
}
if (distance != (size_t)-1) {
if (saddr && !*saddr) {
auto addr = sym_found.getAddress();
assert(addr);
*saddr = (void*)(uintptr_t)(addr.get() - slide);
}
if (name && !*name) {
if (auto name_or_err = sym_found.getName()) {
auto nameref = name_or_err.get();
size_t len = nameref.size();
*name = (char*)malloc(len + 1);
(*name)[len] = 0;
memcpy(*name, nameref.data(), len);
}
}
}
}
#ifdef _OS_WINDOWS_
// For ntdll and msvcrt since we are currently only parsing DWARF debug info through LLVM
if (!insysimage && name && !*name) {
static char frame_info_func[
sizeof(SYMBOL_INFO) +
MAX_SYM_NAME * sizeof(TCHAR)];
DWORD64 dwDisplacement64 = 0;
DWORD64 dwAddress = pointer;
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)frame_info_func;
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
jl_in_stackwalk = 1;
if (SymFromAddr(GetCurrentProcess(), dwAddress, &dwDisplacement64, pSymbol)) {
// errors are ignored
jl_copy_str(name, pSymbol->Name);
}
jl_in_stackwalk = 0;
}
#endif
}

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 Down Expand Up @@ -746,35 +825,12 @@ bool jl_dylib_DI_for_fptr(size_t pointer, const llvm::object::ObjectFile **obj,
if (onlySysImg && !insysimage) {
return false;
}
static char frame_info_func[
sizeof(SYMBOL_INFO) +
MAX_SYM_NAME * sizeof(TCHAR)];
DWORD64 dwDisplacement64 = 0;
DWORD64 dwAddress = pointer;
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)frame_info_func;
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
jl_in_stackwalk = 1;
if (SymFromAddr(GetCurrentProcess(), dwAddress, &dwDisplacement64,
pSymbol)) {
// SymFromAddr returned success
// errors are ignored, but are hopefully patched up by
// using llvm to read the object (below)
if (name)
jl_copy_str(name, pSymbol->Name);
if (saddr)
*saddr = (void*)(uintptr_t)pSymbol->Address;
}
else if (saddr) {
*saddr = NULL;
}

// If we didn't find the filename before in the debug
// info, use the dll name
if (filename && !*filename)
jl_copy_str(filename, fname.data());

jl_in_stackwalk = 0;
if (saddr)
*saddr = NULL;

#else // ifdef _OS_WINDOWS_
Dl_info dlinfo;
Expand Down Expand Up @@ -832,6 +888,7 @@ bool jl_dylib_DI_for_fptr(size_t pointer, const llvm::object::ObjectFile **obj,
*context = it->second.ctx;
*slide = it->second.slide;
*section_slide = it->second.section_slide;
get_function_name_and_base(*obj, insysimage, saddr, name, pointer, *slide);
return true;
}

Expand Down Expand Up @@ -961,6 +1018,7 @@ bool jl_dylib_DI_for_fptr(size_t pointer, const llvm::object::ObjectFile **obj,
// update cache
objfileentry_t entry = {*obj, *context, *slide, *section_slide};
objfilemap[fbase] = entry;
get_function_name_and_base(*obj, insysimage, saddr, name, pointer, *slide);
return true;
}

Expand Down Expand Up @@ -999,32 +1057,15 @@ static int jl_getDylibFunctionInfo(jl_frame_t **frames, size_t pointer, int skip
return 1;
}
frame0->fromC = !isSysImg;
if (isSysImg && sysimg_fvars) {
#if defined(_OS_LINUX_) && !defined(JL_DISABLE_LIBUNWIND)
unw_proc_info_t pip;
if (!saddr && unw_get_proc_info_by_ip(unw_local_addr_space,
pointer, &pip, NULL) == 0)
saddr = (void*)pip.start_ip;
#endif
#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
if (!saddr) {
DWORD64 ImageBase;
PRUNTIME_FUNCTION fn = RtlLookupFunctionEntry(pointer, &ImageBase, NULL);
if (fn)
saddr = (void*)(ImageBase + fn->BeginAddress);
}
#endif
if (saddr) {
for (size_t i = 0; i < sysimg_fvars_n; i++) {
if (saddr == sysimg_fvars[i]) {
frame0->linfo = sysimg_fvars_linfo[i];
break;
}
if (isSysImg && sysimg_fvars && saddr) {
for (size_t i = 0; i < sysimg_fvars_n; i++) {
if (saddr == sysimg_fvars[i]) {
frame0->linfo = sysimg_fvars_linfo[i];
break;
}
}
return lookup_pointer(context, frames, pointer+slide, isSysImg, noInline);
}
return lookup_pointer(context, frames, pointer+slide, isSysImg, noInline);
return lookup_pointer(context, frames, pointer + slide, isSysImg, noInline);
}

int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide, int64_t *section_slide,
Expand Down
8 changes: 1 addition & 7 deletions test/cmdlineargs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -423,13 +423,7 @@ end
for precomp in ("yes", "no")
bt = readstring(pipeline(ignorestatus(`$(Base.julia_cmd()) --startup-file=no --precompiled=$precomp
-E 'include("____nonexistent_file")'`), stderr=catcmd))
@test contains(bt, "include_from_node1")
if ((is_windows() && Sys.WORD_SIZE == 32) || (is_bsd() && !is_apple())) && precomp == "yes"
# FIXME: Issue #17251 (Windows), #20798 (FreeBSD)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool, thanks for fixing this

@test_broken contains(bt, "include_from_node1(::Module, ::String) at $(joinpath(".", "loading.jl"))")
else
@test contains(bt, "include_from_node1(::Module, ::String) at $(joinpath(".", "loading.jl"))")
end
@test contains(bt, "include_from_node1(::Module, ::String) at $(joinpath(".", "loading.jl"))")
lno = match(r"at \.[\/\\]loading\.jl:(\d+)", bt)
@test length(lno.captures) == 1
@test parse(Int, lno.captures[1]) > 0
Expand Down