/* This function will be called from _init in init-first.c. */ void __libc_global_ctors (void) { /* Call constructor functions. */ run_hooks (__CTOR_LIST__); #ifdef HAVE_DWARF2_UNWIND_INFO # ifdef HAVE_DWARF2_UNWIND_INFO_STATIC { static struct object ob; # if defined CRT_GET_RFIB_TEXT || defined CRT_GET_RFIB_DATA void *tbase, *dbase; # ifdef CRT_GET_RFIB_TEXT CRT_GET_RFIB_TEXT (tbase); # else tbase = NULL; # endif # ifdef CRT_GET_RFIB_DATA CRT_GET_RFIB_DATA (dbase); # else dbase = NULL; # endif __register_frame_info_bases (__EH_FRAME_BEGIN__, &ob, tbase, dbase); # else __register_frame_info (__EH_FRAME_BEGIN__, &ob); # endif } # else __register_frame (__EH_FRAME_BEGIN__); # endif #endif }
void _init_c_runtime() { // Initialize .bss section extern char _BSS_START_, _BSS_END_; streamset8(&_BSS_START_, 0, &_BSS_END_ - &_BSS_START_); // Initialize the heap before exceptions extern caddr_t heap_end; // used by SBRK: extern char _end; // Defined by the linker // Set heap to after _end (given by linker script) if needed if (&_end > heap_end) heap_end = &_end; /// initialize newlib I/O newlib_reent = (struct _reent) _REENT_INIT(newlib_reent); // set newlibs internal structure to ours _REENT = &newlib_reent; // Unix standard streams stdin = _REENT->_stdin; // stdin == 1 stdout = _REENT->_stdout; // stdout == 2 stderr = _REENT->_stderr; // stderr == 3 /// initialize exceptions before we can run constructors extern void* __eh_frame_start; // Tell the stack unwinder where exception frames are located extern void __register_frame(void*); __register_frame(&__eh_frame_start); /// call global constructors emitted by compiler extern void _init(); _init(); }
void register_frame(void* frame_begin) { #if defined(USE_KEYMGR_HACK) darwin_register_frame(frame_begin); #else __register_frame(frame_begin); #endif }
static const char *processFDE(const char *Entry) { const char *P = Entry; uint32_t Length = *((const uint32_t *)P); P += 4; uint32_t Offset = *((const uint32_t *)P); if (Offset != 0) __register_frame(const_cast<char *>(Entry)); return P + Length; }
static const char *processFDE(const char *Entry) { const char *P = Entry; uint32_t Length = *((uint32_t*)P); P += 4; uint32_t Offset = *((uint32_t*)P); if (Offset != 0) __register_frame((void*)Entry); return P + Length; }
void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr, size_t Size) { // On Linux __register_frame takes a single argument: // a pointer to the start of the .eh_frame section. // How can it find the end? Because crtendS.o is linked // in and it has an .eh_frame section with four zero chars. __register_frame(Addr); }
EHFrameHandle EHFrameWriter::register_and_release() { auto& vec = *m_buf; auto const fde = m_fde; if (fde != kInvalidFDE) __register_frame(&vec[fde]); return std::shared_ptr<std::vector<uint8_t>>( m_buf.release(), [fde] (std::vector<uint8_t>* p) { SCOPE_EXIT { delete p; }; if (fde != kInvalidFDE) __deregister_frame(&((*p)[fde])); }
static const char *processFDE(const char *Entry, bool isDeregister) { const char *P = Entry; uint32_t Length = *((const uint32_t *)P); P += 4; uint32_t Offset = *((const uint32_t *)P); if (Offset != 0) { if (isDeregister) __deregister_frame(const_cast<char *>(Entry)); else __register_frame(const_cast<char *>(Entry)); } return P + Length; }
/* static */ void XDataAllocator::Register(XDataAllocation * xdataInfo, ULONG_PTR functionStart, DWORD functionSize) { #ifdef _WIN32 ULONG_PTR baseAddress = functionStart; xdataInfo->pdata.BeginAddress = (DWORD)(functionStart - baseAddress); xdataInfo->pdata.EndAddress = (DWORD)(xdataInfo->pdata.BeginAddress + functionSize); xdataInfo->pdata.UnwindInfoAddress = (DWORD)((intptr_t)xdataInfo->address - baseAddress); BOOLEAN success = FALSE; if (AutoSystemInfo::Data.IsWin8OrLater()) { DWORD status = NtdllLibrary::Instance->AddGrowableFunctionTable(&xdataInfo->functionTable, &xdataInfo->pdata, /*MaxEntryCount*/ 1, /*Valid entry count*/ 1, /*RangeBase*/ functionStart, /*RangeEnd*/ functionStart + functionSize); success = NT_SUCCESS(status); if (success) { Assert(xdataInfo->functionTable != nullptr); } } else { success = RtlAddFunctionTable(&xdataInfo->pdata, 1, functionStart); } Js::Throw::CheckAndThrowOutOfMemory(success); #if DBG // Validate that the PDATA registration succeeded ULONG64 imageBase = 0; RUNTIME_FUNCTION *runtimeFunction = RtlLookupFunctionEntry((DWORD64)functionStart, &imageBase, nullptr); Assert(runtimeFunction != NULL); #endif #else // !_WIN32 Assert(ReadHead(xdataInfo->address)); // should be non-empty .eh_frame __register_frame(xdataInfo->address); #endif }
EHFrameDesc EHFrameWriter::register_and_release() { FTRACE(1, "Summary:\n"); EHFrameDesc eh; eh.m_buf = std::move(m_buf); assertx(m_cie.idx == 0); FTRACE(1, " [{}] CIE length={}\n", eh.cie().get(), eh.cie().length()); // Register all the FDEs. eh.for_each_fde([&] (const EHFrameDesc::FDE& fde) { DEBUG_ONLY auto const cie_off = (fde.get() + 4) - fde.cie_off(); assertx(eh.cie().get() == cie_off); FTRACE(1, " [{}] FDE length={} cie=[{}]\n", fde.get(), fde.length(), cie_off); __register_frame(fde.get()); }); FTRACE(1, "\n"); return eh; }
UnwindInfoHandle register_unwind_region(unsigned char* startAddr, size_t size) { std::auto_ptr<std::vector<char> > bufferMem(new std::vector<char>); std::vector<char>& buffer = *bufferMem; { // This is a dwarf CIE header. Looks the same as a fde except the // second field is zero. append_vec<uint32_t>(buffer, 0); // Room for length later append_vec<int32_t>(buffer, 0); // CIE_id append_vec<uint8_t>(buffer, 1); // version /* * Null-terminated "augmentation string" (defines what the rest of * this thing is going to have. * * TODO: probably we should have a 'z' field to indicate length. */ append_vec<char>(buffer, 'P'); append_vec<char>(buffer, '\0'); // Code and data alignment. append_vec<uint8_t>(buffer, 1); append_vec<uint8_t>(buffer, 8); // Multiplies offsets below. // Return address column (in version 1, this is a single byte). append_vec<uint8_t>(buffer, Debug::RIP); // Pointer to the personality routine for the TC. append_vec<uint8_t>(buffer, DW_EH_PE_absptr); append_vec<uintptr_t>(buffer, uintptr_t(tc_unwind_personality)); /* * Define a program for the CIE. This explains to the unwinder * how to figure out where the frame pointer was, etc. * * Arguments to some of these are encoded in LEB128, so we have to * clear the high bit for the signed values. */ // Previous FP (CFA) is at rbp + 16. append_vec<uint8_t>(buffer, DW_CFA_def_cfa); append_vec<uint8_t>(buffer, Debug::RBP); append_vec<uint8_t>(buffer, 16); // rip is at CFA - 1 * data_align. append_vec<uint8_t>(buffer, DW_CFA_offset_extended_sf); append_vec<uint8_t>(buffer, Debug::RIP); append_vec<uint8_t>(buffer, -1u & 0x7f); // rbp is at CFA - 2 * data_align. append_vec<uint8_t>(buffer, DW_CFA_offset_extended_sf); append_vec<uint8_t>(buffer, Debug::RBP); append_vec<uint8_t>(buffer, -2u & 0x7f); /* * Leave rsp unchanged. * * Note that some things in the translator do actually change rsp, * but we assume they cannot throw so this is ok. If rVmSp ever * changes to use rsp this code must change. */ append_vec<uint8_t>(buffer, DW_CFA_same_value); append_vec<uint8_t>(buffer, Debug::RSP); // Fixup the length field. Note that it doesn't include the space // for itself. void* vp = &buffer[0]; *static_cast<uint32_t*>(vp) = buffer.size() - sizeof(uint32_t); } const size_t fdeIdx = buffer.size(); { // Reserve space for FDE length. append_vec<uint32_t>(buffer, 0); // Negative offset to the CIE for this FDE---the offset is // relative to this field. append_vec<int32_t>(buffer, int32_t(buffer.size())); // We're using the addressing mode DW_EH_PE_absptr, which means it // wants a 8 byte pointer and a 8 byte size indicating the region // this FDE applies to. append_vec<unsigned char*>(buffer, startAddr); append_vec<size_t>(buffer, size); // Fixup the length field for this FDE. Again length doesn't // include the length field itself. void* vp = &buffer[fdeIdx]; *static_cast<uint32_t*>(vp) = buffer.size() - fdeIdx - sizeof(uint32_t); } // Add one more zero'd length field---this indicates that there are // no more FDEs sharing this CIE. append_vec<uint32_t>(buffer, 0); __register_frame(&buffer[0]); return boost::shared_ptr<std::vector<char> >( bufferMem.release(), deregister_unwind_region ); }
extern void _force_link() { __register_frame(nullptr); __deregister_frame(nullptr); }