LCOV - code coverage report
Current view: top level - src - debuginfo.cpp (source / functions) Hit Total Coverage
Test: [build process] commit ef510b1f346f4c9f9d86eaceace5ca54961a1dbc Lines: 398 585 68.0 %
Date: 2022-07-17 01:01:28 Functions: 38 48 79.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 149 321 46.4 %

           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 &section: 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                 :            : }

Generated by: LCOV version 1.14