Пример #1
0
// compute stub buffer size for the given section
unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj,
                                                    const SectionRef &Section) {
  unsigned StubSize = getMaxStubSize();
  if (StubSize == 0) {
    return 0;
  }
  // FIXME: this is an inefficient way to handle this. We should computed the
  // necessary section allocation size in loadObject by walking all the sections
  // once.
  unsigned StubBufSize = 0;
  for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections();
       SI != SE; ++SI) {
    section_iterator RelSecI = SI->getRelocatedSection();
    if (!(RelSecI == Section))
      continue;

    for (const RelocationRef &Reloc : SI->relocations()) {
      (void)Reloc;
      StubBufSize += StubSize;
    }
  }

  // Get section data size and alignment
  uint64_t DataSize = Section.getSize();
  uint64_t Alignment64 = Section.getAlignment();

  // Add stubbuf size alignment
  unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
  unsigned StubAlignment = getStubAlignment();
  unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment);
  if (StubAlignment > EndAlignment)
    StubBufSize += StubAlignment - EndAlignment;
  return StubBufSize;
}
Пример #2
0
void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
                                            ObjectImage &Obj,
                                            ObjSectionToIDMap &ObjSectionToID,
                                            const SymbolTableMap &Symbols,
                                            StubMap &Stubs) {

  uint32_t RelType = (uint32_t) (Rel.Type & 0xffffffffL);
  RelocationValueRef Value;
  SectionEntry &Section = Sections[Rel.SectionID];

  bool isExtern = (RelType >> 27) & 1;
  if (isExtern) {
    // Obtain the symbol name which is referenced in the relocation
    StringRef TargetName;
    const SymbolRef &Symbol = Rel.Symbol;
    Symbol.getName(TargetName);
    // First search for the symbol in the local symbol table
    SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data());
    if (lsi != Symbols.end()) {
      Value.SectionID = lsi->second.first;
      Value.Addend = lsi->second.second;
    } else {
      // Search for the symbol in the global symbol table
      SymbolTableMap::const_iterator gsi = GlobalSymbolTable.find(TargetName.data());
      if (gsi != GlobalSymbolTable.end()) {
        Value.SectionID = gsi->second.first;
        Value.Addend = gsi->second.second;
      } else
        Value.SymbolName = TargetName.data();
    }
  } else {
    error_code err;
    uint8_t sectionIndex = static_cast<uint8_t>(RelType & 0xFF);
    section_iterator si = Obj.begin_sections(),
                     se = Obj.end_sections();
    for (uint8_t i = 1; i < sectionIndex; i++) {
      error_code err;
      si.increment(err);
      if (si == se)
        break;
    }
    assert(si != se && "No section containing relocation!");
    Value.SectionID = findOrEmitSection(Obj, *si, true, ObjSectionToID);
    Value.Addend = 0;
    // FIXME: The size and type of the relocation determines if we can
    // encode an Addend in the target location itself, and if so, how many
    // bytes we should read in order to get it. We don't yet support doing
    // that, and just assuming it's sizeof(intptr_t) is blatantly wrong.
    //Value.Addend = *(const intptr_t *)Target;
    if (Value.Addend) {
      // The MachO addend is an offset from the current section.  We need it
      // to be an offset from the destination section
      Value.Addend += Section.ObjAddress - Sections[Value.SectionID].ObjAddress;
    }
  }

  if (Arch == Triple::arm && (RelType & 0xf) == macho::RIT_ARM_Branch24Bit) {
    // This is an ARM branch relocation, need to use a stub function.

    //  Look up for existing stub.
    StubMap::const_iterator i = Stubs.find(Value);
    if (i != Stubs.end())
      resolveRelocation(Section, Rel.Offset,
                        (uint64_t)Section.Address + i->second,
                        RelType, 0);
    else {
      // Create a new stub function.
      Stubs[Value] = Section.StubOffset;
      uint8_t *StubTargetAddr = createStubFunction(Section.Address +
                                                   Section.StubOffset);
      RelocationEntry RE(Rel.SectionID, StubTargetAddr - Section.Address,
                         macho::RIT_Vanilla, Value.Addend);
      if (Value.SymbolName)
        addRelocationForSymbol(RE, Value.SymbolName);
      else
        addRelocationForSection(RE, Value.SectionID);
      resolveRelocation(Section, Rel.Offset,
                        (uint64_t)Section.Address + Section.StubOffset,
                        RelType, 0);
      Section.StubOffset += getMaxStubSize();
    }
  } else {
    RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend);
    if (Value.SymbolName)
      addRelocationForSymbol(RE, Value.SymbolName);
    else
      addRelocationForSection(RE, Value.SectionID);
  }
}
Пример #3
0
    virtual void NotifyObjectEmitted(const ObjectImage &obj)
