Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : #include "platform.h"
4 : :
5 : : #include "llvm-version.h"
6 : : #include <llvm/DebugInfo/DIContext.h>
7 : : #include <llvm/DebugInfo/DWARF/DWARFContext.h>
8 : : #include <llvm/Object/SymbolSize.h>
9 : : #include <llvm/Support/MemoryBuffer.h>
10 : : #include <llvm/IR/Function.h>
11 : : #include <llvm/ADT/StringRef.h>
12 : : #include <llvm/ADT/StringMap.h>
13 : : #include <llvm/IR/DebugInfo.h>
14 : : #include <llvm/IR/DataLayout.h>
15 : : #include <llvm/IR/Mangler.h>
16 : : #include <llvm/ExecutionEngine/RTDyldMemoryManager.h>
17 : : #include <llvm/ExecutionEngine/RuntimeDyld.h>
18 : : #include <llvm/BinaryFormat/Magic.h>
19 : : #include <llvm/Object/MachO.h>
20 : : #include <llvm/Object/COFF.h>
21 : : #include <llvm/Object/ELFObjectFile.h>
22 : :
23 : : using namespace llvm;
24 : :
25 : : #include "julia.h"
26 : : #include "julia_internal.h"
27 : : #include "debuginfo.h"
28 : : #if defined(_OS_LINUX_)
29 : : # include <link.h>
30 : : #endif
31 : : #include "processor.h"
32 : :
33 : : #include <string>
34 : : #include <map>
35 : : #include <vector>
36 : : #include <set>
37 : : #include <mutex>
38 : : #include "julia_assert.h"
39 : :
40 : : #ifdef _OS_DARWIN_
41 : : #include <CoreFoundation/CoreFoundation.h>
42 : : #endif
43 : :
44 : : #include "jitlayers.h"
45 : :
46 : 115280 : static JITDebugInfoRegistry &getJITDebugRegistry() JL_NOTSAFEPOINT {
47 : 115280 : return jl_ExecutionEngine->getDebugInfoRegistry();
48 : : }
49 : :
50 : : struct debug_link_info {
51 : : StringRef filename;
52 : : uint32_t crc32;
53 : : };
54 : :
55 : : #if (defined(_OS_LINUX_) || defined(_OS_FREEBSD_) || (defined(_OS_DARWIN_) && defined(LLVM_SHLIB)))
56 : : extern "C" void __register_frame(void*);
57 : : extern "C" void __deregister_frame(void*);
58 : :
59 : : template <typename callback>
60 : 80736 : static void processFDEs(const char *EHFrameAddr, size_t EHFrameSize, callback f)
61 : : {
62 : 80736 : const char *P = EHFrameAddr;
63 : 80736 : const char *End = P + EHFrameSize;
64 : 240310 : do {
65 : 321046 : const char *Entry = P;
66 : 321046 : P += 4;
67 : : assert(P <= End);
68 : 321046 : uint32_t Length = *(const uint32_t*)Entry;
69 : : // Length == 0: Terminator
70 [ + + ]: 321046 : if (Length == 0)
71 : 80736 : break;
72 : : assert(P + Length <= End);
73 : 240310 : uint32_t Offset = *(const uint32_t*)P;
74 : : // Offset == 0: CIE
75 [ + + ]: 240310 : if (Offset != 0)
76 : 159574 : f(Entry);
77 : 240310 : P += Length;
78 [ + - ]: 240310 : } while (P != End);
79 : 80736 : }
80 : : #endif
81 : :
82 : 73617 : std::string JITDebugInfoRegistry::mangle(StringRef Name, const DataLayout &DL) JL_NOTSAFEPOINT
83 : : {
84 : 73617 : std::string MangledName;
85 : : {
86 : 73617 : raw_string_ostream MangledNameStream(MangledName);
87 : 73617 : Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
88 : : }
89 : 73617 : return MangledName;
90 : : }
91 : :
92 : 73617 : void JITDebugInfoRegistry::add_code_in_flight(StringRef name, jl_code_instance_t *codeinst, const DataLayout &DL) JL_NOTSAFEPOINT {
93 : 73617 : (**codeinst_in_flight)[mangle(name, DL)] = codeinst;
94 : 73617 : }
95 : :
96 : 102 : jl_method_instance_t *JITDebugInfoRegistry::lookupLinfo(size_t pointer) JL_NOTSAFEPOINT
97 : : {
98 : 102 : jl_lock_profile();
99 : 102 : auto region = linfomap.lower_bound(pointer);
100 : 102 : jl_method_instance_t *linfo = NULL;
101 [ + - + + : 102 : if (region != linfomap.end() && pointer < region->first + region->second.first)
+ + ]
102 : 91 : linfo = region->second.second;
103 : 102 : jl_unlock_profile();
104 : 102 : return linfo;
105 : : }
106 : :
107 : : //Protected by debuginfo_asyncsafe (profile) lock
108 : : JITDebugInfoRegistry::objectmap_t &
109 : 366 : JITDebugInfoRegistry::getObjectMap() JL_NOTSAFEPOINT
110 : : {
111 : 366 : return objectmap;
112 : : }
113 : :
114 : 2 : void JITDebugInfoRegistry::set_sysimg_info(sysimg_info_t info) JL_NOTSAFEPOINT {
115 : 2 : (**this->sysimg_info) = info;
116 : 2 : }
117 : :
118 : : JITDebugInfoRegistry::Locked<JITDebugInfoRegistry::sysimg_info_t>::ConstLockT
119 : 522 : JITDebugInfoRegistry::get_sysimg_info() const JL_NOTSAFEPOINT {
120 : 522 : return *this->sysimg_info;
121 : : }
122 : :
123 : : JITDebugInfoRegistry::Locked<JITDebugInfoRegistry::objfilemap_t>::LockT
124 : 272 : JITDebugInfoRegistry::get_objfile_map() JL_NOTSAFEPOINT {
125 : 272 : return *this->objfilemap;
126 : : }
127 : :
128 : 15 : JITDebugInfoRegistry::JITDebugInfoRegistry() JL_NOTSAFEPOINT { }
129 : :
130 : : struct unw_table_entry
131 : : {
132 : : int32_t start_ip_offset;
133 : : int32_t fde_offset;
134 : : };
135 : :
136 : : // some actions aren't signal (especially profiler) safe so we acquire a lock
137 : : // around them to establish a mutual exclusion with unwinding from a signal
138 : : template <typename T>
139 : 160523 : static void jl_profile_atomic(T f)
140 : : {
141 : : assert(0 == jl_lock_profile_rd_held());
142 : 160523 : jl_lock_profile_wr();
143 : : #ifndef _OS_WINDOWS_
144 : : sigset_t sset;
145 : : sigset_t oset;
146 : 160523 : sigfillset(&sset);
147 : 160523 : pthread_sigmask(SIG_BLOCK, &sset, &oset);
148 : : #endif
149 : 160523 : f();
150 : : #ifndef _OS_WINDOWS_
151 : 160523 : pthread_sigmask(SIG_SETMASK, &oset, NULL);
152 : : #endif
153 : 160523 : jl_unlock_profile_wr();
154 : 160523 : }
155 : :
156 : :
157 : : // --- storing and accessing source location metadata ---
158 : 73617 : void jl_add_code_in_flight(StringRef name, jl_code_instance_t *codeinst, const DataLayout &DL)
159 : : {
160 : 73617 : getJITDebugRegistry().add_code_in_flight(name, codeinst, DL);
161 : 73617 : }
162 : :
163 : :
164 : : #if defined(_OS_WINDOWS_)
165 : : static void create_PRUNTIME_FUNCTION(uint8_t *Code, size_t Size, StringRef fnname,
166 : : uint8_t *Section, size_t Allocated, uint8_t *UnwindData)
167 : : {
168 : : // GC safe
169 : : DWORD mod_size = 0;
170 : : #if defined(_CPU_X86_64_)
171 : : PRUNTIME_FUNCTION tbl = (PRUNTIME_FUNCTION)malloc_s(sizeof(RUNTIME_FUNCTION));
172 : : tbl->BeginAddress = (DWORD)(Code - Section);
173 : : tbl->EndAddress = (DWORD)(Code - Section + Size);
174 : : tbl->UnwindData = (DWORD)(UnwindData - Section);
175 : : assert(Code >= Section && Code + Size <= Section + Allocated);
176 : : assert(UnwindData >= Section && UnwindData <= Section + Allocated);
177 : : #else // defined(_CPU_X86_64_)
178 : : Section += (uintptr_t)Code;
179 : : mod_size = Size;
180 : : #endif
181 : : if (0) {
182 : : uv_mutex_lock(&jl_in_stackwalk);
183 : : if (mod_size && !SymLoadModuleEx(GetCurrentProcess(), NULL, NULL, NULL, (DWORD64)Section, mod_size, NULL, SLMFLAG_VIRTUAL)) {
184 : : static int warned = 0;
185 : : if (!warned) {
186 : : jl_printf(JL_STDERR, "WARNING: failed to insert module info for backtrace: %lu\n", GetLastError());
187 : : warned = 1;
188 : : }
189 : : }
190 : : else {
191 : : size_t len = fnname.size()+1;
192 : : if (len > MAX_SYM_NAME)
193 : : len = MAX_SYM_NAME;
194 : : char *name = (char*)alloca(len);
195 : : memcpy(name, fnname.data(), len-1);
196 : : name[len-1] = 0;
197 : : if (!SymAddSymbol(GetCurrentProcess(), (ULONG64)Section, name,
198 : : (DWORD64)Code, (DWORD)Size, 0)) {
199 : : jl_printf(JL_STDERR, "WARNING: failed to insert function name %s into debug info: %lu\n", name, GetLastError());
200 : : }
201 : : }
202 : : uv_mutex_unlock(&jl_in_stackwalk);
203 : : }
204 : : #if defined(_CPU_X86_64_)
205 : : jl_profile_atomic([&]() {
206 : : if (!RtlAddFunctionTable(tbl, 1, (DWORD64)Section)) {
207 : : static int warned = 0;
208 : : if (!warned) {
209 : : jl_printf(JL_STDERR, "WARNING: failed to insert function stack unwind info: %lu\n", GetLastError());
210 : : warned = 1;
211 : : }
212 : : }
213 : : });
214 : : #endif
215 : : }
216 : : #endif
217 : :
218 : 40399 : void JITDebugInfoRegistry::registerJITObject(const object::ObjectFile &Object,
219 : : std::function<uint64_t(const StringRef &)> getLoadAddress,
220 : : std::function<void*(void*)> lookupWriteAddress)
221 : : {
222 : 40399 : object::section_iterator EndSection = Object.section_end();
223 : :
224 : : #ifdef _CPU_ARM_
225 : : // ARM does not have/use .eh_frame
226 : : uint64_t arm_exidx_addr = 0;
227 : : size_t arm_exidx_len = 0;
228 : : uint64_t arm_text_addr = 0;
229 : : size_t arm_text_len = 0;
230 : : for (auto §ion: Object.sections()) {
231 : : bool istext = false;
232 : : if (section.isText()) {
233 : : istext = true;
234 : : }
235 : : else {
236 : : auto sName = section.getName();
237 : : if (!sName)
238 : : continue;
239 : : if (sName.get() != ".ARM.exidx") {
240 : : continue;
241 : : }
242 : : }
243 : : uint64_t loadaddr = getLoadAddress(section.getName().get());
244 : : size_t seclen = section.getSize();
245 : : if (istext) {
246 : : arm_text_addr = loadaddr;
247 : : arm_text_len = seclen;
248 : : if (!arm_exidx_addr) {
249 : : continue;
250 : : }
251 : : }
252 : : else {
253 : : arm_exidx_addr = loadaddr;
254 : : arm_exidx_len = seclen;
255 : : if (!arm_text_addr) {
256 : : continue;
257 : : }
258 : : }
259 : : unw_dyn_info_t *di = new unw_dyn_info_t;
260 : : di->gp = 0;
261 : : di->format = UNW_INFO_FORMAT_ARM_EXIDX;
262 : : di->start_ip = (uintptr_t)arm_text_addr;
263 : : di->end_ip = (uintptr_t)(arm_text_addr + arm_text_len);
264 : : di->u.rti.name_ptr = 0;
265 : : di->u.rti.table_data = arm_exidx_addr;
266 : : di->u.rti.table_len = arm_exidx_len;
267 : : jl_profile_atomic([&]() {
268 : : _U_dyn_register(di);
269 : : });
270 : : break;
271 : : }
272 : : #endif
273 : :
274 : : #if defined(_OS_WINDOWS_)
275 : : uint64_t SectionAddrCheck = 0;
276 : : uint64_t SectionLoadCheck = 0; (void)SectionLoadCheck;
277 : : uint64_t SectionWriteCheck = 0; (void)SectionWriteCheck;
278 : : uint8_t *UnwindData = NULL;
279 : : #if defined(_CPU_X86_64_)
280 : : uint8_t *catchjmp = NULL;
281 : : for (const object::SymbolRef &sym_iter : Object.symbols()) {
282 : : StringRef sName = cantFail(sym_iter.getName());
283 : : if (sName.equals("__UnwindData") || sName.equals("__catchjmp")) {
284 : : uint64_t Addr = cantFail(sym_iter.getAddress());
285 : : auto Section = cantFail(sym_iter.getSection());
286 : : assert(Section != EndSection && Section->isText());
287 : : uint64_t SectionAddr = Section->getAddress();
288 : : StringRef secName = cantFail(Section->getName());
289 : : uint64_t SectionLoadAddr = getLoadAddress(secName);
290 : : assert(SectionLoadAddr);
291 : : if (SectionAddrCheck) // assert that all of the Sections are at the same location
292 : : assert(SectionAddrCheck == SectionAddr &&
293 : : SectionLoadCheck == SectionLoadAddr);
294 : : SectionAddrCheck = SectionAddr;
295 : : SectionLoadCheck = SectionLoadAddr;
296 : : SectionWriteCheck = SectionLoadAddr;
297 : : if (lookupWriteAddress)
298 : : SectionWriteCheck = (uintptr_t)lookupWriteAddress((void*)SectionLoadAddr);
299 : : Addr += SectionWriteCheck - SectionLoadCheck;
300 : : if (sName.equals("__UnwindData")) {
301 : : UnwindData = (uint8_t*)Addr;
302 : : }
303 : : else if (sName.equals("__catchjmp")) {
304 : : catchjmp = (uint8_t*)Addr;
305 : : }
306 : : }
307 : : }
308 : : assert(catchjmp);
309 : : assert(UnwindData);
310 : : assert(SectionAddrCheck);
311 : : assert(SectionLoadCheck);
312 : : assert(!memcmp(catchjmp, "\0\0\0\0\0\0\0\0\0\0\0\0", 12) &&
313 : : !memcmp(UnwindData, "\0\0\0\0\0\0\0\0\0\0\0\0", 12));
314 : : catchjmp[0] = 0x48;
315 : : catchjmp[1] = 0xb8; // mov RAX, QWORD PTR [&__julia_personality]
316 : : *(uint64_t*)(&catchjmp[2]) = (uint64_t)&__julia_personality;
317 : : catchjmp[10] = 0xff;
318 : : catchjmp[11] = 0xe0; // jmp RAX
319 : : UnwindData[0] = 0x09; // version info, UNW_FLAG_EHANDLER
320 : : UnwindData[1] = 4; // size of prolog (bytes)
321 : : UnwindData[2] = 2; // count of unwind codes (slots)
322 : : UnwindData[3] = 0x05; // frame register (rbp) = rsp
323 : : UnwindData[4] = 4; // second instruction
324 : : UnwindData[5] = 0x03; // mov RBP, RSP
325 : : UnwindData[6] = 1; // first instruction
326 : : UnwindData[7] = 0x50; // push RBP
327 : : *(DWORD*)&UnwindData[8] = (DWORD)(catchjmp - (uint8_t*)SectionWriteCheck); // relative location of catchjmp
328 : : UnwindData -= SectionWriteCheck - SectionLoadCheck;
329 : : #endif // defined(_OS_X86_64_)
330 : : #endif // defined(_OS_WINDOWS_)
331 : :
332 : 80798 : auto symbols = object::computeSymbolSizes(Object);
333 : 40399 : bool first = true;
334 [ + + ]: 682097 : for (const auto &sym_size : symbols) {
335 : 641698 : const object::SymbolRef &sym_iter = sym_size.first;
336 : 641698 : object::SymbolRef::Type SymbolType = cantFail(sym_iter.getType());
337 [ + + ]: 641698 : if (SymbolType != object::SymbolRef::ST_Function) continue;
338 : 79787 : uint64_t Addr = cantFail(sym_iter.getAddress());
339 : 79787 : auto Section = cantFail(sym_iter.getSection());
340 [ - + ]: 79787 : if (Section == EndSection) continue;
341 [ - + ]: 79787 : if (!Section->isText()) continue;
342 : 79787 : uint64_t SectionAddr = Section->getAddress();
343 : 79787 : StringRef secName = cantFail(Section->getName());
344 : 79787 : uint64_t SectionLoadAddr = getLoadAddress(secName);
345 : 79787 : Addr -= SectionAddr - SectionLoadAddr;
346 : 79787 : StringRef sName = cantFail(sym_iter.getName());
347 : 79787 : uint64_t SectionSize = Section->getSize();
348 : 79787 : size_t Size = sym_size.second;
349 : : #if defined(_OS_WINDOWS_)
350 : : if (SectionAddrCheck)
351 : : assert(SectionAddrCheck == SectionAddr &&
352 : : SectionLoadCheck == SectionLoadAddr);
353 : : SectionAddrCheck = SectionAddr;
354 : : SectionLoadCheck = SectionLoadAddr;
355 : : create_PRUNTIME_FUNCTION(
356 : : (uint8_t*)(uintptr_t)Addr, (size_t)Size, sName,
357 : : (uint8_t*)(uintptr_t)SectionLoadAddr, (size_t)SectionSize, UnwindData);
358 : : #endif
359 : 79787 : jl_code_instance_t *codeinst = NULL;
360 : : {
361 : 159574 : auto lock = *this->codeinst_in_flight;
362 : 79787 : auto &codeinst_in_flight = *lock;
363 : 79787 : StringMap<jl_code_instance_t*>::iterator codeinst_it = codeinst_in_flight.find(sName);
364 [ + + ]: 79787 : if (codeinst_it != codeinst_in_flight.end()) {
365 : 73617 : codeinst = codeinst_it->second;
366 : 73617 : codeinst_in_flight.erase(codeinst_it);
367 : : }
368 : : }
369 : 79787 : jl_profile_atomic([&]() {
370 [ + + ]: 79787 : if (codeinst)
371 : 73617 : linfomap[Addr] = std::make_pair(Size, codeinst->def);
372 [ + + ]: 79787 : if (first) {
373 : 40368 : objectmap[SectionLoadAddr] = {&Object,
374 : 40368 : (size_t)SectionSize,
375 : 40368 : (ptrdiff_t)(SectionAddr - SectionLoadAddr),
376 : 40368 : *Section,
377 : : nullptr,
378 : : };
379 : 40368 : first = false;
380 : : }
381 : 79787 : });
382 : : }
383 : 40399 : }
384 : :
385 : 40399 : void jl_register_jit_object(const object::ObjectFile &Object,
386 : : std::function<uint64_t(const StringRef &)> getLoadAddress,
387 : : std::function<void *(void *)> lookupWriteAddress)
388 : : {
389 : 40399 : getJITDebugRegistry().registerJITObject(Object, getLoadAddress, lookupWriteAddress);
390 : 40399 : }
391 : :
392 : : // TODO: convert the safe names from aotcomile.cpp:makeSafeName back into symbols
393 : 0 : static std::pair<char *, bool> jl_demangle(const char *name) JL_NOTSAFEPOINT
394 : : {
395 : : // This function is not allowed to reference any TLS variables since
396 : : // it can be called from an unmanaged thread on OSX.
397 : 0 : const char *start = name + 6;
398 : 0 : const char *end = name + strlen(name);
399 : : char *ret;
400 [ # # ]: 0 : if (end <= start)
401 : 0 : goto done;
402 [ # # ]: 0 : if (strncmp(name, "japi1_", 6) &&
403 [ # # ]: 0 : strncmp(name, "japi3_", 6) &&
404 [ # # ]: 0 : strncmp(name, "julia_", 6) &&
405 [ # # ]: 0 : strncmp(name, "jsys1_", 6) &&
406 [ # # ]: 0 : strncmp(name, "jlsys_", 6))
407 : 0 : goto done;
408 [ # # ]: 0 : if (*start == '\0')
409 : 0 : goto done;
410 [ # # ]: 0 : while (*(--end) != '_') {
411 : 0 : char c = *end;
412 [ # # # # ]: 0 : if (c < '0' || c > '9')
413 : 0 : goto done;
414 : : }
415 [ # # ]: 0 : if (end <= start)
416 : 0 : goto done;
417 : 0 : ret = (char*)malloc_s(end - start + 1);
418 : 0 : memcpy(ret, start, end - start);
419 : 0 : ret[end - start] = '\0';
420 : 0 : return std::make_pair(ret, true);
421 : 0 : done:
422 : 0 : return std::make_pair(strdup(name), false);
423 : : }
424 : :
425 : : // *frames is a one element array containing whatever we could come up
426 : : // with for the current frame. here we'll try to expand it using debug info
427 : : // func_name and file_name are either NULL or malloc'd pointers
428 : 417 : static int lookup_pointer(
429 : : object::SectionRef Section, DIContext *context,
430 : : jl_frame_t **frames, size_t pointer, int64_t slide,
431 : : bool demangle, bool noInline) JL_NOTSAFEPOINT
432 : : {
433 : : // This function is not allowed to reference any TLS variables
434 : : // since it can be called from an unmanaged thread on OSX.
435 [ + + - + : 417 : if (!context || !Section.getObject()) {
+ + ]
436 [ + + ]: 54 : if (demangle) {
437 : 20 : char *oldname = (*frames)[0].func_name;
438 [ - + ]: 20 : if (oldname != NULL) {
439 : 0 : std::pair<char *, bool> demangled = jl_demangle(oldname);
440 : 0 : (*frames)[0].func_name = demangled.first;
441 : 0 : (*frames)[0].fromC = !demangled.second;
442 : 0 : free(oldname);
443 : : }
444 : : else {
445 : : // We do this to hide the jlcall wrappers when getting julia backtraces,
446 : : // but it is still good to have them for regular lookup of C frames.
447 : : // Technically not true, but we don't want them
448 : : // in julia backtraces, so close enough
449 : 20 : (*frames)[0].fromC = 1;
450 : : }
451 : : }
452 : 54 : return 1;
453 : : }
454 : : DILineInfoSpecifier infoSpec(DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
455 : 363 : DILineInfoSpecifier::FunctionNameKind::ShortName);
456 : :
457 : : // DWARFContext/DWARFUnit update some internal tables during these queries, so
458 : : // a lock is needed.
459 : : assert(0 == jl_lock_profile_rd_held());
460 : 363 : jl_lock_profile_wr();
461 : 726 : auto inlineInfo = context->getInliningInfoForAddress(makeAddress(Section, pointer + slide), infoSpec);
462 : 363 : jl_unlock_profile_wr();
463 : :
464 : 363 : int fromC = (*frames)[0].fromC;
465 : 363 : int n_frames = inlineInfo.getNumberOfFrames();
466 [ + + ]: 363 : if (n_frames == 0) {
467 : : // no line number info available in the context, return without the context
468 : 54 : return lookup_pointer(object::SectionRef(), NULL, frames, pointer, slide, demangle, noInline);
469 : : }
470 [ - + ]: 309 : if (noInline)
471 : 0 : n_frames = 1;
472 [ + + ]: 309 : if (n_frames > 1) {
473 : 28 : jl_frame_t *new_frames = (jl_frame_t*)calloc(sizeof(jl_frame_t), n_frames);
474 : 28 : memcpy(&new_frames[n_frames - 1], *frames, sizeof(jl_frame_t));
475 : 28 : free(*frames);
476 : 28 : *frames = new_frames;
477 : : }
478 [ + + ]: 705 : for (int i = 0; i < n_frames; i++) {
479 : 396 : bool inlined_frame = i != n_frames - 1;
480 : 792 : DILineInfo info;
481 [ + - ]: 396 : if (!noInline) {
482 : 396 : info = inlineInfo.getFrame(i);
483 : : }
484 : : else {
485 : 0 : jl_lock_profile_wr();
486 : 0 : info = context->getLineInfoForAddress(makeAddress(Section, pointer + slide), infoSpec);
487 : 0 : jl_unlock_profile_wr();
488 : : }
489 : :
490 : 396 : jl_frame_t *frame = &(*frames)[i];
491 : 792 : std::string func_name(info.FunctionName);
492 : :
493 [ + + ]: 396 : if (inlined_frame) {
494 : 87 : frame->inlined = 1;
495 : 87 : frame->fromC = fromC;
496 [ + - ]: 87 : if (!fromC) {
497 : 87 : std::size_t semi_pos = func_name.find(';');
498 [ + - ]: 87 : if (semi_pos != std::string::npos) {
499 : 87 : func_name = func_name.substr(0, semi_pos);
500 : 87 : frame->linfo = NULL; // TODO: if (new_frames[n_frames - 1].linfo) frame->linfo = lookup(func_name in linfo)?
501 : : }
502 : : }
503 : : }
504 : :
505 [ - + ]: 396 : if (func_name == "<invalid>")
506 : 0 : frame->func_name = NULL;
507 : : else
508 : 396 : jl_copy_str(&frame->func_name, func_name.c_str());
509 [ - + ]: 396 : if (!frame->func_name)
510 : 0 : frame->fromC = 1;
511 : :
512 : 396 : frame->line = info.Line;
513 : 792 : std::string file_name(info.FileName);
514 : :
515 [ - + ]: 396 : if (file_name == "<invalid>")
516 : 0 : frame->file_name = NULL;
517 : : else
518 : 396 : jl_copy_str(&frame->file_name, file_name.c_str());
519 : : }
520 : 309 : return n_frames;
521 : : }
522 : :
523 : : #ifdef _OS_DARWIN_
524 : : #include <mach-o/dyld.h>
525 : : #else
526 : : #define LC_UUID 0
527 : : #endif
528 : : #ifndef _OS_WINDOWS_
529 : : #include <dlfcn.h>
530 : : #endif
531 : :
532 : :
533 : :
534 : : #if defined(_OS_DARWIN_) && defined(LLVM_SHLIB)
535 : :
536 : : void JITDebugInfoRegistry::libc_frames_t::libc_register_frame(const char *Entry) {
537 : : auto libc_register_frame_ = jl_atomic_load_relaxed(&this->libc_register_frame_);
538 : : if (!libc_register_frame_) {
539 : : libc_register_frame_ = (void(*)(void*))dlsym(RTLD_NEXT, "__register_frame");
540 : : jl_atomic_store_release(&this->libc_register_frame_, libc_register_frame_);
541 : : }
542 : : assert(libc_register_frame_);
543 : : jl_profile_atomic([&]() {
544 : : libc_register_frame_(const_cast<char *>(Entry));
545 : : __register_frame(const_cast<char *>(Entry));
546 : : });
547 : : }
548 : :
549 : : void JITDebugInfoRegistry::libc_frames_t::libc_deregister_frame(const char *Entry) {
550 : : auto libc_deregister_frame_ = jl_atomic_load_relaxed(&this->libc_deregister_frame_);
551 : : if (!libc_deregister_frame_) {
552 : : libc_deregister_frame_ = (void(*)(void*))dlsym(RTLD_NEXT, "__deregister_frame");
553 : : jl_atomic_store_release(&this->libc_deregister_frame_, libc_deregister_frame_);
554 : : }
555 : : assert(libc_deregister_frame_);
556 : : jl_profile_atomic([&]() {
557 : : libc_deregister_frame_(const_cast<char *>(Entry));
558 : : __deregister_frame(const_cast<char *>(Entry));
559 : : });
560 : : }
561 : : #endif
562 : :
563 : 0 : static bool getObjUUID(llvm::object::MachOObjectFile *obj, uint8_t uuid[16]) JL_NOTSAFEPOINT
564 : : {
565 [ # # ]: 0 : for (auto Load : obj->load_commands())
566 : : {
567 [ # # ]: 0 : if (Load.C.cmd == LC_UUID) {
568 : 0 : memcpy(uuid, ((const MachO::uuid_command*)Load.Ptr)->uuid, 16);
569 : 0 : return true;
570 : : }
571 : : }
572 : 0 : return false;
573 : : }
574 : 11 : static debug_link_info getDebuglink(const object::ObjectFile &Obj) JL_NOTSAFEPOINT
575 : : {
576 : 11 : debug_link_info info = {};
577 [ + + ]: 468 : for (const object::SectionRef &Section: Obj.sections()) {
578 : 460 : Expected<StringRef> sName = Section.getName();
579 [ + - + + : 460 : if (sName && *sName == ".gnu_debuglink")
+ + ]
580 : : {
581 : 3 : auto found = Section.getContents();
582 [ + - ]: 3 : if (found) {
583 : 3 : StringRef Contents = *found;
584 : 3 : size_t length = Contents.find('\0');
585 : 3 : info.filename = Contents.substr(0, length);
586 : 3 : info.crc32 = *(const uint32_t*)Contents.substr(LLT_ALIGN(length + 1, 4), 4).data();
587 : 3 : break;
588 : : }
589 : : }
590 : : }
591 : 11 : return info;
592 : : }
593 : : /*
594 : : * crc function from http://svnweb.freebsd.org/base/head/sys/libkern/crc32.c (and lldb)
595 : : *
596 : : * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
597 : : * code or tables extracted from it, as desired without restriction.
598 : : */
599 : : static uint32_t
600 : 0 : calc_gnu_debuglink_crc32(const void *buf, size_t size)
601 : : {
602 : : static const uint32_t g_crc32_tab[] =
603 : : {
604 : : 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
605 : : 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
606 : : 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
607 : : 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
608 : : 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
609 : : 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
610 : : 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
611 : : 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
612 : : 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
613 : : 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
614 : : 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
615 : : 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
616 : : 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
617 : : 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
618 : : 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
619 : : 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
620 : : 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
621 : : 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
622 : : 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
623 : : 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
624 : : 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
625 : : 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
626 : : 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
627 : : 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
628 : : 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
629 : : 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
630 : : 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
631 : : 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
632 : : 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
633 : : 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
634 : : 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
635 : : 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
636 : : 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
637 : : 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
638 : : 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
639 : : 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
640 : : 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
641 : : 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
642 : : 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
643 : : 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
644 : : 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
645 : : 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
646 : : 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
647 : : };
648 : 0 : const uint8_t *p = (const uint8_t *)buf;
649 : : uint32_t crc;
650 : :
651 : 0 : crc = ~0U;
652 [ # # ]: 0 : while (size--)
653 : 0 : crc = g_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
654 : 0 : return crc ^ ~0U;
655 : : }
656 : :
657 : : static Expected<object::OwningBinary<object::ObjectFile>>
658 : 9 : openDebugInfo(StringRef debuginfopath, const debug_link_info &info)
659 : : {
660 : 18 : auto SplitFile = MemoryBuffer::getFile(debuginfopath);
661 [ + - ]: 9 : if (std::error_code EC = SplitFile.getError()) {
662 : 9 : return errorCodeToError(EC);
663 : : }
664 : :
665 : 0 : uint32_t crc32 = calc_gnu_debuglink_crc32(
666 : 0 : SplitFile.get()->getBufferStart(),
667 : 0 : SplitFile.get()->getBufferSize());
668 [ # # ]: 0 : if (crc32 != info.crc32) {
669 : 0 : return errorCodeToError(object::object_error::arch_not_found);
670 : : }
671 : :
672 : : auto error_splitobj = object::ObjectFile::createObjectFile(
673 : 0 : SplitFile.get().get()->getMemBufferRef(),
674 : 0 : file_magic::unknown);
675 [ # # ]: 0 : if (!error_splitobj) {
676 : 0 : return error_splitobj.takeError();
677 : : }
678 : :
679 : : // successfully validated and loaded split debug info file
680 : 0 : return object::OwningBinary<object::ObjectFile>(
681 : 0 : std::move(error_splitobj.get()),
682 : 0 : std::move(SplitFile.get()));
683 : : }
684 : : extern "C" JL_DLLEXPORT
685 : 2 : void jl_register_fptrs_impl(uint64_t sysimage_base, const jl_sysimg_fptrs_t *fptrs,
686 : : jl_method_instance_t **linfos, size_t n)
687 : : {
688 : 2 : getJITDebugRegistry().set_sysimg_info({(uintptr_t) sysimage_base, *fptrs, linfos, n});
689 : 2 : }
690 : :
691 : : template<typename T>
692 : 12 : static inline void ignoreError(T &err) JL_NOTSAFEPOINT
693 : : {
694 : : #if !defined(NDEBUG) // Needed only with LLVM assertion build
695 : : consumeError(err.takeError());
696 : : #endif
697 : 12 : }
698 : :
699 : 261 : static void get_function_name_and_base(llvm::object::SectionRef Section, size_t pointer, int64_t slide, bool insysimage,
700 : : void **saddr, char **name, bool untrusted_dladdr) JL_NOTSAFEPOINT
701 : : {
702 : : // Assume we only need base address for sysimg for now
703 [ - + - - : 261 : if (!insysimage || !getJITDebugRegistry().get_sysimg_info()->sysimg_fptrs.base)
- + + - ]
704 : 261 : saddr = nullptr;
705 [ - + - - : 261 : bool needs_saddr = saddr && (!*saddr || untrusted_dladdr);
- - ]
706 [ + - + + : 261 : bool needs_name = name && (!*name || untrusted_dladdr);
- + ]
707 : : // Try platform specific methods first since they are usually faster
708 [ - + ]: 261 : if (needs_saddr) {
709 : : #if (defined(_OS_LINUX_) || defined(_OS_FREEBSD_)) && !defined(JL_DISABLE_LIBUNWIND)
710 : : unw_proc_info_t pip;
711 : : // Seems that libunwind may return NULL IP depending on what info it finds...
712 : 0 : if (unw_get_proc_info_by_ip(unw_local_addr_space, pointer,
713 [ # # # # : 0 : &pip, NULL) == 0 && pip.start_ip) {
# # ]
714 : 0 : *saddr = (void*)pip.start_ip;
715 : 0 : needs_saddr = false;
716 : : }
717 : : #endif
718 : : #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
719 : : DWORD64 ImageBase;
720 : : PRUNTIME_FUNCTION fn = RtlLookupFunctionEntry(pointer, &ImageBase, NULL);
721 : : if (fn) {
722 : : *saddr = (void*)(ImageBase + fn->BeginAddress);
723 : : needs_saddr = false;
724 : : }
725 : : #endif
726 : : }
727 [ + - + - : 261 : if (Section.getObject() && (needs_saddr || needs_name)) {
+ + + + ]
728 : 163 : size_t distance = (size_t)-1;
729 : 163 : object::SymbolRef sym_found;
730 [ + + ]: 3134860 : for (auto sym : Section.getObject()->symbols()) {
731 [ + + ]: 3134700 : if (!Section.containsSymbol(sym))
732 : 3019320 : continue;
733 : 1308310 : auto addr = sym.getAddress();
734 [ - + ]: 1308310 : if (!addr)
735 : 0 : continue;
736 : 1308310 : size_t symptr = addr.get();
737 [ + + ]: 1308310 : if (symptr > pointer + slide)
738 : 1093020 : continue;
739 : 215293 : size_t new_dist = pointer + slide - symptr;
740 [ + + ]: 215293 : if (new_dist > distance)
741 : 99912 : continue;
742 : 115381 : distance = new_dist;
743 : 115381 : sym_found = sym;
744 : : }
745 [ + + ]: 163 : if (distance != (size_t)-1) {
746 [ - + ]: 162 : if (needs_saddr) {
747 : 0 : uintptr_t addr = cantFail(sym_found.getAddress());
748 : 0 : *saddr = (void*)(addr - slide);
749 : 0 : needs_saddr = false;
750 : : }
751 [ + - ]: 162 : if (needs_name) {
752 [ + - ]: 324 : if (auto name_or_err = sym_found.getName()) {
753 : 162 : auto nameref = name_or_err.get();
754 : 162 : const char globalPrefix = // == DataLayout::getGlobalPrefix
755 : : #if defined(_OS_WINDOWS_) && !defined(_CPU_X86_64_)
756 : : '_';
757 : : #elif defined(_OS_DARWIN_)
758 : : '_';
759 : : #else
760 : : '\0';
761 : : #endif
762 : : if (globalPrefix) {
763 : : if (nameref[0] == globalPrefix)
764 : : nameref = nameref.drop_front();
765 : : #if defined(_OS_WINDOWS_) && !defined(_CPU_X86_64_)
766 : : else if (nameref[0] == '@') // X86_VectorCall
767 : : nameref = nameref.drop_front();
768 : : #endif
769 : : // else VectorCall, Assembly, Internal, etc.
770 : : }
771 : : #if defined(_OS_WINDOWS_) && !defined(_CPU_X86_64_)
772 : : nameref = nameref.split('@').first;
773 : : #endif
774 : 162 : size_t len = nameref.size();
775 : 162 : *name = (char*)realloc_s(*name, len + 1);
776 : 162 : memcpy(*name, nameref.data(), len);
777 : 162 : (*name)[len] = 0;
778 : 162 : needs_name = false;
779 : : }
780 : : }
781 : : }
782 : : }
783 : : #ifdef _OS_WINDOWS_
784 : : // For ntdll and msvcrt since we are currently only parsing DWARF debug info through LLVM
785 : : if (!insysimage && needs_name) {
786 : : static char frame_info_func[
787 : : sizeof(SYMBOL_INFO) +
788 : : MAX_SYM_NAME * sizeof(TCHAR)];
789 : : DWORD64 dwDisplacement64 = 0;
790 : : DWORD64 dwAddress = pointer;
791 : : PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)frame_info_func;
792 : : pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
793 : : pSymbol->MaxNameLen = MAX_SYM_NAME;
794 : : uv_mutex_lock(&jl_in_stackwalk);
795 : : if (SymFromAddr(GetCurrentProcess(), dwAddress, &dwDisplacement64, pSymbol)) {
796 : : // errors are ignored
797 : : jl_copy_str(name, pSymbol->Name);
798 : : }
799 : : uv_mutex_unlock(&jl_in_stackwalk);
800 : : }
801 : : #endif
802 : 261 : }
803 : :
804 : 261 : static objfileentry_t find_object_file(uint64_t fbase, StringRef fname) JL_NOTSAFEPOINT
805 : : {
806 : 261 : int isdarwin = 0, islinux = 0, iswindows = 0;
807 : : #if defined(_OS_DARWIN_)
808 : : isdarwin = 1;
809 : : #elif defined(_OS_LINUX_) || defined(_OS_FREEBSD_)
810 : 261 : islinux = 1;
811 : : #elif defined(_OS_WINDOWS_)
812 : : iswindows = 1;
813 : : #endif
814 : : (void)iswindows;
815 : :
816 : : // GOAL: Read debuginfo from file
817 : 261 : objfileentry_t entry{nullptr, nullptr, 0};
818 : 261 : auto success = getJITDebugRegistry().get_objfile_map()->emplace(fbase, entry);
819 [ + + ]: 261 : if (!success.second)
820 : : // Return cached value
821 : 250 : return success.first->second;
822 : :
823 : : // GOAL: Assign errorobj
824 : 11 : StringRef objpath;
825 : 22 : std::string debuginfopath;
826 : : uint8_t uuid[16], uuid2[16];
827 [ + - ]: 11 : if (isdarwin) {
828 : : // Hide Darwin symbols (e.g. CoreFoundation) from non-Darwin systems.
829 : : #ifdef _OS_DARWIN_
830 : :
831 : : size_t msize = (size_t)(((uint64_t)-1) - fbase);
832 : : std::unique_ptr<MemoryBuffer> membuf = MemoryBuffer::getMemBuffer(
833 : : StringRef((const char *)fbase, msize), "", false);
834 : : auto origerrorobj = llvm::object::ObjectFile::createObjectFile(
835 : : membuf->getMemBufferRef(), file_magic::unknown);
836 : : if (!origerrorobj) {
837 : : ignoreError(origerrorobj);
838 : : return entry;
839 : : }
840 : :
841 : : llvm::object::MachOObjectFile *morigobj = (llvm::object::MachOObjectFile*)
842 : : origerrorobj.get().get();
843 : :
844 : : // First find the uuid of the object file (we'll use this to make sure we find the
845 : : // correct debug symbol file).
846 : : if (!getObjUUID(morigobj, uuid))
847 : : return entry;
848 : :
849 : : // On macOS, debug symbols are not contained in the dynamic library.
850 : : // Use DBGCopyFullDSYMURLForUUID from the private DebugSymbols framework
851 : : // to make use of spotlight to find the dSYM file. If that fails, lookup
852 : : // the dSYM file in the same directory as the dynamic library. TODO: If
853 : : // the DebugSymbols framework is moved or removed, an alternative would
854 : : // be to directly query Spotlight for the dSYM bundle.
855 : :
856 : : typedef CFURLRef (*DBGCopyFullDSYMURLForUUIDfn)(CFUUIDRef, CFURLRef) JL_NOTSAFEPOINT;
857 : : DBGCopyFullDSYMURLForUUIDfn DBGCopyFullDSYMURLForUUID = NULL;
858 : :
859 : : // First, try to load the private DebugSymbols framework.
860 : : CFURLRef dsfmwkurl = CFURLCreateWithFileSystemPath(
861 : : kCFAllocatorDefault,
862 : : CFSTR("/System/Library/PrivateFrameworks/DebugSymbols.framework"),
863 : : kCFURLPOSIXPathStyle, true);
864 : : CFBundleRef dsfmwkbundle =
865 : : CFBundleCreate(kCFAllocatorDefault, dsfmwkurl);
866 : : CFRelease(dsfmwkurl);
867 : :
868 : : if (dsfmwkbundle) {
869 : : DBGCopyFullDSYMURLForUUID =
870 : : (DBGCopyFullDSYMURLForUUIDfn)CFBundleGetFunctionPointerForName(
871 : : dsfmwkbundle, CFSTR("DBGCopyFullDSYMURLForUUID"));
872 : : }
873 : :
874 : : if (DBGCopyFullDSYMURLForUUID != NULL) {
875 : : // Prepare UUID and shared object path URL.
876 : : CFUUIDRef objuuid = CFUUIDCreateWithBytes(
877 : : kCFAllocatorDefault, uuid[0], uuid[1], uuid[2], uuid[3],
878 : : uuid[4], uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], uuid[10],
879 : : uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
880 : : CFURLRef objurl = CFURLCreateFromFileSystemRepresentation(
881 : : kCFAllocatorDefault, (UInt8 const *)fname.data(),
882 : : (CFIndex)strlen(fname.data()), FALSE);
883 : :
884 : : // Call private DBGCopyFullDSYMURLForUUID() to find dSYM.
885 : : CFURLRef dsympathurl = DBGCopyFullDSYMURLForUUID(objuuid, objurl);
886 : : CFRelease(objuuid);
887 : : CFRelease(objurl);
888 : :
889 : : char objpathcstr[JL_PATH_MAX];
890 : : if (dsympathurl != NULL &&
891 : : CFURLGetFileSystemRepresentation(
892 : : dsympathurl, true, (UInt8 *)objpathcstr,
893 : : (CFIndex)sizeof(objpathcstr))) {
894 : : // The dSYM was found. Copy its path.
895 : : debuginfopath = objpathcstr;
896 : : objpath = debuginfopath;
897 : : CFRelease(dsympathurl);
898 : : }
899 : : }
900 : :
901 : : if (dsfmwkbundle) {
902 : : CFRelease(dsfmwkbundle);
903 : : }
904 : :
905 : : if (objpath.empty()) {
906 : : // Fall back to simple path relative to the dynamic library.
907 : : size_t sep = fname.rfind('/');
908 : : debuginfopath = fname.str();
909 : : debuginfopath += ".dSYM/Contents/Resources/DWARF/";
910 : : debuginfopath += fname.substr(sep + 1);
911 : : objpath = debuginfopath;
912 : : }
913 : : #endif
914 : : }
915 : : else {
916 : : // On Linux systems we need to mmap another copy because of the permissions on the mmap'ed shared library.
917 : : // On Windows we need to mmap another copy since reading the in-memory copy seems to return object_error:unexpected_eof
918 : 11 : objpath = fname;
919 : : }
920 : 22 : auto errorobj = llvm::object::ObjectFile::createObjectFile(objpath);
921 : :
922 : : // GOAL: Find obj, context, slide (if above succeeded)
923 [ + - ]: 11 : if (errorobj) {
924 : 11 : auto *debugobj = errorobj->getBinary();
925 : :
926 [ + - ]: 11 : if (islinux) {
927 : : // if the file has a .gnu_debuglink section,
928 : : // try to load its companion file instead
929 : : // in the expected locations
930 : : // for now, we don't support the build-id method
931 : 11 : debug_link_info info = getDebuglink(*debugobj);
932 [ + + ]: 11 : if (!info.filename.empty()) {
933 : 3 : size_t sep = fname.rfind('/');
934 : : Expected<object::OwningBinary<object::ObjectFile>>
935 : 6 : DebugInfo(errorCodeToError(std::make_error_code(std::errc::no_such_file_or_directory)));
936 : : // Can't find a way to construct an empty Expected object
937 : : // that can be ignored.
938 [ + - ]: 3 : if (fname.substr(sep + 1) != info.filename) {
939 : 3 : debuginfopath = fname.substr(0, sep + 1).str();
940 : 3 : debuginfopath += info.filename;
941 : 3 : ignoreError(DebugInfo);
942 : 3 : DebugInfo = openDebugInfo(debuginfopath, info);
943 : : }
944 [ + - ]: 3 : if (!DebugInfo) {
945 : 3 : debuginfopath = fname.substr(0, sep + 1).str();
946 : 3 : debuginfopath += ".debug/";
947 : 3 : debuginfopath += info.filename;
948 : 3 : ignoreError(DebugInfo);
949 : 3 : DebugInfo = openDebugInfo(debuginfopath, info);
950 : : }
951 [ + - ]: 3 : if (!DebugInfo) {
952 : 3 : debuginfopath = "/usr/lib/debug/";
953 : 3 : debuginfopath += fname.substr(0, sep + 1);
954 : 3 : debuginfopath += info.filename;
955 : 3 : ignoreError(DebugInfo);
956 : 3 : DebugInfo = openDebugInfo(debuginfopath, info);
957 : : }
958 [ - + ]: 3 : if (DebugInfo) {
959 : 0 : errorobj = std::move(DebugInfo);
960 : : // Yes, we've checked, and yes LLVM want us to check again.
961 : 0 : ignoreError(errorobj);
962 : 0 : debugobj = errorobj->getBinary();
963 : : }
964 : : else {
965 : 3 : ignoreError(DebugInfo);
966 : : }
967 : : }
968 : : }
969 : :
970 [ - + ]: 11 : if (isdarwin) {
971 : : // verify the UUID matches
972 [ # # # # ]: 0 : if (!getObjUUID((llvm::object::MachOObjectFile*)debugobj, uuid2) ||
973 [ # # ]: 0 : memcmp(uuid, uuid2, sizeof(uuid)) != 0) {
974 : 0 : return entry;
975 : : }
976 : : }
977 : :
978 : 11 : int64_t slide = 0;
979 [ - + ]: 11 : if (auto *OF = dyn_cast<const object::COFFObjectFile>(debugobj)) {
980 : : assert(iswindows);
981 : 0 : slide = OF->getImageBase() - fbase;
982 : : }
983 : : else {
984 : 11 : slide = -(int64_t)fbase;
985 : : }
986 : :
987 : 11 : auto context = DWARFContext::create(*debugobj).release();
988 : 11 : auto binary = errorobj->takeBinary();
989 : 11 : binary.first.release();
990 : 11 : binary.second.release();
991 : 11 : entry = {debugobj, context, slide};
992 : : // update cache
993 : 11 : (*getJITDebugRegistry().get_objfile_map())[fbase] = entry;
994 : : }
995 : : else {
996 : : // TODO: report the error instead of silently consuming it?
997 : : // jl_error might run into the same error again...
998 : 0 : ignoreError(errorobj);
999 : : }
1000 : 11 : return entry;
1001 : : }
1002 : :
1003 : : // from llvm::SymbolizableObjectFile
1004 : 261 : static object::SectionRef getModuleSectionForAddress(const object::ObjectFile *obj, uint64_t Address) JL_NOTSAFEPOINT
1005 : : {
1006 [ + - ]: 3431 : for (object::SectionRef Sec : obj->sections()) {
1007 [ + + - + : 3431 : if (!Sec.isText() || Sec.isVirtual())
+ + ]
1008 : 2374 : continue;
1009 [ + - + + : 1057 : if (Address >= Sec.getAddress() && Address < Sec.getAddress() + Sec.getSize())
+ + ]
1010 : 261 : return Sec;
1011 : : }
1012 : 0 : return object::SectionRef();
1013 : : }
1014 : :
1015 : :
1016 : 264 : bool jl_dylib_DI_for_fptr(size_t pointer, object::SectionRef *Section, int64_t *slide, llvm::DIContext **context,
1017 : : bool onlySysImg, bool *isSysImg, void **saddr, char **name, char **filename) JL_NOTSAFEPOINT
1018 : : {
1019 : 264 : *Section = object::SectionRef();
1020 : 264 : *context = NULL;
1021 : : // On Windows and FreeBSD, `dladdr` (or its equivalent) returns the closest exported symbol
1022 : : // without checking the size.
1023 : : // This causes the lookup to return incorrect non-NULL result for local functions
1024 : : // when better result is available through other methods.
1025 : : // macOS's `dladdr` returns local symbols and Linux's `dladdr`
1026 : : // checks the symbol size so they do not have this problem.
1027 : : // On systems with an untrusted dladdr, the result cannot be used for sysimg
1028 : : // (it's always wrong) and should in general be used only as the last fallback.
1029 : : #if defined(_OS_FREEBSD_) || defined(_OS_WINDOWS_)
1030 : : bool untrusted_dladdr = true;
1031 : : #else
1032 : 264 : bool untrusted_dladdr = false;
1033 : : #endif
1034 : :
1035 : : // GOAL: Determine containing Library
1036 : : // Assigning fname, fbase
1037 : : #ifdef _OS_WINDOWS_
1038 : : IMAGEHLP_MODULE64 ModuleInfo;
1039 : : ModuleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
1040 : : uv_mutex_lock(&jl_in_stackwalk);
1041 : : jl_refresh_dbg_module_list();
1042 : : bool isvalid = SymGetModuleInfo64(GetCurrentProcess(), (DWORD64)pointer, &ModuleInfo);
1043 : : uv_mutex_unlock(&jl_in_stackwalk);
1044 : : if (!isvalid)
1045 : : return false;
1046 : :
1047 : : StringRef fname = ModuleInfo.LoadedImageName;
1048 : : if (fname.empty()) // empirically, LoadedImageName might be missing
1049 : : fname = ModuleInfo.ImageName;
1050 : : DWORD64 fbase = ModuleInfo.BaseOfImage;
1051 : : bool insysimage = (fbase == getJITDebugRegistry().get_sysimg_info()->jl_sysimage_base);
1052 : : if (isSysImg)
1053 : : *isSysImg = insysimage;
1054 : : if (onlySysImg && !insysimage)
1055 : : return false;
1056 : : // If we didn't find the filename before in the debug
1057 : : // info, use the dll name
1058 : : if (filename && !*filename)
1059 : : jl_copy_str(filename, fname.data());
1060 : : if (saddr)
1061 : : *saddr = NULL;
1062 : :
1063 : : #else // ifdef _OS_WINDOWS_
1064 : : Dl_info dlinfo;
1065 : : int dladdr_success;
1066 : : uint64_t fbase;
1067 : : #ifdef __GLIBC__
1068 : : struct link_map *extra_info;
1069 : 264 : dladdr_success = dladdr1((void*)pointer, &dlinfo, (void**)&extra_info, RTLD_DL_LINKMAP) != 0;
1070 : : #else
1071 : : #ifdef _OS_DARWIN_
1072 : : // On macOS 12, dladdr(-1, …) succeeds and returns the main executable image,
1073 : : // despite there never actually being an image there. This is not what we want,
1074 : : // as we use -1 as a known-invalid value e.g. in the test suite.
1075 : : if (pointer == ~(size_t)0) {
1076 : : return false;
1077 : : }
1078 : : #endif
1079 : : dladdr_success = dladdr((void*)pointer, &dlinfo) != 0;
1080 : : #endif
1081 [ + + - + ]: 264 : if (!dladdr_success || !dlinfo.dli_fname)
1082 : 3 : return false;
1083 : :
1084 : : #ifdef __GLIBC__
1085 : : // dlinfo.dli_fbase is not the right value for the main executable on linux
1086 : 261 : fbase = (uintptr_t)extra_info->l_addr;
1087 : : #else
1088 : : fbase = (uintptr_t)dlinfo.dli_fbase;
1089 : : #endif
1090 : 261 : StringRef fname;
1091 : 261 : bool insysimage = (fbase == getJITDebugRegistry().get_sysimg_info()->jl_sysimage_base);
1092 [ + - - + : 261 : if (saddr && !(insysimage && untrusted_dladdr))
- - ]
1093 : 261 : *saddr = dlinfo.dli_saddr;
1094 [ + - ]: 261 : if (isSysImg)
1095 : 261 : *isSysImg = insysimage;
1096 [ - + - - ]: 261 : if (onlySysImg && !insysimage)
1097 : 0 : return false;
1098 : : // In case we fail with the debug info lookup, we at least still
1099 : : // have the function name, even if we don't have line numbers
1100 [ + - - + : 261 : if (name && !(insysimage && untrusted_dladdr))
- - ]
1101 : 261 : jl_copy_str(name, dlinfo.dli_sname);
1102 [ + - ]: 261 : if (filename)
1103 : 261 : jl_copy_str(filename, dlinfo.dli_fname);
1104 : 261 : fname = dlinfo.dli_fname;
1105 : : #endif // ifdef _OS_WINDOWS_
1106 : 261 : auto entry = find_object_file(fbase, fname);
1107 : 261 : *slide = entry.slide;
1108 : 261 : *context = entry.ctx;
1109 [ + - ]: 261 : if (entry.obj)
1110 : 261 : *Section = getModuleSectionForAddress(entry.obj, pointer + entry.slide);
1111 : 261 : get_function_name_and_base(*Section, pointer, entry.slide, insysimage, saddr, name, untrusted_dladdr);
1112 : 261 : return true;
1113 : : }
1114 : :
1115 : : // *name and *filename should be either NULL or malloc'd pointer
1116 : 264 : static int jl_getDylibFunctionInfo(jl_frame_t **frames, size_t pointer, int skipC, int noInline) JL_NOTSAFEPOINT
1117 : : {
1118 : : // This function is not allowed to reference any TLS variables if noInline
1119 : : // since it can be called from an unmanaged thread (the segfault handler)
1120 : 264 : jl_frame_t *frame0 = *frames;
1121 : : #ifdef _OS_WINDOWS_
1122 : : static IMAGEHLP_LINE64 frame_info_line;
1123 : : DWORD dwDisplacement = 0;
1124 : : uv_mutex_lock(&jl_in_stackwalk);
1125 : : jl_refresh_dbg_module_list();
1126 : : DWORD64 dwAddress = pointer;
1127 : : frame_info_line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
1128 : : if (SymGetLineFromAddr64(GetCurrentProcess(), dwAddress, &dwDisplacement, &frame_info_line)) {
1129 : : // SymGetLineFromAddr64 returned success
1130 : : // record source file name and line number
1131 : : if (frame_info_line.FileName)
1132 : : jl_copy_str(&frame0->file_name, frame_info_line.FileName);
1133 : : frame0->line = frame_info_line.LineNumber;
1134 : : }
1135 : : uv_mutex_unlock(&jl_in_stackwalk);
1136 : : #endif
1137 : 264 : object::SectionRef Section;
1138 : 264 : llvm::DIContext *context = NULL;
1139 : : int64_t slide;
1140 : : bool isSysImg;
1141 : : void *saddr;
1142 [ + + ]: 264 : if (!jl_dylib_DI_for_fptr(pointer, &Section, &slide, &context, skipC, &isSysImg, &saddr, &frame0->func_name, &frame0->file_name)) {
1143 : 3 : frame0->fromC = 1;
1144 : 3 : return 1;
1145 : : }
1146 : 261 : frame0->fromC = !isSysImg;
1147 : : {
1148 : 522 : auto sysimg_locked = getJITDebugRegistry().get_sysimg_info();
1149 [ - + - - : 261 : if (isSysImg && sysimg_locked->sysimg_fptrs.base && saddr) {
- - - + ]
1150 : 0 : intptr_t diff = (uintptr_t)saddr - (uintptr_t)sysimg_locked->sysimg_fptrs.base;
1151 [ # # ]: 0 : for (size_t i = 0; i < sysimg_locked->sysimg_fptrs.nclones; i++) {
1152 [ # # ]: 0 : if (diff == sysimg_locked->sysimg_fptrs.clone_offsets[i]) {
1153 : 0 : uint32_t idx = sysimg_locked->sysimg_fptrs.clone_idxs[i] & jl_sysimg_val_mask;
1154 [ # # ]: 0 : if (idx < sysimg_locked->sysimg_fvars_n) // items after this were cloned but not referenced directly by a method (such as our ccall PLT thunks)
1155 : 0 : frame0->linfo = sysimg_locked->sysimg_fvars_linfo[idx];
1156 : 0 : break;
1157 : : }
1158 : : }
1159 [ # # ]: 0 : for (size_t i = 0; i < sysimg_locked->sysimg_fvars_n; i++) {
1160 [ # # ]: 0 : if (diff == sysimg_locked->sysimg_fptrs.offsets[i]) {
1161 : 0 : frame0->linfo = sysimg_locked->sysimg_fvars_linfo[i];
1162 : 0 : break;
1163 : : }
1164 : : }
1165 : : }
1166 : : }
1167 : 261 : return lookup_pointer(Section, context, frames, pointer, slide, isSysImg, noInline);
1168 : : }
1169 : :
1170 : 366 : int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide,
1171 : : object::SectionRef *Section, llvm::DIContext **context) JL_NOTSAFEPOINT
1172 : : {
1173 : 366 : int found = 0;
1174 : : assert(0 == jl_lock_profile_rd_held());
1175 : 366 : jl_lock_profile_wr();
1176 : :
1177 [ + - ]: 366 : if (symsize)
1178 : 366 : *symsize = 0;
1179 : :
1180 : 366 : auto &objmap = getJITDebugRegistry().getObjectMap();
1181 : 366 : auto fit = objmap.lower_bound(fptr);
1182 [ + + + + : 366 : if (fit != objmap.end() && fptr < fit->first + fit->second.SectionSize) {
+ + ]
1183 : 102 : *slide = fit->second.slide;
1184 : 102 : *Section = fit->second.Section;
1185 [ + - ]: 102 : if (context) {
1186 [ + + ]: 102 : if (fit->second.context == nullptr)
1187 : 30 : fit->second.context = DWARFContext::create(*fit->second.object).release();
1188 : 102 : *context = fit->second.context;
1189 : : }
1190 : 102 : found = 1;
1191 : : }
1192 : 366 : jl_unlock_profile_wr();
1193 : 366 : return found;
1194 : : }
1195 : :
1196 : : // Set *name and *filename to either NULL or malloc'd string
1197 : 366 : extern "C" JL_DLLEXPORT int jl_getFunctionInfo_impl(jl_frame_t **frames_out, size_t pointer, int skipC, int noInline) JL_NOTSAFEPOINT
1198 : : {
1199 : : // This function is not allowed to reference any TLS variables if noInline
1200 : : // since it can be called from an unmanaged thread on OSX.
1201 : :
1202 : 366 : jl_frame_t *frames = (jl_frame_t*)calloc(sizeof(jl_frame_t), 1);
1203 : 366 : frames[0].line = -1;
1204 : 366 : *frames_out = frames;
1205 : :
1206 : : llvm::DIContext *context;
1207 : 366 : object::SectionRef Section;
1208 : : int64_t slide;
1209 : : uint64_t symsize;
1210 [ + + ]: 366 : if (jl_DI_for_fptr(pointer, &symsize, &slide, &Section, &context)) {
1211 : 102 : frames[0].linfo = getJITDebugRegistry().lookupLinfo(pointer);
1212 : 102 : int nf = lookup_pointer(Section, context, frames_out, pointer, slide, true, noInline);
1213 : 102 : return nf;
1214 : : }
1215 : 264 : return jl_getDylibFunctionInfo(frames_out, pointer, skipC, noInline);
1216 : : }
1217 : :
1218 : 0 : extern "C" jl_method_instance_t *jl_gdblookuplinfo(void *p) JL_NOTSAFEPOINT
1219 : : {
1220 : 0 : return getJITDebugRegistry().lookupLinfo((size_t)p);
1221 : : }
1222 : :
1223 : : #if defined(_OS_DARWIN_) && defined(LLVM_SHLIB)
1224 : :
1225 : : /*
1226 : : * We use a custom unwinder, so we need to make sure that when registering dynamic
1227 : : * frames, we do so with our unwinder rather than with the system one. If LLVM is
1228 : : * statically linked everything works out fine, but if it's dynamically linked
1229 : : * it would usually pick up the system one, so we need to do the registration
1230 : : * ourselves to ensure the right one gets picked.
1231 : : */
1232 : :
1233 : : // This implementation handles frame registration for local targets.
1234 : : void register_eh_frames(uint8_t *Addr, size_t Size)
1235 : : {
1236 : : // On OS X OS X __register_frame takes a single FDE as an argument.
1237 : : // See http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/061768.html
1238 : : processFDEs((char*)Addr, Size, [](const char *Entry) {
1239 : : getJITDebugRegistry().libc_frames.libc_register_frame(Entry);
1240 : : });
1241 : : }
1242 : :
1243 : : void deregister_eh_frames(uint8_t *Addr, size_t Size)
1244 : : {
1245 : : processFDEs((char*)Addr, Size, [](const char *Entry) {
1246 : : getJITDebugRegistry().libc_frames.libc_deregister_frame(Entry);
1247 : : });
1248 : : }
1249 : :
1250 : : #elif (defined(_OS_LINUX_) || defined(_OS_FREEBSD_)) && \
1251 : : defined(JL_UNW_HAS_FORMAT_IP) && \
1252 : : !defined(_CPU_ARM_) // ARM does not have/use .eh_frame, so we handle this elsewhere
1253 : : #include <type_traits>
1254 : :
1255 : : // Skip over an arbitrary long LEB128 encoding.
1256 : : // Return the pointer to the first unprocessed byte.
1257 : 159574 : static const uint8_t *consume_leb128(const uint8_t *Addr, const uint8_t *End)
1258 : : {
1259 : 159574 : const uint8_t *P = Addr;
1260 [ - + - - ]: 159574 : while ((*P >> 7) != 0 && P < End)
1261 : 0 : ++P;
1262 : 159574 : return P + 1;
1263 : : }
1264 : :
1265 : : // Parse a LEB128 encoding to a type T. Truncate the result if there's more
1266 : : // bytes than what there are more bytes than what the type can store.
1267 : : // Adjust the pointer to the first unprocessed byte.
1268 : 0 : template<typename T> static T parse_leb128(const uint8_t *&Addr,
1269 : : const uint8_t *End)
1270 : : {
1271 : : typedef typename std::make_unsigned<T>::type uT;
1272 : 0 : uT v = 0;
1273 [ # # ]: 0 : for (unsigned i = 0;i < ((sizeof(T) * 8 - 1) / 7 + 1);i++) {
1274 : 0 : uint8_t a = *Addr;
1275 : 0 : Addr++;
1276 : 0 : v |= uT(a & 0x7f) << (i * 7);
1277 [ # # # # ]: 0 : if ((a & 0x80) == 0 || Addr >= End) {
1278 [ # # ]: 0 : if (a & 0x40 && std::is_signed<T>::value) {
1279 : 0 : int valid_bits = (i + 1) * 7;
1280 [ # # ]: 0 : if (valid_bits < 64) {
1281 : 0 : v |= -(uT(1) << valid_bits);
1282 : : }
1283 : : }
1284 : 0 : return T(v);
1285 : : }
1286 : : }
1287 : 0 : Addr = consume_leb128(Addr, End);
1288 : 0 : return T(v);
1289 : : }
1290 : :
1291 : : template <typename U, typename T>
1292 : 159574 : static U safe_trunc(T t)
1293 : : {
1294 : : assert((t >= static_cast<T>(std::numeric_limits<U>::min()))
1295 : : && (t <= static_cast<T>(std::numeric_limits<U>::max())));
1296 : 159574 : return static_cast<U>(t);
1297 : : }
1298 : :
1299 : : // How the address and size in the FDE are encoded.
1300 : : enum DW_EH_PE : uint8_t {
1301 : : DW_EH_PE_absptr = 0x00, /* An absolute pointer. The size is determined by
1302 : : * whether this is a 32-bit or 64-bit address space,
1303 : : * and will be 32 or 64 bits */
1304 : : DW_EH_PE_omit = 0xff, // The value is omitted
1305 : : DW_EH_PE_uleb128 = 0x01, // The value is an unsigned LEB128
1306 : : DW_EH_PE_udata2 = 0x02,
1307 : : DW_EH_PE_udata4 = 0x03,
1308 : : DW_EH_PE_udata8 = 0x04, /* The value is stored as unsigned data with the
1309 : : * specified number of bytes. */
1310 : : DW_EH_PE_signed = 0x08, /* A signed number. The size is determined by
1311 : : * whether this is a 32-bit or 64-bit address space */
1312 : : DW_EH_PE_sleb128 = 0x09, /* A signed LEB128. */
1313 : : DW_EH_PE_sdata2 = 0x0a,
1314 : : DW_EH_PE_sdata4 = 0x0b,
1315 : : DW_EH_PE_sdata8 = 0x0c, /* The value is stored as signed data with the
1316 : : * specified number of bytes. */
1317 : :
1318 : : // In addition the above basic encodings, there are modifiers.
1319 : :
1320 : : DW_EH_PE_pcrel = 0x10, // Value is PC relative.
1321 : :
1322 : : // We currently don't support the following once.
1323 : : DW_EH_PE_textrel = 0x20, // Value is text relative.
1324 : : DW_EH_PE_datarel = 0x30, // Value is data relative.
1325 : : DW_EH_PE_funcrel = 0x40, // Value is relative to start of function.
1326 : : DW_EH_PE_aligned = 0x50, /* Value is aligned: padding bytes are inserted as
1327 : : * required to make value be naturally aligned. */
1328 : : DW_EH_PE_indirect = 0x80 /* This is actually the address of the real value. */
1329 : : };
1330 : :
1331 : : // Parse the CIE and return the type of encoding used by FDE
1332 : 79787 : static DW_EH_PE parseCIE(const uint8_t *Addr, const uint8_t *End)
1333 : : {
1334 : : // http://www.airs.com/blog/archives/460
1335 : : // Length (4 bytes)
1336 : 79787 : uint32_t cie_size = *(const uint32_t*)Addr;
1337 : 79787 : const uint8_t *cie_addr = Addr + 4;
1338 : 79787 : const uint8_t *p = cie_addr;
1339 : 79787 : const uint8_t *cie_end = cie_addr + cie_size;
1340 : : assert(cie_end <= End);
1341 : : // Check this is an CIE record (CIE ID: 4 bytes)
1342 : : assert(*(const uint32_t*)cie_addr == 0);
1343 : 79787 : p += 4;
1344 : : // Check CIE version (1 byte)
1345 : 79787 : uint8_t cie_version = *p;
1346 : : assert(cie_version == 1 || cie_version == 3);
1347 : 79787 : p++;
1348 : : // Augmentation String (NUL terminate)
1349 : 79787 : const char *augmentation = (const char*)p;
1350 : 79787 : size_t augmentation_len = strlen(augmentation);
1351 : : // Assume there's no EH Data field, which exist when the augmentation
1352 : : // string has "eh" in it.
1353 : 79787 : p += augmentation_len + 1;
1354 : : // Code Alignment Factor (1 byte)
1355 : : // should always be 1 on x86, 4 on PPC, etc.
1356 : : // (used for DW_CFA_advance_loc / not used here)
1357 : : //assert(*p == 1);
1358 : 79787 : p++;
1359 : : // Data Alignment Factor (LEB128)
1360 : : assert(cie_end >= p);
1361 : 79787 : p = consume_leb128(p, cie_end);
1362 : : // return address register
1363 [ + - ]: 79787 : if (cie_version == 1) {
1364 : 79787 : p++;
1365 : : }
1366 : : else {
1367 : 0 : p = consume_leb128(p, cie_end);
1368 : : }
1369 : : // Now it's the augmentation data. which may have the information we
1370 : : // are interested in...
1371 : 79787 : for (const char *augp = augmentation;;augp++) {
1372 [ + - + - : 159574 : switch (*augp) {
- ]
1373 : 79787 : case 'z':
1374 : : // Augmentation Length
1375 : 79787 : p = consume_leb128(p, cie_end);
1376 : 79787 : break;
1377 : 0 : case 'L':
1378 : : // LSDA encoding
1379 : 0 : p++;
1380 : 0 : break;
1381 : 79787 : case 'R':
1382 : : // .... the only one we care about ....
1383 : 79787 : return static_cast<DW_EH_PE>(*p);
1384 : 0 : case 'P': {
1385 : : // Personality data
1386 : : // Encoding
1387 : 0 : auto encoding = static_cast<DW_EH_PE>(*p);
1388 : 0 : p++;
1389 : : // Personality function
1390 [ # # # # : 0 : switch (encoding & 0xf) {
# # ]
1391 : 0 : case DW_EH_PE_uleb128:
1392 : : case DW_EH_PE_sleb128:
1393 : 0 : p = consume_leb128(p, cie_end);
1394 : 0 : break;
1395 : 0 : case DW_EH_PE_udata2:
1396 : : case DW_EH_PE_sdata2:
1397 : 0 : p += 2;
1398 : 0 : break;
1399 : 0 : case DW_EH_PE_udata4:
1400 : : case DW_EH_PE_sdata4:
1401 : 0 : p += 4;
1402 : 0 : break;
1403 : 0 : case DW_EH_PE_udata8:
1404 : : case DW_EH_PE_sdata8:
1405 : 0 : p += 8;
1406 : 0 : break;
1407 : 0 : case DW_EH_PE_signed:
1408 : 0 : p += sizeof(void*);
1409 : 0 : break;
1410 : 0 : default:
1411 [ # # # # ]: 0 : if (encoding == DW_EH_PE_absptr || encoding == DW_EH_PE_omit) {
1412 : 0 : p += sizeof(void*);
1413 : : }
1414 : : else {
1415 : : assert(0 && "Invalid personality encoding.");
1416 : : }
1417 : 0 : break;
1418 : : }
1419 : : }
1420 : 0 : break;
1421 : 0 : default:
1422 : 0 : continue;
1423 : : }
1424 : : assert(cie_end >= p);
1425 : 79787 : }
1426 : : return DW_EH_PE_absptr;
1427 : : }
1428 : :
1429 : 40368 : void register_eh_frames(uint8_t *Addr, size_t Size)
1430 : : {
1431 : : // System unwinder
1432 : 40368 : jl_profile_atomic([&]() {
1433 : 40368 : __register_frame(Addr);
1434 : 40368 : });
1435 : :
1436 : : // Now first count the number of FDEs
1437 : 40368 : size_t nentries = 0;
1438 : 40368 : processFDEs((char*)Addr, Size, [&](const char*){ nentries++; });
1439 [ - + ]: 40368 : if (nentries == 0)
1440 : 0 : return;
1441 : :
1442 : : // Our unwinder
1443 : 40368 : unw_dyn_info_t *di = new unw_dyn_info_t;
1444 : : // In a shared library, this is set to the address of the PLT.
1445 : : // For us, just put 0 to emulate a static library. This field does
1446 : : // not seem to be used on our supported architectures.
1447 : 40368 : di->gp = 0;
1448 : : // I'm not a great fan of the naming of this constant, but it means the
1449 : : // right thing, which is a table of FDEs and IPs.
1450 : 40368 : di->format = UNW_INFO_FORMAT_IP_OFFSET;
1451 : 40368 : di->u.rti.name_ptr = 0;
1452 : 40368 : di->u.rti.segbase = (unw_word_t)Addr;
1453 : :
1454 : 40368 : uintptr_t start_ip = (uintptr_t)-1;
1455 : 40368 : uintptr_t end_ip = 0;
1456 : :
1457 : : // Then allocate a table and fill in the information
1458 : : // While we're at it, also record the start_ip and size,
1459 : : // which we fill in the table
1460 [ + - ]: 40368 : unw_table_entry *table = new unw_table_entry[nentries];
1461 : 80736 : std::vector<uintptr_t> start_ips(nentries);
1462 : 40368 : size_t cur_entry = 0;
1463 : : // Cache the previously parsed CIE entry so that we can support multiple
1464 : : // CIE's (may not happen) without parsing it every time.
1465 : 40368 : const uint8_t *cur_cie = nullptr;
1466 : 40368 : DW_EH_PE encoding = DW_EH_PE_omit;
1467 : 40368 : processFDEs((char*)Addr, Size, [&](const char *Entry) {
1468 : : // Skip Length (4bytes) and CIE offset (4bytes)
1469 : 79787 : uint32_t fde_size = *(const uint32_t*)Entry;
1470 : 79787 : uint32_t cie_id = ((const uint32_t*)Entry)[1];
1471 : 79787 : const uint8_t *cie_addr = (const uint8_t*)(Entry + 4 - cie_id);
1472 [ + - ]: 79787 : if (cie_addr != cur_cie)
1473 : 79787 : encoding = parseCIE(cie_addr, Addr + Size);
1474 : 79787 : const uint8_t *fde_end = (const uint8_t*)(Entry + 4 + fde_size);
1475 : 79787 : const uint8_t *EntryPtr = (const uint8_t*)(Entry + 8);
1476 : 79787 : uintptr_t start = 0;
1477 : 79787 : uintptr_t size = 0;
1478 : : // The next two fields are address and size of the PC range
1479 : : // covered by this FDE.
1480 [ + - - + ]: 79787 : if (encoding == DW_EH_PE_absptr || encoding == DW_EH_PE_omit) {
1481 : : assert(fde_size >= 2 * sizeof(void*) + 4);
1482 : 0 : start = *(const uintptr_t*)EntryPtr;
1483 : 0 : size = *(const uintptr_t*)(EntryPtr + sizeof(void*));
1484 : : }
1485 : : else {
1486 : 79787 : uintptr_t baseptr = (uintptr_t)EntryPtr;
1487 : : // Only support pcrel for now...
1488 : : assert((encoding & 0xf0) == 0x10 &&
1489 : : "Only pcrel mode is supported");
1490 [ - - - - : 79787 : switch (encoding & 0xf) {
- - - - +
- ]
1491 : 0 : case DW_EH_PE_uleb128:
1492 : 0 : start = baseptr + parse_leb128<uintptr_t>(EntryPtr, fde_end);
1493 : 0 : size = parse_leb128<uintptr_t>(EntryPtr, fde_end);
1494 : 0 : break;
1495 : 0 : case DW_EH_PE_udata2:
1496 : : assert(fde_size >= 2 * 2 + 4);
1497 : 0 : start = baseptr + ((const uint16_t*)EntryPtr)[0];
1498 : 0 : size = ((const uint16_t*)EntryPtr)[1];
1499 : 0 : break;
1500 : 0 : case DW_EH_PE_udata4:
1501 : : assert(fde_size >= 2 * 4 + 4);
1502 : 0 : start = baseptr + ((const uint32_t*)EntryPtr)[0];
1503 : 0 : size = ((const uint32_t*)EntryPtr)[1];
1504 : 0 : break;
1505 : 0 : case DW_EH_PE_udata8:
1506 : : assert(fde_size >= 2 * 8 + 4);
1507 : 0 : start = uintptr_t(baseptr + ((const uint64_t*)EntryPtr)[0]);
1508 : 0 : size = uintptr_t(((const uint64_t*)EntryPtr)[1]);
1509 : 0 : break;
1510 : 0 : case DW_EH_PE_signed:
1511 : : assert(fde_size >= 2 * sizeof(void*) + 4);
1512 : 0 : start = baseptr + ((const intptr_t*)EntryPtr)[0];
1513 : 0 : size = ((const intptr_t*)EntryPtr)[1];
1514 : 0 : break;
1515 : 0 : case DW_EH_PE_sleb128:
1516 : 0 : start = baseptr + parse_leb128<intptr_t>(EntryPtr, fde_end);
1517 : 0 : size = parse_leb128<intptr_t>(EntryPtr, fde_end);
1518 : 0 : break;
1519 : 0 : case DW_EH_PE_sdata2:
1520 : : assert(fde_size >= 2 * 2 + 4);
1521 : 0 : start = baseptr + ((const int16_t*)EntryPtr)[0];
1522 : 0 : size = ((const int16_t*)EntryPtr)[1];
1523 : 0 : break;
1524 : 0 : case DW_EH_PE_sdata4:
1525 : : assert(fde_size >= 2 * 4 + 4);
1526 : 0 : start = baseptr + ((const int32_t*)EntryPtr)[0];
1527 : 0 : size = ((const int32_t*)EntryPtr)[1];
1528 : 0 : break;
1529 : 79787 : case DW_EH_PE_sdata8:
1530 : : assert(fde_size >= 2 * 8 + 4);
1531 : 79787 : start = uintptr_t(baseptr + ((const int64_t*)EntryPtr)[0]);
1532 : 79787 : size = uintptr_t(((const int64_t*)EntryPtr)[1]);
1533 : 79787 : break;
1534 : 0 : default:
1535 : : assert(0 && "Invalid FDE encoding.");
1536 : 0 : break;
1537 : : }
1538 : : }
1539 : :
1540 [ + + ]: 79787 : if (start < start_ip)
1541 : 40368 : start_ip = start;
1542 [ + - ]: 79787 : if (end_ip < (start + size))
1543 : 79787 : end_ip = start + size;
1544 : 239361 : table[cur_entry].fde_offset =
1545 : 79787 : safe_trunc<int32_t>((intptr_t)Entry - (intptr_t)Addr);
1546 : 79787 : start_ips[cur_entry] = start;
1547 : 79787 : cur_entry++;
1548 : 79787 : });
1549 [ + + ]: 120155 : for (size_t i = 0; i < nentries; i++) {
1550 : 79787 : table[i].start_ip_offset =
1551 : 79787 : safe_trunc<int32_t>((intptr_t)start_ips[i] - (intptr_t)start_ip);
1552 : : }
1553 : : assert(end_ip != 0);
1554 : :
1555 : 40368 : di->u.rti.table_len = nentries * sizeof(*table) / sizeof(unw_word_t);
1556 : 40368 : di->u.rti.table_data = (unw_word_t)table;
1557 : 40368 : di->start_ip = start_ip;
1558 : 40368 : di->end_ip = end_ip;
1559 : :
1560 : 40368 : jl_profile_atomic([&]() {
1561 : 40368 : _U_dyn_register(di);
1562 : 40368 : });
1563 : : }
1564 : :
1565 : 0 : void deregister_eh_frames(uint8_t *Addr, size_t Size)
1566 : : {
1567 : 0 : jl_profile_atomic([&]() {
1568 : 0 : __deregister_frame(Addr);
1569 : 0 : });
1570 : : // Deregistering with our unwinder (_U_dyn_cancel) requires a lookup table
1571 : : // to find the allocated entry above (or looking into libunwind's internal
1572 : : // data structures).
1573 : 0 : }
1574 : :
1575 : : #else
1576 : :
1577 : : void register_eh_frames(uint8_t *Addr, size_t Size)
1578 : : {
1579 : : }
1580 : :
1581 : : void deregister_eh_frames(uint8_t *Addr, size_t Size)
1582 : : {
1583 : : }
1584 : :
1585 : : #endif
1586 : :
1587 : : extern "C" JL_DLLEXPORT
1588 : 0 : uint64_t jl_getUnwindInfo_impl(uint64_t dwAddr)
1589 : : {
1590 : : // Might be called from unmanaged thread
1591 : 0 : jl_lock_profile();
1592 : 0 : auto &objmap = getJITDebugRegistry().getObjectMap();
1593 : 0 : auto it = objmap.lower_bound(dwAddr);
1594 : 0 : uint64_t ipstart = 0; // ip of the start of the section (if found)
1595 [ # # # # : 0 : if (it != objmap.end() && dwAddr < it->first + it->second.SectionSize) {
# # ]
1596 : 0 : ipstart = (uint64_t)(uintptr_t)(*it).first;
1597 : : }
1598 : 0 : jl_unlock_profile();
1599 : 0 : return ipstart;
1600 : : }
|