Skip to content

Commit cbd835b

Browse files
yuyichaoararslan
authored andcommitted
Merge pull request #22472 from JuliaLang/yyc/codegen/function_offset
Store global variables and function addresses as 32bit offsets Ref #22472 (cherry picked from commit d040151)
1 parent 489dcc5 commit cbd835b

File tree

6 files changed

+170
-101
lines changed

6 files changed

+170
-101
lines changed

src/anticodegen.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ int jl_getFunctionInfo(jl_frame_t **frames, uintptr_t pointer, int skipC, int no
3636
return 0;
3737
}
3838

39-
void jl_register_fptrs(uint64_t sysimage_base, void **fptrs, jl_method_instance_t **linfos, size_t n)
39+
void jl_register_fptrs(uint64_t sysimage_base, const char *base, const int32_t *offsets,
40+
jl_method_instance_t **linfos, size_t n)
4041
{
41-
(void)sysimage_base; (void)fptrs; (void)linfos; (void)n;
42+
(void)sysimage_base; (void)base; (void)offsets; (void)linfos; (void)n;
4243
}
4344

4445
void jl_compile_linfo(jl_method_instance_t *li) { }

src/debuginfo.cpp

Lines changed: 99 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,13 +1026,20 @@ openDebugInfo(StringRef debuginfopath, const debug_link_info &info)
10261026
#endif
10271027

10281028
static uint64_t jl_sysimage_base;
1029-
static void **sysimg_fvars;
1029+
static const char *sysimg_fvars_base = nullptr;
1030+
static const int32_t *sysimg_fvars_offsets;
10301031
static jl_method_instance_t **sysimg_fvars_linfo;
10311032
static size_t sysimg_fvars_n;
1032-
extern "C" void jl_register_fptrs(uint64_t sysimage_base, void **fptrs, jl_method_instance_t **linfos, size_t n)
1033+
static const void *sysimg_fvars(size_t idx)
1034+
{
1035+
return sysimg_fvars_base + sysimg_fvars_offsets[idx];
1036+
}
1037+
void jl_register_fptrs(uint64_t sysimage_base, const char *base, const int32_t *offsets,
1038+
jl_method_instance_t **linfos, size_t n)
10331039
{
10341040
jl_sysimage_base = (uintptr_t)sysimage_base;
1035-
sysimg_fvars = fptrs;
1041+
sysimg_fvars_base = base;
1042+
sysimg_fvars_offsets = offsets;
10361043
sysimg_fvars_linfo = linfos;
10371044
sysimg_fvars_n = n;
10381045
}
@@ -1046,6 +1053,85 @@ static inline void ignoreError(T &err)
10461053
#endif
10471054
}
10481055