#endif
    {
        int8_t gc_state = jl_gc_safe_enter();
        uv_rwlock_wrlock(&threadsafe);
        jl_gc_safe_leave(gc_state);
#ifdef LLVM36
        object::section_iterator Section = obj.section_begin();
        object::section_iterator EndSection = obj.section_end();
#else
        object::section_iterator Section = obj.begin_sections();
        object::section_iterator EndSection = obj.end_sections();
#endif

#if defined(_OS_WINDOWS_)
        uint64_t SectionAddrCheck = 0; // assert that all of the Sections are at the same location
        uint8_t *UnwindData = NULL;
#if defined(_CPU_X86_64_)
        uint8_t *catchjmp = NULL;
        for (const object::SymbolRef &sym_iter : obj.symbols()) {
            StringRef sName;
#ifdef LLVM37
            sName = sym_iter.getName().get();
#else
            sym_iter.getName(sName);
#endif
            uint8_t **pAddr = NULL;
            if (sName.equals("__UnwindData")) {
                pAddr = &UnwindData;
            }
            else if (sName.equals("__catchjmp")) {
                pAddr = &catchjmp;
            }
            if (pAddr) {
                uint64_t Addr, SectionAddr;
#if defined(LLVM38)
                Addr = sym_iter.getAddress().get();
                Section = sym_iter.getSection().get();
                assert(Section != EndSection && Section->isText());
                SectionAddr = L.getSectionLoadAddress(*Section);
#elif defined(LLVM37)
                Addr = sym_iter.getAddress().get();
                sym_iter.getSection(Section);
                assert(Section != EndSection && Section->isText());
                Section->getName(sName);
                SectionAddr = L.getSectionLoadAddress(sName);
#elif defined(LLVM36)
                sym_iter.getAddress(Addr);
                sym_iter.getSection(Section);
                assert(Section != EndSection && Section->isText());
                Section->getName(sName);
                SectionAddr = L.getSectionLoadAddress(sName);
#else // LLVM35
                sym_iter.getAddress(Addr);
                sym_iter.getSection(Section);
                assert(Section != EndSection);
                assert(!Section->isText(isText) && isText);
                Section->getAddress(SectionAddr);
#endif
#ifdef LLVM36
                Addr += SectionAddr;
#endif
                *pAddr = (uint8_t*)Addr;
                if (SectionAddrCheck)
                    assert(SectionAddrCheck == SectionAddr);
                else
                    SectionAddrCheck = SectionAddr;
            }
        }
        assert(catchjmp);
        assert(UnwindData);
        assert(SectionAddrCheck);
        catchjmp[0] = 0x48;
        catchjmp[1] = 0xb8; // mov RAX, QWORD PTR [&_seh_exception_handle]
        *(uint64_t*)(&catchjmp[2]) = (uint64_t)&_seh_exception_handler;
        catchjmp[10] = 0xff;
        catchjmp[11] = 0xe0; // jmp RAX
        UnwindData[0] = 0x09; // version info, UNW_FLAG_EHANDLER
        UnwindData[1] = 4;    // size of prolog (bytes)
        UnwindData[2] = 2;    // count of unwind codes (slots)
        UnwindData[3] = 0x05; // frame register (rbp) = rsp
        UnwindData[4] = 4;    // second instruction
        UnwindData[5] = 0x03; // mov RBP, RSP
        UnwindData[6] = 1;    // first instruction
        UnwindData[7] = 0x50; // push RBP
        *(DWORD*)&UnwindData[8] = (DWORD)(catchjmp - (uint8_t*)SectionAddrCheck); // relative location of catchjmp
#endif // defined(_OS_X86_64_)
#endif // defined(_OS_WINDOWS_)

#ifdef LLVM37
        auto symbols = object::computeSymbolSizes(obj);
        for(const auto &sym_size : symbols) {
            const object::SymbolRef &sym_iter = sym_size.first;
            object::SymbolRef::Type SymbolType = sym_iter.getType();
            if (SymbolType != object::SymbolRef::ST_Function) continue;
            uint64_t Size = sym_size.second;
            uint64_t Addr = sym_iter.getAddress().get();
#ifdef LLVM38
            Section = sym_iter.getSection().get();
#else
            sym_iter.getSection(Section);
#endif
            if (Section == EndSection) continue;
            if (!Section->isText()) continue;
#ifdef LLVM38
            uint64_t SectionAddr = L.getSectionLoadAddress(*Section);
#else
            StringRef secName;
            Section->getName(secName);
            uint64_t SectionAddr = L.getSectionLoadAddress(secName);
#endif
            Addr += SectionAddr;
            StringRef sName = sym_iter.getName().get();
#if defined(_OS_WINDOWS_)
            uint64_t SectionSize = Section->getSize();
            if (SectionAddrCheck)
                assert(SectionAddrCheck == SectionAddr);
            else
                SectionAddrCheck = SectionAddr;
            create_PRUNTIME_FUNCTION(
                   (uint8_t*)(intptr_t)Addr, (size_t)Size, sName,
                   (uint8_t*)(intptr_t)SectionAddr, (size_t)SectionSize, UnwindData);
#endif
            StringMap<jl_lambda_info_t*>::iterator linfo_it = linfo_in_flight.find(sName);
            jl_lambda_info_t *linfo = NULL;
            if (linfo_it != linfo_in_flight.end()) {
                linfo = linfo_it->second;
                linfo_in_flight.erase(linfo_it);
            }
            ObjectInfo tmp = {&debugObj, (size_t)Size, L.clone().release(), linfo};
            objectmap[Addr] = tmp;
        }

#else // pre-LLVM37
        uint64_t Addr;
        uint64_t Size;
        object::SymbolRef::Type SymbolType;
        StringRef sName;
#ifdef LLVM36
        uint64_t SectionAddr = 0;
#else
        bool isText;
#ifdef _OS_WINDOWS_
        uint64_t SectionAddr = 0;
#endif
#endif

#if defined(LLVM35)
        for (const object::SymbolRef &sym_iter : obj.symbols()) {
            sym_iter.getType(SymbolType);
            if (SymbolType != object::SymbolRef::ST_Function) continue;
            sym_iter.getSize(Size);
            sym_iter.getAddress(Addr);
            sym_iter.getSection(Section);
            if (Section == EndSection) continue;
#if defined(LLVM36)
            if (!Section->isText()) continue;
            Section->getName(sName);
            SectionAddr = L.getSectionLoadAddress(sName);
            Addr += SectionAddr;
#else
            if (Section->isText(isText) || !isText) continue;
#endif
            sym_iter.getName(sName);
#ifdef _OS_DARWIN_
#   if !defined(LLVM36)
            Addr = ((MCJIT*)jl_ExecutionEngine)->getSymbolAddress(sName, true);
            if (!Addr && sName[0] == '_') {
                Addr = ((MCJIT*)jl_ExecutionEngine)->getSymbolAddress(sName.substr(1), true);
            }
            if (!Addr) continue;
#   endif
#elif defined(_OS_WINDOWS_)
            uint64_t SectionSize = 0;
#   if defined(LLVM36)
            SectionSize = Section->getSize();
#   else
            Section->getAddress(SectionAddr);
            Section->getSize(SectionSize);
#   endif
            if (SectionAddrCheck)
                assert(SectionAddrCheck == SectionAddr);
            else
                SectionAddrCheck = SectionAddr;
            create_PRUNTIME_FUNCTION(
                   (uint8_t*)(intptr_t)Addr, (size_t)Size, sName,
                   (uint8_t*)(intptr_t)SectionAddr, (size_t)SectionSize, UnwindData);
#endif
            StringMap<jl_lambda_info_t*>::iterator linfo_it = linfo_in_flight.find(sName);
            jl_lambda_info_t *linfo = NULL;
            if (linfo_it != linfo_in_flight.end()) {
                linfo = linfo_it->second;
                linfo_in_flight.erase(linfo_it);
            }
            const object::ObjectFile *objfile =
#ifdef LLVM36
                &obj;
#else
                obj.getObjectFile();
#endif
            ObjectInfo tmp = {objfile, (size_t)Size,
#ifdef LLVM37
                L.clone().release(),
#elif defined(LLVM36)
                (size_t)SectionAddr,
#endif
#ifdef _OS_DARWIN_
                strndup(sName.data(), sName.size()),
#endif
                linfo
            };
            objectmap[Addr] = tmp;
        }
#else //LLVM34
        error_code itererr;
        object::symbol_iterator sym_iter = obj.begin_symbols();
        object::symbol_iterator sym_end = obj.end_symbols();
        for (; sym_iter != sym_end; sym_iter.increment(itererr)) {
            sym_iter->getType(SymbolType);
            if (SymbolType != object::SymbolRef::ST_Function) continue;
            sym_iter->getAddress(Addr);
            sym_iter->getSize(Size);

            ObjectInfo tmp = {obj.getObjectFile(), (size_t)Size};
            objectmap[Addr] = tmp;
        }
#endif
#endif
        uv_rwlock_wrunlock(&threadsafe);
    }
