Skip to content

Commit 4363c55

Browse files
committed
internals: redesign debug object slide handling
LLVM redesigned their debug object slide handling (again), and added asserts for the old, less good way of doing things. Thus we needed to make the same changes (and which makes us more correct, like LLVM).
1 parent 5db347b commit 4363c55

File tree

3 files changed

+102
-181
lines changed

3 files changed

+102
-181
lines changed

src/debuginfo.cpp

Lines changed: 52 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ struct ObjectInfo {
6666
const object::ObjectFile *object;
6767
size_t SectionSize;
6868
ptrdiff_t slide;
69+
object::SectionRef Section;
6970
DIContext *context;
7071
};
7172

@@ -411,7 +412,8 @@ class JuliaJITEventListener: public JITEventListener
411412
ObjectInfo tmp = {&debugObj,
412413
(size_t)SectionSize,
413414
(ptrdiff_t)(SectionAddr - SectionLoadAddr),
414-
DWARFContext::create(debugObj).release(),
415+
*Section,
416+
nullptr,
415417
};
416418
objectmap[SectionLoadAddr] = tmp;
417419
first = false;
@@ -483,13 +485,13 @@ JITEventListener *CreateJuliaJITEventListener()
483485
// with for the current frame. here we'll try to expand it using debug info
484486
// func_name and file_name are either NULL or malloc'd pointers
485487
static int lookup_pointer(
486-
const object::ObjectFile *object, DIContext *context,
487-
jl_frame_t **frames, size_t pointer,
488-
int demangle, int noInline)
488+
object::SectionRef Section, DIContext *context,
489+
jl_frame_t **frames, size_t pointer, int64_t slide,
490+
bool demangle, bool noInline)
489491
{
490492
// This function is not allowed to reference any TLS variables
491493
// since it can be called from an unmanaged thread on OSX.
492-
if (!context || !object) {
494+
if (!context || !Section.getObject()) {
493495
if (demangle) {
494496
char *oldname = (*frames)[0].func_name;
495497
if (oldname != NULL) {
@@ -512,14 +514,14 @@ static int lookup_pointer(
512514
DILineInfoSpecifier infoSpec(DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
513515
DILineInfoSpecifier::FunctionNameKind::ShortName);
514516

515-
auto inlineInfo = context->getInliningInfoForAddress(makeAddress(object, pointer), infoSpec);
517+
auto inlineInfo = context->getInliningInfoForAddress(makeAddress(Section, pointer + slide), infoSpec);
516518

517519
int fromC = (*frames)[0].fromC;
518520
int n_frames = inlineInfo.getNumberOfFrames();
519521
if (n_frames == 0) {
520522
jl_mutex_unlock_maybe_nogc(&codegen_lock);
521523
// no line number info available in the context, return without the context
522-
return lookup_pointer(NULL, NULL, frames, pointer, demangle, noInline);
524+
return lookup_pointer(object::SectionRef(), NULL, frames, pointer, slide, demangle, noInline);
523525
}
524526
if (noInline)
525527
n_frames = 1;
@@ -536,7 +538,7 @@ static int lookup_pointer(
536538
info = inlineInfo.getFrame(i);
537539
}
538540
else {
539-
info = context->getLineInfoForAddress(makeAddress(object, pointer), infoSpec);
541+
info = context->getLineInfoForAddress(makeAddress(Section, pointer + slide), infoSpec);
540542
}
541543

542544
jl_frame_t *frame = &(*frames)[i];
@@ -585,7 +587,6 @@ typedef struct {
585587
const llvm::object::ObjectFile *obj;
586588
DIContext *ctx;
587589
int64_t slide;
588-
int64_t section_slide;
589590
} objfileentry_t;
590591
typedef std::map<uint64_t, objfileentry_t, revcomp> obfiletype;
591592
static obfiletype objfilemap;
@@ -750,9 +751,8 @@ static inline void ignoreError(T &err)
750751
#endif
751752
}
752753

753-
static void get_function_name_and_base(const object::ObjectFile *object, bool insysimage,
754-
void **saddr, char **name, size_t pointer,
755-
int64_t slide, bool untrusted_dladdr)
754+
static void get_function_name_and_base(llvm::object::SectionRef Section, size_t pointer, int64_t slide, bool insysimage,
755+
void **saddr, char **name, bool untrusted_dladdr)
756756
{
757757
// Assume we only need base address for sysimg for now
758758
if (!insysimage || !sysimg_fptrs.base)
@@ -779,10 +779,12 @@ static void get_function_name_and_base(const object::ObjectFile *object, bool in
779779
}
780780
#endif
781781
}
782-
if (object && (needs_saddr || needs_name)) {
782+
if (Section.getObject() && (needs_saddr || needs_name)) {
783783
size_t distance = (size_t)-1;
784784
SymRef sym_found;
785-
for (auto sym: object->symbols()) {
785+
for (auto sym : Section.getObject()->symbols()) {
786+
if (!Section.containsSymbol(sym))
787+
continue;
786788
auto addr = sym.getAddress();
787789
if (!addr)
788790
continue;
@@ -1009,11 +1011,9 @@ static objfileentry_t &find_object_file(uint64_t fbase, StringRef fname)
10091011
}
10101012

10111013
int64_t slide = 0;
1012-
int64_t section_slide = 0;
10131014
if (auto *OF = dyn_cast<const object::COFFObjectFile>(debugobj)) {
10141015
assert(iswindows);
10151016
slide = OF->getImageBase() - fbase;
1016-
section_slide = 0; // Since LLVM 3.8+ addresses are adjusted correctly
10171017
}
10181018
else {
10191019
slide = -(int64_t)fbase;
@@ -1024,7 +1024,7 @@ static objfileentry_t &find_object_file(uint64_t fbase, StringRef fname)
10241024
binary.first.release();
10251025
binary.second.release();
10261026
// update cache
1027-
entry = {debugobj, context, slide, section_slide};
1027+
entry = {debugobj, context, slide};
10281028
}
10291029
else {
10301030
// TODO: report the error instead of silently consuming it?
@@ -1034,14 +1034,25 @@ static objfileentry_t &find_object_file(uint64_t fbase, StringRef fname)
10341034
return entry;
10351035
}
10361036

1037+
// from llvm::SymbolizableObjectFile
1038+
static object::SectionRef getModuleSectionForAddress(const object::ObjectFile *obj, uint64_t Address)
1039+
{
1040+
for (object::SectionRef Sec : obj->sections()) {
1041+
if (!Sec.isText() || Sec.isVirtual())
1042+
continue;
1043+
if (Address >= Sec.getAddress() && Address < Sec.getAddress() + Sec.getSize())
1044+
return Sec;
1045+
}
1046+
return object::SectionRef();
1047+
}
1048+
1049+
10371050
extern "C" void jl_refresh_dbg_module_list(void);
1038-
bool jl_dylib_DI_for_fptr(size_t pointer, const llvm::object::ObjectFile **obj, llvm::DIContext **context, int64_t *slide, int64_t *section_slide,
1051+
bool jl_dylib_DI_for_fptr(size_t pointer, object::SectionRef *Section, int64_t *slide, llvm::DIContext **context,
10391052
bool onlySysImg, bool *isSysImg, void **saddr, char **name, char **filename)
10401053
{
1041-
*obj = NULL;
1054+
*Section = object::SectionRef();
10421055
*context = NULL;
1043-
*slide = 0;
1044-
*section_slide = 0;
10451056
// On Windows and FreeBSD, `dladdr` (or its equivalent) returns the closest exported symbol
10461057
// without checking the size.
10471058
// This causes the lookup to return incorrect non-NULL result for local functions
@@ -1119,12 +1130,11 @@ bool jl_dylib_DI_for_fptr(size_t pointer, const llvm::object::ObjectFile **obj,
11191130
fname = dlinfo.dli_fname;
11201131
#endif // ifdef _OS_WINDOWS_
11211132
auto &entry = find_object_file(fbase, fname);
1122-
*obj = entry.obj;
1123-
*context = entry.ctx;
11241133
*slide = entry.slide;
1125-
*section_slide = entry.section_slide;
1126-
get_function_name_and_base(entry.obj, insysimage, saddr, name, pointer, entry.slide,
1127-
untrusted_dladdr);
1134+
*context = entry.ctx;
1135+
if (entry.obj)
1136+
*Section = getModuleSectionForAddress(entry.obj, pointer + entry.slide);
1137+
get_function_name_and_base(*Section, pointer, entry.slide, insysimage, saddr, name, untrusted_dladdr);
11281138
return true;
11291139
}
11301140

@@ -1153,12 +1163,12 @@ static int jl_getDylibFunctionInfo(jl_frame_t **frames, size_t pointer, int skip
11531163
}
11541164
jl_in_stackwalk = 0;
11551165
#endif
1156-
const object::ObjectFile *object;
1166+
object::SectionRef Section;
11571167
llvm::DIContext *context = NULL;
1168+
int64_t slide;
11581169
bool isSysImg;
11591170
void *saddr;
1160-
int64_t slide, section_slide;
1161-
if (!jl_dylib_DI_for_fptr(pointer, &object, &context, &slide, &section_slide, skipC, &isSysImg, &saddr, &frame0->func_name, &frame0->file_name)) {
1171+
if (!jl_dylib_DI_for_fptr(pointer, &Section, &slide, &context, skipC, &isSysImg, &saddr, &frame0->func_name, &frame0->file_name)) {
11621172
frame0->fromC = 1;
11631173
return 1;
11641174
}
@@ -1180,26 +1190,24 @@ static int jl_getDylibFunctionInfo(jl_frame_t **frames, size_t pointer, int skip
11801190
}
11811191
}
11821192
}
1183-
return lookup_pointer(object, context, frames, pointer + slide, isSysImg, noInline);
1193+
return lookup_pointer(Section, context, frames, pointer, slide, isSysImg, noInline);
11841194
}
11851195

1186-
int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide, int64_t *section_slide,
1187-
const object::ObjectFile **object,
1188-
llvm::DIContext **context
1189-
)
1196+
int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide,
1197+
object::SectionRef *Section, llvm::DIContext **context) JL_NOTSAFEPOINT
11901198
{
11911199
int found = 0;
1192-
*slide = 0;
11931200
std::map<size_t, ObjectInfo, revcomp> &objmap = jl_jit_events->getObjectMap();
11941201
std::map<size_t, ObjectInfo, revcomp>::iterator fit = objmap.lower_bound(fptr);
11951202

1203+
if (symsize)
1204+
*symsize = 0;
11961205
if (fit != objmap.end() && fptr < fit->first + fit->second.SectionSize) {
1197-
if (symsize)
1198-
*symsize = 0;
1199-
if (section_slide)
1200-
*section_slide = fit->second.slide;
1201-
*object = fit->second.object;
1206+
*slide = fit->second.slide;
1207+
*Section = fit->second.Section;
12021208
if (context) {
1209+
if (fit->second.context == nullptr)
1210+
fit->second.context = DWARFContext::create(*fit->second.object).release();
12031211
*context = fit->second.context;
12041212
}
12051213
found = 1;
@@ -1208,54 +1216,6 @@ int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide, int64_t *se
12081216
return found;
12091217
}
12101218

1211-
extern "C"
1212-
JL_DLLEXPORT jl_value_t *jl_get_dobj_data(uint64_t fptr)
1213-
{
1214-
jl_ptls_t ptls = jl_get_ptls_states();
1215-
// Used by Gallium.jl
1216-
const object::ObjectFile *object = NULL;
1217-
DIContext *context;
1218-
int64_t slide, section_slide;
1219-
int8_t gc_state = jl_gc_safe_enter(ptls);
1220-
if (!jl_DI_for_fptr(fptr, NULL, &slide, NULL, &object, NULL))
1221-
if (!jl_dylib_DI_for_fptr(fptr, &object, &context, &slide, &section_slide, false, NULL, NULL, NULL, NULL)) {
1222-
jl_gc_safe_leave(ptls, gc_state);
1223-
return jl_nothing;
1224-
}
1225-
jl_gc_safe_leave(ptls, gc_state);
1226-
if (object == NULL)
1227-
return jl_nothing;
1228-
return (jl_value_t*)jl_ptr_to_array_1d((jl_value_t*)jl_array_uint8_type,
1229-
const_cast<char*>(object->getData().data()),
1230-
object->getData().size(), false);
1231-
}
1232-
1233-
extern "C"
1234-
JL_DLLEXPORT uint64_t jl_get_section_start(uint64_t fptr)
1235-
{
1236-
jl_ptls_t ptls = jl_get_ptls_states();
1237-
// Used by Gallium.jl
1238-
int8_t gc_state = jl_gc_safe_enter(ptls);
1239-
std::map<size_t, ObjectInfo, revcomp> &objmap = jl_jit_events->getObjectMap();
1240-
std::map<size_t, ObjectInfo, revcomp>::iterator fit = objmap.lower_bound(fptr);
1241-
1242-
uint64_t ret = 0;
1243-
if (fit != objmap.end() && fptr < fit->first + fit->second.SectionSize) {
1244-
ret = fit->first;
1245-
}
1246-
else {
1247-
obfiletype::iterator objit = objfilemap.lower_bound(fptr);
1248-
// Ideally we'd have a containment check here, but we can't really
1249-
// get the shared library size easily.
1250-
if (objit != objfilemap.end()) {
1251-
ret = objit->first;
1252-
}
1253-
}
1254-
uv_rwlock_rdunlock(&threadsafe);
1255-
jl_gc_safe_leave(ptls, gc_state);
1256-
return ret;
1257-
}
1258-
12591219
// Set *name and *filename to either NULL or malloc'd string
12601220
int jl_getFunctionInfo(jl_frame_t **frames_out, size_t pointer, int skipC, int noInline) JL_NOTSAFEPOINT
12611221
{
@@ -1267,12 +1227,12 @@ int jl_getFunctionInfo(jl_frame_t **frames_out, size_t pointer, int skipC, int n
12671227
*frames_out = frames;
12681228

12691229
llvm::DIContext *context;
1270-
const object::ObjectFile *object;
1230+
object::SectionRef Section;
1231+
int64_t slide;
12711232
uint64_t symsize;
1272-
int64_t slide = 0;
1273-
if (jl_DI_for_fptr(pointer, &symsize, &slide, NULL, &object, &context)) {
1233+
if (jl_DI_for_fptr(pointer, &symsize, &slide, &Section, &context)) {
12741234
frames[0].linfo = jl_jit_events->lookupLinfo(pointer);
1275-
int nf = lookup_pointer(object, context, frames_out, pointer+slide, 1, noInline);
1235+
int nf = lookup_pointer(Section, context, frames_out, pointer, slide, true, noInline);
12761236
return nf;
12771237
}
12781238
return jl_getDylibFunctionInfo(frames_out, pointer, skipC, noInline);

src/debuginfo.h

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,21 @@
22

33
// Declarations for debuginfo.cpp
44

5-
extern int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide, int64_t *section_slide,
6-
const object::ObjectFile **object,
7-
llvm::DIContext **context);
5+
int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide,
6+
llvm::object::SectionRef *Section, llvm::DIContext **context) JL_NOTSAFEPOINT;
87

9-
extern bool jl_dylib_DI_for_fptr(size_t pointer, const object::ObjectFile **object, llvm::DIContext **context,
10-
int64_t *slide, int64_t *section_slide,
11-
bool onlySysImg, bool *isSysImg, void **saddr, char **name, char **filename);
8+
bool jl_dylib_DI_for_fptr(size_t pointer, llvm::object::SectionRef *Section, int64_t *slide, llvm::DIContext **context,
9+
bool onlySysImg, bool *isSysImg, void **saddr, char **name, char **filename);
1210

1311
#if JL_LLVM_VERSION >= 90000
14-
extern uint64_t getModuleSectionIndexForAddress(const object::ObjectFile *obj, uint64_t Address);
15-
static object::SectionedAddress makeAddress(const llvm::object::ObjectFile *object, uint64_t address)
12+
static object::SectionedAddress makeAddress(
13+
llvm::object::SectionRef Section, uint64_t address)
1614
{
17-
return object::SectionedAddress{address, getModuleSectionIndexForAddress(object, address)};
15+
return object::SectionedAddress{address, Section.getIndex()};
1816
}
1917
#else
20-
static uint64_t makeAddress(const llvm::object::ObjectFile *object, uint64_t address)
18+
static uint64_t makeAddress(llvm::object::SectionRef Section, uint64_t address)
2119
{
22-
(void)object;
2320
return address;
2421
}
2522
#endif

0 commit comments

Comments
 (0)