1056+
static void get_function_name_and_base(const object::ObjectFile *object, bool insysimage,
1057+
void **saddr, char **name, size_t pointer,
1058+
int64_t slide)
1059+
{
1060+
if (!object)
1061+
return;
1062+
// Assume we only need base address for sysimg for now
1063+
if (!insysimage || !sysimg_fvars_base)
1064+
saddr = nullptr;
1065+
// Try platform specific methods first since they are usually faster
1066+
if (saddr && !*saddr) {
1067+
#if defined(_OS_LINUX_) && !defined(JL_DISABLE_LIBUNWIND)
1068+
unw_proc_info_t pip;
1069+
if (unw_get_proc_info_by_ip(unw_local_addr_space, pointer, &pip, NULL) == 0) {
1070+
*saddr = (void*)pip.start_ip;
1071+
}
1072+
#endif
1073+
#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
1074+
DWORD64 ImageBase;
1075+
PRUNTIME_FUNCTION fn = RtlLookupFunctionEntry(pointer, &ImageBase, NULL);
1076+
if (fn) {
1077+
*saddr = (void*)(ImageBase + fn->BeginAddress);
1078+
}
1079+
#endif
1080+
}
1081+
if ((saddr && !*saddr) || (name && !*name)) {
1082+
size_t distance = (size_t)-1;
1083+
SymRef sym_found;
1084+
for (auto sym: object->symbols()) {
1085+
auto addr = sym.getAddress();
1086+
if (!addr)
1087+
continue;
1088+
size_t symptr = addr.get();
1089+
if (symptr > pointer + slide)
1090+
continue;
1091+
size_t new_dist = pointer + slide - symptr;
1092+
if (new_dist > distance)
1093+
continue;
1094+
distance = new_dist;
1095+
sym_found = sym;
1096+
}
1097+
if (distance != (size_t)-1) {
1098+
if (saddr && !*saddr) {
1099+
auto addr = sym_found.getAddress();
1100+
assert(addr);
1101+
*saddr = (void*)(uintptr_t)(addr.get() - slide);
1102+
}
1103+
if (name && !*name) {
1104+
if (auto name_or_err = sym_found.getName()) {
1105+
auto nameref = name_or_err.get();
1106+
size_t len = nameref.size();
1107+
*name = (char*)malloc(len + 1);
1108+
(*name)[len] = 0;
1109+
memcpy(*name, nameref.data(), len);
1110+
}
1111+
}
1112+
}
1113+
}
1114+
#ifdef _OS_WINDOWS_
1115+
// For ntdll and msvcrt since we are currently only parsing DWARF debug info through LLVM
1116+
if (!insysimage && name && !*name) {
1117+
static char frame_info_func[
1118+
sizeof(SYMBOL_INFO) +
1119+
MAX_SYM_NAME * sizeof(TCHAR)];
1120+
DWORD64 dwDisplacement64 = 0;
1121+
DWORD64 dwAddress = pointer;
1122+
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)frame_info_func;
1123+
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
1124+
pSymbol->MaxNameLen = MAX_SYM_NAME;
1125+
jl_in_stackwalk = 1;
1126+
if (SymFromAddr(GetCurrentProcess(), dwAddress, &dwDisplacement64, pSymbol)) {
1127+
// errors are ignored
1128+
jl_copy_str(name, pSymbol->Name);
1129+
}
1130+
jl_in_stackwalk = 0;
1131+
}
1132+
#endif
1133+
}
1134+
10491135
extern "C" void jl_refresh_dbg_module_list(void);
10501136
bool jl_dylib_DI_for_fptr(size_t pointer, const llvm::object::ObjectFile **obj, llvm::DIContext **context, int64_t *slide, int64_t *section_slide,
10511137
bool onlySysImg, bool *isSysImg, void **saddr, char **name, char **filename)
@@ -1076,35 +1162,12 @@ bool jl_dylib_DI_for_fptr(size_t pointer, const llvm::object::ObjectFile **obj,
10761162
if (onlySysImg && !insysimage) {
10771163
return false;
10781164
}
1079-
static char frame_info_func[
1080-
sizeof(SYMBOL_INFO) +
1081-
MAX_SYM_NAME * sizeof(TCHAR)];
1082-
DWORD64 dwDisplacement64 = 0;
1083-
DWORD64 dwAddress = pointer;
1084-
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)frame_info_func;
1085-
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
1086-
pSymbol->MaxNameLen = MAX_SYM_NAME;
1087-
jl_in_stackwalk = 1;
1088-
if (SymFromAddr(GetCurrentProcess(), dwAddress, &dwDisplacement64,
1089-
pSymbol)) {
1090-
// SymFromAddr returned success
1091-
// errors are ignored, but are hopefully patched up by
1092-
// using llvm to read the object (below)
1093-
if (name)
1094-
jl_copy_str(name, pSymbol->Name);
1095-
if (saddr)
1096-
*saddr = (void*)(uintptr_t)pSymbol->Address;
1097-
}
1098-
else if (saddr) {
1099-
*saddr = NULL;
1100-
}
1101-
11021165
// If we didn't find the filename before in the debug
11031166
// info, use the dll name
11041167
if (filename && !*filename)
11051168
jl_copy_str(filename, fname.data());
1106-
1107-
jl_in_stackwalk = 0;
1169+
if (saddr)
1170+
*saddr = NULL;
11081171

11091172
#else // ifdef _OS_WINDOWS_
11101173
Dl_info dlinfo;
@@ -1168,6 +1231,7 @@ bool jl_dylib_DI_for_fptr(size_t pointer, const llvm::object::ObjectFile **obj,
11681231
*context = it->second.ctx;
11691232
*slide = it->second.slide;
11701233
*section_slide = it->second.section_slide;
1234+
get_function_name_and_base(*obj, insysimage, saddr, name, pointer, *slide);
11711235
return true;
11721236
}
11731237

@@ -1361,6 +1425,7 @@ bool jl_dylib_DI_for_fptr(size_t pointer, const llvm::object::ObjectFile **obj,
13611425
// update cache
13621426
objfileentry_t entry = {*obj, *context, *slide, *section_slide};
13631427
objfilemap[fbase] = entry;
1428+
get_function_name_and_base(*obj, insysimage, saddr, name, pointer, *slide);
13641429
return true;
13651430
}
13661431

