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 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
5 changes: 3 additions & 2 deletions src/anticodegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ int jl_getFunctionInfo(jl_frame_t **frames, uintptr_t pointer, int skipC, int no
return 0;
}

void jl_register_fptrs(uint64_t sysimage_base, void **fptrs, jl_method_instance_t **linfos, size_t n)
void jl_register_fptrs(uint64_t sysimage_base, const char *base, const int32_t *offsets,
jl_method_instance_t **linfos, size_t n)
{
(void)sysimage_base; (void)fptrs; (void)linfos; (void)n;
(void)sysimage_base; (void)base; (void)offsets; (void)linfos; (void)n;
}

void jl_compile_linfo(jl_method_instance_t *li) { }
Expand Down
150 changes: 99 additions & 51 deletions src/debuginfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,13 +696,20 @@ openDebugInfo(StringRef debuginfopath, const debug_link_info &info)
}

static uint64_t jl_sysimage_base;
static void **sysimg_fvars;
static const char *sysimg_fvars_base = nullptr;
static const int32_t *sysimg_fvars_offsets;
static jl_method_instance_t **sysimg_fvars_linfo;
static size_t sysimg_fvars_n;
extern "C" void jl_register_fptrs(uint64_t sysimage_base, void **fptrs, jl_method_instance_t **linfos, size_t n)
static const void *sysimg_fvars(size_t idx)
{
return sysimg_fvars_base + sysimg_fvars_offsets[idx];
}
void jl_register_fptrs(uint64_t sysimage_base, const char *base, const int32_t *offsets,
jl_method_instance_t **linfos, size_t n)
{
jl_sysimage_base = (uintptr_t)sysimage_base;
sysimg_fvars = fptrs;
sysimg_fvars_base = base;
sysimg_fvars_offsets = offsets;
sysimg_fvars_linfo = linfos;
sysimg_fvars_n = n;
}
Expand All @@ -716,6 +723,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_base)
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 +832,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 +895,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 +1025,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 +1064,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_base && 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
50 changes: 32 additions & 18 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,20 @@ static void write_float64(ios_t *s, double x)
#define jl_serialize_value(s, v) jl_serialize_value_((s), (jl_value_t*)(v), 0)
static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal);
static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc);
static jl_value_t ***sysimg_gvars = NULL;
static void **sysimg_fvars = NULL;
static char *sysimg_gvars_base = NULL;
static const int32_t *sysimg_gvars_offsets = NULL;
static const char *sysimg_fvars_base = NULL;
static const int32_t *sysimg_fvars_offsets = NULL;

static inline jl_value_t **sysimg_gvars(size_t idx)
{
return (jl_value_t**)(sysimg_gvars_base + sysimg_gvars_offsets[idx]);
}

static inline const void *sysimg_fvars(const char *base, size_t idx)
{
return base + sysimg_fvars_offsets[idx];
}