Пример #4
0
// Compute an upper bound of the memory size that is required to load all
// sections
void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj,
                                            uint64_t &CodeSize,
                                            uint64_t &DataSizeRO,
                                            uint64_t &DataSizeRW) {
  // Compute the size of all sections required for execution
  std::vector<uint64_t> CodeSectionSizes;
  std::vector<uint64_t> ROSectionSizes;
  std::vector<uint64_t> RWSectionSizes;
  uint64_t MaxAlignment = sizeof(void *);

  // Collect sizes of all sections to be loaded;
  // also determine the max alignment of all sections
  for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections();
       SI != SE; ++SI) {
    const SectionRef &Section = *SI;

    bool IsRequired = Section.isRequiredForExecution();

    // Consider only the sections that are required to be loaded for execution
    if (IsRequired) {
      StringRef Name;
      uint64_t DataSize = Section.getSize();
      uint64_t Alignment64 = Section.getAlignment();
      bool IsCode = Section.isText();
      bool IsReadOnly = Section.isReadOnlyData();
      Check(Section.getName(Name));
      unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;

      uint64_t StubBufSize = computeSectionStubBufSize(Obj, Section);
      uint64_t SectionSize = DataSize + StubBufSize;

      // The .eh_frame section (at least on Linux) needs an extra four bytes
      // padded
      // with zeroes added at the end.  For MachO objects, this section has a
      // slightly different name, so this won't have any effect for MachO
      // objects.
      if (Name == ".eh_frame")
        SectionSize += 4;

      if (SectionSize > 0) {
        // save the total size of the section
        if (IsCode) {
          CodeSectionSizes.push_back(SectionSize);
        } else if (IsReadOnly) {
          ROSectionSizes.push_back(SectionSize);
        } else {
          RWSectionSizes.push_back(SectionSize);
        }
        // update the max alignment
        if (Alignment > MaxAlignment) {
          MaxAlignment = Alignment;
        }
      }
    }
  }

  // Compute the size of all common symbols
  uint64_t CommonSize = 0;
  for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E;
       ++I) {
    uint32_t Flags = I->getFlags();
    if (Flags & SymbolRef::SF_Common) {
      // Add the common symbols to a list.  We'll allocate them all below.
      uint64_t Size = 0;
      Check(I->getSize(Size));
      CommonSize += Size;
    }
  }
  if (CommonSize != 0) {
    RWSectionSizes.push_back(CommonSize);
  }

  // Compute the required allocation space for each different type of sections
  // (code, read-only data, read-write data) assuming that all sections are
  // allocated with the max alignment. Note that we cannot compute with the
  // individual alignments of the sections, because then the required size
  // depends on the order, in which the sections are allocated.
  CodeSize = computeAllocationSizeForSections(CodeSectionSizes, MaxAlignment);
  DataSizeRO = computeAllocationSizeForSections(ROSectionSizes, MaxAlignment);
  DataSizeRW = computeAllocationSizeForSections(RWSectionSizes, MaxAlignment);
}
Пример #5
0
    virtual void NotifyObjectEmitted(const ObjectImage &obj)