@@ -1399,32 +1464,15 @@ static int jl_getDylibFunctionInfo(jl_frame_t **frames, size_t pointer, int skip
13991464
return 1;
14001465
}
14011466
frame0->fromC = !isSysImg;
1402-
if (isSysImg && sysimg_fvars) {
1403-
#ifdef _OS_LINUX_
1404-
unw_proc_info_t pip;
1405-
if (!saddr && unw_get_proc_info_by_ip(unw_local_addr_space,
1406-
pointer, &pip, NULL) == 0)
1407-
saddr = (void*)pip.start_ip;
1408-
#endif
1409-
#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
1410-
if (!saddr) {
1411-
DWORD64 ImageBase;
1412-
PRUNTIME_FUNCTION fn = RtlLookupFunctionEntry(pointer, &ImageBase, NULL);
1413-
if (fn)
1414-
saddr = (void*)(ImageBase + fn->BeginAddress);
1415-
}
1416-
#endif
1417-
if (saddr) {
1418-
for (size_t i = 0; i < sysimg_fvars_n; i++) {
1419-
if (saddr == sysimg_fvars[i]) {
1420-
frame0->linfo = sysimg_fvars_linfo[i];
1421-
break;
1422-
}
1467+
if (isSysImg && sysimg_fvars_base && saddr) {
1468+
for (size_t i = 0; i < sysimg_fvars_n; i++) {
1469+
if (saddr == sysimg_fvars(i)) {
1470+
frame0->linfo = sysimg_fvars_linfo[i];
1471+
break;
14231472
}
14241473
}
1425-
return lookup_pointer(context, frames, pointer+slide, isSysImg, noInline);
14261474
}
1427-
return lookup_pointer(context, frames, pointer+slide, isSysImg, noInline);
1475+
return lookup_pointer(context, frames, pointer + slide, isSysImg, noInline);
14281476
}
14291477

14301478
int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide, int64_t *section_slide,

src/dump.c

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,20 @@ static void write_float64(ios_t *s, double x)
209209
#define jl_serialize_value(s, v) jl_serialize_value_((s), (jl_value_t*)(v), 0)
210210
static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal);
211211
static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc);
212-
static jl_value_t ***sysimg_gvars = NULL;
213-
static void **sysimg_fvars = NULL;
212+
static char *sysimg_gvars_base = NULL;
213+
static const int32_t *sysimg_gvars_offsets = NULL;
214+
static const char *sysimg_fvars_base = NULL;
215+
static const int32_t *sysimg_fvars_offsets = NULL;
216+
217+
static inline jl_value_t **sysimg_gvars(size_t idx)
218+
{
219+
return (jl_value_t**)(sysimg_gvars_base + sysimg_gvars_offsets[idx]);
220+
}
221+
222+
static inline const void *sysimg_fvars(const char *base, size_t idx)
223+
{
224+
return base + sysimg_fvars_offsets[idx];
225+
}
214226