#ifdef HAVE_CPUID
extern void jl_cpuid(int32_t CPUInfo[4], int32_t InfoType);
Expand All @@ -233,17 +245,21 @@ static void jl_load_sysimg_so(void)
int imaging_mode = jl_generating_output() && !jl_options.incremental;
// in --build mode only use sysimg data, not precompiled native code
if (!imaging_mode && jl_options.use_precompiled==JL_OPTIONS_USE_PRECOMPILED_YES) {
sysimg_gvars = (jl_value_t***)jl_dlsym(jl_sysimg_handle, "jl_sysimg_gvars");
sysimg_fvars = (void**)jl_dlsym(jl_sysimg_handle, "jl_sysimg_fvars");
sysimg_gvars_base = (char*)jl_dlsym(jl_sysimg_handle, "jl_sysimg_gvars_base");
sysimg_gvars_offsets = (const int32_t*)jl_dlsym(jl_sysimg_handle,
"jl_sysimg_gvars_offsets");
sysimg_fvars_base = (const char*)jl_dlsym(jl_sysimg_handle, "jl_sysimg_fvars_base");
sysimg_fvars_offsets = (const int32_t*)jl_dlsym(jl_sysimg_handle,
"jl_sysimg_fvars_offsets");
globalUnique = *(size_t*)jl_dlsym(jl_sysimg_handle, "jl_globalUnique");
#ifdef JULIA_ENABLE_THREADING
size_t tls_getter_idx = *(size_t*)jl_dlsym(jl_sysimg_handle,
"jl_ptls_states_getter_idx");
*sysimg_gvars[tls_getter_idx - 1] =
*sysimg_gvars(tls_getter_idx - 1) =
(jl_value_t*)(uintptr_t)jl_get_ptls_states_getter();
size_t tls_offset_idx = *(size_t*)jl_dlsym(jl_sysimg_handle,
"jl_tls_offset_idx");
*sysimg_gvars[tls_offset_idx - 1] =
*sysimg_gvars(tls_offset_idx - 1) =
(jl_value_t*)(uintptr_t)(jl_tls_offset == -1 ? 0 : jl_tls_offset);
#endif
const char *cpu_target = (const char*)jl_dlsym(jl_sysimg_handle, "jl_sysimg_cpu_target");
Expand Down Expand Up @@ -271,7 +287,7 @@ static void jl_load_sysimg_so(void)
#ifdef _OS_WINDOWS_
sysimage_base = (intptr_t)jl_sysimg_handle;
#else
if (dladdr((void*)sysimg_gvars, &dlinfo) != 0) {
if (dladdr((void*)sysimg_gvars_base, &dlinfo) != 0) {
sysimage_base = (intptr_t)dlinfo.dli_fbase;
}
else {
Expand All @@ -288,8 +304,8 @@ static jl_value_t *jl_deserialize_gv(jl_serializer_state *s, jl_value_t *v)
{
// Restore the GlobalVariable reference to this jl_value_t via the sysimg_gvars table
int32_t gvname_index = read_int32(s->s)-1;
if (sysimg_gvars != NULL && gvname_index >= 0 && s->mode == MODE_SYSTEM_IMAGE) {
*sysimg_gvars[gvname_index] = v;
if (sysimg_gvars_base != NULL && gvname_index >= 0 && s->mode == MODE_SYSTEM_IMAGE) {
*sysimg_gvars(gvname_index) = v;
}
return v;
}
Expand Down Expand Up @@ -419,13 +435,11 @@ static void jl_delayed_fptrs(jl_method_instance_t *li, int32_t func, int32_t cfu
}
}

void jl_register_fptrs(uint64_t sysimage_base, void **fptrs, jl_method_instance_t **linfos, size_t n);

static void jl_update_all_fptrs(void)
{
//jl_printf(JL_STDOUT, "delayed_fptrs_n: %d\n", delayed_fptrs_n);
void **fvars = sysimg_fvars;
if (fvars == NULL) {
const char *fvars_base = sysimg_fvars_base;
if (fvars_base == NULL) {
size_t i;
for (i = 0; i < delayed_fptrs_n; i++) {
jl_method_instance_t *li = delayed_fptrs[i].li;
Expand All @@ -436,25 +450,25 @@ static void jl_update_all_fptrs(void)
}
// jl_fptr_to_llvm needs to decompress some ASTs, therefore this needs to be NULL
// to skip trying to restore GlobalVariable pointers in jl_deserialize_gv
sysimg_gvars = NULL;
sysimg_fvars = NULL;
sysimg_gvars_base = NULL;
sysimg_fvars_base = NULL;
size_t i;
jl_method_instance_t **linfos = (jl_method_instance_t**)malloc(sizeof(jl_method_instance_t*) * sysimg_fvars_max);
for (i = 0; i < delayed_fptrs_n; i++) {
jl_method_instance_t *li = delayed_fptrs[i].li;
assert(jl_is_method(li->def.method) && li->jlcall_api && li->jlcall_api != 2);
int32_t cfunc = delayed_fptrs[i].cfunc - 1;
if (cfunc >= 0) {
jl_fptr_to_llvm((jl_fptr_t)(uintptr_t)fvars[cfunc], li, 1);
jl_fptr_to_llvm((jl_fptr_t)(uintptr_t)sysimg_fvars(fvars_base, cfunc), li, 1);
linfos[cfunc] = li;
}
int32_t func = delayed_fptrs[i].func - 1;
if (func >= 0) {
jl_fptr_to_llvm((jl_fptr_t)(uintptr_t)fvars[func], li, 0);
jl_fptr_to_llvm((jl_fptr_t)(uintptr_t)sysimg_fvars(fvars_base, func), li, 0);
linfos[func] = li;
}
}
jl_register_fptrs(sysimage_base, fvars, linfos, sysimg_fvars_max);
jl_register_fptrs(sysimage_base, fvars_base, sysimg_fvars_offsets, linfos, sysimg_fvars_max);
delayed_fptrs_n = 0;
delayed_fptrs_max = 0;
sysimg_fvars_max = 0;
Expand Down
Loading