Exemple #1
0
/* 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
}
Exemple #2
0
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();
}
Exemple #3
0
	void register_frame(void* frame_begin) {
		#if defined(USE_KEYMGR_HACK)
		darwin_register_frame(frame_begin);
		#else
		__register_frame(frame_begin);
		#endif
	}
Exemple #4
0
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;
}
Exemple #6
0
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);
}
Exemple #7
0
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]));
    }
Exemple #8
0
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
}
Exemple #10
0
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;
}
Exemple #11
0
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
  );
}
Exemple #12
0
extern void _force_link() {
    __register_frame(nullptr);
    __deregister_frame(nullptr);
}