#endif
    {
        uint64_t Addr;
        uint64_t Size;
        object::SymbolRef::Type SymbolType;
#ifdef LLVM36
        object::section_iterator Section = obj.section_begin();
        object::section_iterator EndSection = obj.section_end();
        uint64_t SectionAddr = 0;
        StringRef sName;
#else
        object::section_iterator Section = obj.begin_sections();
        object::section_iterator EndSection = obj.end_sections();
        bool isText;
#ifndef _OS_LINUX_
        StringRef sName;
#endif
#endif

#ifndef LLVM36
        uint64_t SectionAddr = 0;
#endif
        uint64_t SectionSize = 0;
        uint64_t SectionAddrCheck = 0; // assert that all of the Sections are at the same location

#if defined(_OS_WINDOWS_)
#if defined(_CPU_X86_64_)
        uint8_t *UnwindData = NULL;
        uint8_t *catchjmp = NULL;
        for (const object::SymbolRef &sym_iter : obj.symbols()) {
#  ifdef LLVM37
            sName = sym_iter.getName().get();
#  else
            sym_iter.getName(sName);
#  endif
            if (sName.equals("__UnwindData")) {
#  ifdef LLVM37
                Addr = sym_iter.getAddress().get();
#  else
                sym_iter.getAddress(Addr);
#  endif
                sym_iter.getSection(Section);
#  ifdef LLVM36
                assert(Section->isText());
                Section->getName(sName);
                SectionAddr = L.getSectionLoadAddress(sName);
                Addr += SectionAddr;
#  else
                if (Section->isText(isText) || !isText) assert(0 && "!isText");
                Section->getAddress(SectionAddr);
#  endif
                UnwindData = (uint8_t*)Addr;
                if (SectionAddrCheck)
                    assert(SectionAddrCheck == SectionAddr);
                else
                    SectionAddrCheck = SectionAddr;
            }
            if (sName.equals("__catchjmp")) {
#  ifdef LLVM37
                Addr = sym_iter.getAddress().get();
#  else
                sym_iter.getAddress(Addr);
#  endif
                sym_iter.getSection(Section);
#  ifdef LLVM36
                assert(Section->isText());
                Section->getName(sName);
                SectionAddr = L.getSectionLoadAddress(sName);
                Addr += SectionAddr;
#  else
                if (Section->isText(isText) || !isText) assert(0 && "!isText");
                Section->getAddress(SectionAddr);
#  endif
                catchjmp = (uint8_t*)Addr;
                if (SectionAddrCheck)
                    assert(SectionAddrCheck == SectionAddr);
                else
                    SectionAddrCheck = SectionAddr;
            }
        }
        assert(catchjmp);
        assert(UnwindData);
        catchjmp[0] = 0x48;
        catchjmp[1] = 0xb8; // mov RAX, QWORD PTR [&_seh_exception_handle]
        *(uint64_t*)(&catchjmp[2]) = (uint64_t)&_seh_exception_handler;
        catchjmp[10] = 0xff;
        catchjmp[11] = 0xe0; // jmp RAX
        UnwindData[0] = 0x09; // version info, UNW_FLAG_EHANDLER
        UnwindData[1] = 4;    // size of prolog (bytes)
        UnwindData[2] = 2;    // count of unwind codes (slots)
        UnwindData[3] = 0x05; // frame register (rbp) = rsp
        UnwindData[4] = 4;    // second instruction
        UnwindData[5] = 0x03; // mov RBP, RSP
        UnwindData[6] = 1;    // first instruction
        UnwindData[7] = 0x50; // push RBP
        *(DWORD*)&UnwindData[8] = (DWORD)(catchjmp - (uint8_t*)SectionAddr); // relative location of catchjmp
#else // defined(_OS_X86_64_)
        uint8_t *UnwindData = NULL;
#endif // defined(_OS_X86_64_)
#endif // defined(_OS_WINDOWS_)

#ifdef LLVM35
        for (const object::SymbolRef &sym_iter : obj.symbols()) {
#           ifdef LLVM37
            SymbolType = sym_iter.getType();
#           else
            sym_iter.getType(SymbolType);
#           endif
            if (SymbolType != object::SymbolRef::ST_Function) continue;
#           ifdef LLVM37
            Addr = sym_iter.getAddress().get();
#           else
            sym_iter.getAddress(Addr);
#           endif
            sym_iter.getSection(Section);
            if (Section == EndSection) continue;
#if defined(LLVM36)
            if (!Section->isText()) continue;
            Section->getName(sName);
            SectionAddr = L.getSectionLoadAddress(sName);
            Addr += SectionAddr;
#else
            if (Section->isText(isText) || !isText) continue;
#endif
#if defined(LLVM36)
            SectionSize = Section->getSize();
#else
            Section->getAddress(SectionAddr);
            Section->getSize(SectionSize);
#endif
#ifdef _OS_DARWIN_
#   if defined(LLVM37)
            Size = Section->getSize();
            sName = sym_iter.getName().get();
#   else
            sym_iter.getName(sName);
#   endif
#   if defined(LLVM36)
            if (sName[0] == '_') {
                sName = sName.substr(1);
            }
#   else
            Addr = ((MCJIT*)jl_ExecutionEngine)->getSymbolAddress(sName, true);
            if (!Addr && sName[0] == '_') {
                sName = sName.substr(1);
                Addr = ((MCJIT*)jl_ExecutionEngine)->getSymbolAddress(sName, true);
            }
            if (!Addr) continue;
#   endif
#elif defined(_OS_WINDOWS_)
#   if defined(LLVM37)
            assert(obj.isELF());
            Size = ((llvm::object::ELFSymbolRef)sym_iter).getSize();
            sName = sym_iter.getName().get();
#   else
            sym_iter.getSize(Size);
            sym_iter.getName(sName);
#   endif
#   ifdef _CPU_X86_
            if (sName[0] == '_') sName = sName.substr(1);
#   endif
            if (SectionAddrCheck)
                assert(SectionAddrCheck == SectionAddr);
            else
                SectionAddrCheck = SectionAddr;
            create_PRUNTIME_FUNCTION(
                   (uint8_t*)(intptr_t)Addr, (size_t)Size, sName,
                   (uint8_t*)(intptr_t)SectionAddr, (size_t)SectionSize, UnwindData);
#endif
            const object::ObjectFile *objfile =
#ifdef LLVM36
                &obj;
#else
                obj.getObjectFile();
#endif
            ObjectInfo tmp = {objfile, SectionSize
#ifdef LLVM37
                ,L.clone().release()
#elif defined(LLVM36)
                ,(size_t)SectionAddr
#endif
#ifdef _OS_DARWIN_
                ,strndup(sName.data(), sName.size())
#endif
            };
            objectmap[Addr] = tmp;
        }
#else //LLVM34
        error_code itererr;
        object::symbol_iterator sym_iter = obj.begin_symbols();
        object::symbol_iterator sym_end = obj.end_symbols();
        for (; sym_iter != sym_end; sym_iter.increment(itererr)) {
            sym_iter->getType(SymbolType);
            if (SymbolType != object::SymbolRef::ST_Function) continue;
            sym_iter->getAddress(Addr);
            sym_iter->getSize(Size);

            ObjectInfo tmp = {obj.getObjectFile(), (size_t)Size};
            objectmap[Addr] = tmp;
        }
#endif
    }