215227
#ifdef HAVE_CPUID
216228
extern void jl_cpuid(int32_t CPUInfo[4], int32_t InfoType);
@@ -233,14 +245,22 @@ static void jl_load_sysimg_so(void)
233245
int imaging_mode = jl_generating_output() && !jl_options.incremental;
234246
// in --build mode only use sysimg data, not precompiled native code
235247
if (!imaging_mode && jl_options.use_precompiled==JL_OPTIONS_USE_PRECOMPILED_YES) {
236-
sysimg_gvars = (jl_value_t***)jl_dlsym(jl_sysimg_handle, "jl_sysimg_gvars");
237-
sysimg_fvars = (void**)jl_dlsym(jl_sysimg_handle, "jl_sysimg_fvars");
248+
sysimg_gvars_base = (char*)jl_dlsym(jl_sysimg_handle, "jl_sysimg_gvars_base");
249+
sysimg_gvars_offsets = (const int32_t*)jl_dlsym(jl_sysimg_handle,
250+
"jl_sysimg_gvars_offsets");
251+
sysimg_fvars_base = (const char*)jl_dlsym(jl_sysimg_handle, "jl_sysimg_fvars_base");
252+
sysimg_fvars_offsets = (const int32_t*)jl_dlsym(jl_sysimg_handle,
253+
"jl_sysimg_fvars_offsets");
238254
globalUnique = *(size_t*)jl_dlsym(jl_sysimg_handle, "jl_globalUnique");
239255
#ifdef JULIA_ENABLE_THREADING
240256
size_t tls_getter_idx = *(size_t*)jl_dlsym(jl_sysimg_handle,
241257
"jl_ptls_states_getter_idx");
242-
*sysimg_gvars[tls_getter_idx - 1] =
243-
(jl_value_t*)jl_get_ptls_states_getter();
258+
*sysimg_gvars(tls_getter_idx - 1) =
259+
(jl_value_t*)(uintptr_t)jl_get_ptls_states_getter();
260+
size_t tls_offset_idx = *(size_t*)jl_dlsym(jl_sysimg_handle,
261+
"jl_tls_offset_idx");
262+
*sysimg_gvars(tls_offset_idx - 1) =
263+
(jl_value_t*)(uintptr_t)(jl_tls_offset == -1 ? 0 : jl_tls_offset);
244264
#endif
245265
const char *cpu_target = (const char*)jl_dlsym(jl_sysimg_handle, "jl_sysimg_cpu_target");
246266
if (strcmp(cpu_target,jl_options.cpu_target) != 0)
@@ -267,7 +287,7 @@ static void jl_load_sysimg_so(void)
267287
#ifdef _OS_WINDOWS_
268288
sysimage_base = (intptr_t)jl_sysimg_handle;
269289
#else
270-
if (dladdr((void*)sysimg_gvars, &dlinfo) != 0) {
290+
if (dladdr((void*)sysimg_gvars_base, &dlinfo) != 0) {
271291
sysimage_base = (intptr_t)dlinfo.dli_fbase;
272292
}
273293
else {
@@ -284,8 +304,8 @@ static jl_value_t *jl_deserialize_gv(jl_serializer_state *s, jl_value_t *v)
284304
{
285305
// Restore the GlobalVariable reference to this jl_value_t via the sysimg_gvars table
286306
int32_t gvname_index = read_int32(s->s)-1;
287-
if (sysimg_gvars != NULL && gvname_index >= 0 && s->mode == MODE_SYSTEM_IMAGE) {
288-
*sysimg_gvars[gvname_index] = v;
307+
if (sysimg_gvars_base != NULL && gvname_index >= 0 && s->mode == MODE_SYSTEM_IMAGE) {
308+
*sysimg_gvars(gvname_index) = v;
289309
}
290310
return v;
291311
}
@@ -415,13 +435,11 @@ static void jl_delayed_fptrs(jl_method_instance_t *li, int32_t func, int32_t cfu
415435
}
416436
}
417437

418-
void jl_register_fptrs(uint64_t sysimage_base, void **fptrs, jl_method_instance_t **linfos, size_t n);
419-
420438
static void jl_update_all_fptrs(void)
421439
{
422440
//jl_printf(JL_STDOUT, "delayed_fptrs_n: %d\n", delayed_fptrs_n);
423-
void **fvars = sysimg_fvars;
424-
if (fvars == NULL) {
441+
const char *fvars_base = sysimg_fvars_base;
442+
if (fvars_base == NULL) {
425443
size_t i;
426444
for (i = 0; i < delayed_fptrs_n; i++) {
427445
jl_method_instance_t *li = delayed_fptrs[i].li;
@@ -432,25 +450,25 @@ static void jl_update_all_fptrs(void)
432450
}
433451
// jl_fptr_to_llvm needs to decompress some ASTs, therefore this needs to be NULL
434452
// to skip trying to restore GlobalVariable pointers in jl_deserialize_gv
435-
sysimg_gvars = NULL;
436-
sysimg_fvars = NULL;
453+
sysimg_gvars_base = NULL;
454+
sysimg_fvars_base = NULL;
437455
size_t i;
438456
jl_method_instance_t **linfos = (jl_method_instance_t**)malloc(sizeof(jl_method_instance_t*) * sysimg_fvars_max);
439457
for (i = 0; i < delayed_fptrs_n; i++) {
440458
jl_method_instance_t *li = delayed_fptrs[i].li;
441459
assert(li->def && li->jlcall_api && li->jlcall_api != 2);
442460
int32_t cfunc = delayed_fptrs[i].cfunc - 1;
443461
if (cfunc >= 0) {
444-
jl_fptr_to_llvm((jl_fptr_t)fvars[cfunc], li, 1);
462+
jl_fptr_to_llvm((jl_fptr_t)(uintptr_t)sysimg_fvars(fvars_base, cfunc), li, 1);
445463
linfos[cfunc] = li;
446464
}
447465
int32_t func = delayed_fptrs[i].func - 1;
448466
if (func >= 0) {
449-
jl_fptr_to_llvm((jl_fptr_t)fvars[func], li, 0);
467+
jl_fptr_to_llvm((jl_fptr_t)(uintptr_t)sysimg_fvars(fvars_base, func), li, 0);
450468
linfos[func] = li;
451469
}
452470
}
453-
jl_register_fptrs(sysimage_base, fvars, linfos, sysimg_fvars_max);
471+
jl_register_fptrs(sysimage_base, fvars_base, sysimg_fvars_offsets, linfos, sysimg_fvars_max);
454472
delayed_fptrs_n = 0;
455473
delayed_fptrs_max = 0;
456474
sysimg_fvars_max = 0;

0 commit comments

Comments
 (0)