void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) { unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; unsigned TextSID = RTDYLD_INVALID_SECTION_ID; unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; for (const auto &Section : Obj.sections()) { StringRef Name; Section.getName(Name); // Force emission of the __text, __eh_frame, and __gcc_except_tab sections // if they're present. Otherwise call down to the impl to handle other // sections that have already been emitted. if (Name == "__text") TextSID = findOrEmitSection(Obj, Section, true, SectionMap); else if (Name == "__eh_frame") EHFrameSID = findOrEmitSection(Obj, Section, false, SectionMap); else if (Name == "__gcc_except_tab") ExceptTabSID = findOrEmitSection(Obj, Section, true, SectionMap); else { auto I = SectionMap.find(Section); if (I != SectionMap.end()) impl().finalizeSection(Obj, I->second, Section); } } UnregisteredEHFrameSections.push_back( EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); }
relocation_iterator RuntimeDyldMachO::processScatteredVANILLA( unsigned SectionID, relocation_iterator RelI, const ObjectFile &BaseObjT, RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) { const MachOObjectFile &Obj = static_cast<const MachOObjectFile&>(BaseObjT); MachO::any_relocation_info RE = Obj.getRelocation(RelI->getRawDataRefImpl()); SectionEntry &Section = Sections[SectionID]; uint32_t RelocType = Obj.getAnyRelocationType(RE); bool IsPCRel = Obj.getAnyRelocationPCRel(RE); unsigned Size = Obj.getAnyRelocationLength(RE); uint64_t Offset = RelI->getOffset(); uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); unsigned NumBytes = 1 << Size; int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes); unsigned SymbolBaseAddr = Obj.getScatteredRelocationValue(RE); section_iterator TargetSI = getSectionByAddress(Obj, SymbolBaseAddr); assert(TargetSI != Obj.section_end() && "Can't find section for symbol"); uint64_t SectionBaseAddr = TargetSI->getAddress(); SectionRef TargetSection = *TargetSI; bool IsCode = TargetSection.isText(); uint32_t TargetSectionID = findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID); Addend -= SectionBaseAddr; RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size); addRelocationForSection(R, TargetSectionID); return ++RelI; }
RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( const ObjectFile &BaseTObj, const relocation_iterator &RI, const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) { const MachOObjectFile &Obj = static_cast<const MachOObjectFile &>(BaseTObj); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); RelocationValueRef Value; bool IsExternal = Obj.getPlainRelocationExternal(RelInfo); if (IsExternal) { symbol_iterator Symbol = RI->getSymbol(); StringRef TargetName; Symbol->getName(TargetName); SymbolTableMap::const_iterator SI = GlobalSymbolTable.find(TargetName.data()); if (SI != GlobalSymbolTable.end()) { Value.SectionID = SI->second.first; Value.Offset = SI->second.second + RE.Addend; } else { Value.SymbolName = TargetName.data(); Value.Offset = RE.Addend; } } else { SectionRef Sec = Obj.getRelocationSection(RelInfo); bool IsCode = Sec.isText(); Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); uint64_t Addr = Sec.getAddress(); Value.Offset = RE.Addend - Addr; } return Value; }
RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( const ObjectFile &BaseTObj, const relocation_iterator &RI, const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) { const MachOObjectFile &Obj = static_cast<const MachOObjectFile &>(BaseTObj); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); RelocationValueRef Value; bool IsExternal = Obj.getPlainRelocationExternal(RelInfo); if (IsExternal) { symbol_iterator Symbol = RI->getSymbol(); ErrorOr<StringRef> TargetNameOrErr = Symbol->getName(); if (std::error_code EC = TargetNameOrErr.getError()) report_fatal_error(EC.message()); StringRef TargetName = *TargetNameOrErr; RTDyldSymbolTable::const_iterator SI = GlobalSymbolTable.find(TargetName.data()); if (SI != GlobalSymbolTable.end()) { const auto &SymInfo = SI->second; Value.SectionID = SymInfo.getSectionID(); Value.Offset = SymInfo.getOffset() + RE.Addend; } else { Value.SymbolName = TargetName.data(); Value.Offset = RE.Addend; } } else { SectionRef Sec = Obj.getAnyRelocationSection(RelInfo); bool IsCode = Sec.isText(); Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); uint64_t Addr = Sec.getAddress(); Value.Offset = RE.Addend - Addr; } return Value; }
bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) { // FIXME: ObjectFile don't modify MemoryBuffer. // It should use const MemoryBuffer as parameter. OwningPtr<ObjectFile> obj(ObjectFile::createObjectFile( const_cast<MemoryBuffer*>(InputBuffer))); if (!obj) report_fatal_error("Unable to create object image from memory buffer!"); Arch = (Triple::ArchType)obj->getArch(); LocalSymbolMap LocalSymbols; // Functions and data symbols from the // object file. ObjSectionToIDMap LocalSections; // Used sections from the object file CommonSymbolMap CommonSymbols; // Common symbols requiring allocation uint64_t CommonSize = 0; error_code err; // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); for (symbol_iterator i = obj->begin_symbols(), e = obj->end_symbols(); i != e; i.increment(err)) { Check(err); object::SymbolRef::Type SymType; StringRef Name; Check(i->getType(SymType)); Check(i->getName(Name)); uint32_t flags; Check(i->getFlags(flags)); bool isCommon = flags & SymbolRef::SF_Common; if (isCommon) { // Add the common symbols to a list. We'll allocate them all below. uint64_t Size = 0; Check(i->getSize(Size)); CommonSize += Size; CommonSymbols[*i] = Size; } else { if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data) { uint64_t FileOffset; StringRef sData; section_iterator si = obj->end_sections(); Check(i->getFileOffset(FileOffset)); Check(i->getSection(si)); if (si == obj->end_sections()) continue; Check(si->getContents(sData)); const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() + (uintptr_t)FileOffset; uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t*)sData.begin()); unsigned SectionID = findOrEmitSection(*si, SymType == object::SymbolRef::ST_Function, LocalSections); bool isGlobal = flags & SymbolRef::SF_Global; LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset) << " flags: " << flags << " SID: " << SectionID << " Offset: " << format("%p", SectOffset)); if (isGlobal) SymbolTable[Name] = SymbolLoc(SectionID, SectOffset); } } DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); } // Allocate common symbols if (CommonSize != 0) emitCommonSymbols(CommonSymbols, CommonSize, LocalSymbols); // Parse and proccess relocations DEBUG(dbgs() << "Parse relocations:\n"); for (section_iterator si = obj->begin_sections(), se = obj->end_sections(); si != se; si.increment(err)) { Check(err); bool isFirstRelocation = true; unsigned SectionID = 0; StubMap Stubs; for (relocation_iterator i = si->begin_relocations(), e = si->end_relocations(); i != e; i.increment(err)) { Check(err); // If it's first relocation in this section, find its SectionID if (isFirstRelocation) { SectionID = findOrEmitSection(*si, true, LocalSections); DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); isFirstRelocation = false; } ObjRelocationInfo RI; RI.SectionID = SectionID; Check(i->getAdditionalInfo(RI.AdditionalInfo)); Check(i->getOffset(RI.Offset)); Check(i->getSymbol(RI.Symbol)); Check(i->getType(RI.Type)); DEBUG(dbgs() << "\t\tAddend: " << RI.AdditionalInfo << " Offset: " << format("%p", (uintptr_t)RI.Offset) << " Type: " << (uint32_t)(RI.Type & 0xffffffffL) << "\n"); processRelocationRef(RI, *obj, LocalSections, LocalSymbols, Stubs); } } return false; }
ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer)); if (!obj) report_fatal_error("Unable to create object image from memory buffer!"); Arch = (Triple::ArchType)obj->getArch(); // Symbols found in this object StringMap<SymbolLoc> LocalSymbols; // Used sections from the object file ObjSectionToIDMap LocalSections; // Common symbols requiring allocation, with their sizes and alignments CommonSymbolMap CommonSymbols; // Maximum required total memory to allocate all common symbols uint64_t CommonSize = 0; error_code err; // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); for (symbol_iterator i = obj->begin_symbols(), e = obj->end_symbols(); i != e; i.increment(err)) { Check(err); object::SymbolRef::Type SymType; StringRef Name; Check(i->getType(SymType)); Check(i->getName(Name)); uint32_t flags; Check(i->getFlags(flags)); bool isCommon = flags & SymbolRef::SF_Common; if (isCommon) { // Add the common symbols to a list. We'll allocate them all below. uint32_t Align; Check(i->getAlignment(Align)); uint64_t Size = 0; Check(i->getSize(Size)); CommonSize += Size + Align; CommonSymbols[*i] = CommonSymbolInfo(Size, Align); } else { if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || SymType == object::SymbolRef::ST_Unknown) { uint64_t FileOffset; StringRef SectionData; bool IsCode; section_iterator si = obj->end_sections(); Check(i->getFileOffset(FileOffset)); Check(i->getSection(si)); if (si == obj->end_sections()) continue; Check(si->getContents(SectionData)); Check(si->isText(IsCode)); const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() + (uintptr_t)FileOffset; uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t*)SectionData.begin()); unsigned SectionID = findOrEmitSection(*obj, *si, IsCode, LocalSections); LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset) << " flags: " << flags << " SID: " << SectionID << " Offset: " << format("%p", SectOffset)); GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset); } } DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); } // Allocate common symbols if (CommonSize != 0) emitCommonSymbols(*obj, CommonSymbols, CommonSize, LocalSymbols); // Parse and process relocations DEBUG(dbgs() << "Parse relocations:\n"); for (section_iterator si = obj->begin_sections(), se = obj->end_sections(); si != se; si.increment(err)) { Check(err); bool isFirstRelocation = true; unsigned SectionID = 0; StubMap Stubs; section_iterator RelocatedSection = si->getRelocatedSection(); for (relocation_iterator i = si->begin_relocations(), e = si->end_relocations(); i != e; i.increment(err)) { Check(err); // If it's the first relocation in this section, find its SectionID if (isFirstRelocation) { SectionID = findOrEmitSection(*obj, *RelocatedSection, true, LocalSections); DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); isFirstRelocation = false; } processRelocationRef(SectionID, *i, *obj, LocalSections, LocalSymbols, Stubs); } } return obj.take(); }
ObjectImage *RuntimeDyldImpl::loadObject(ObjectImage *InputObject) { MutexGuard locked(lock); std::unique_ptr<ObjectImage> Obj(InputObject); if (!Obj) return NULL; // Save information about our target Arch = (Triple::ArchType)Obj->getArch(); IsTargetLittleEndian = Obj->getObjectFile()->isLittleEndian(); // Compute the memory size required to load all sections to be loaded // and pass this information to the memory manager if (MemMgr->needsToReserveAllocationSpace()) { uint64_t CodeSize = 0, DataSizeRO = 0, DataSizeRW = 0; computeTotalAllocSize(*Obj, CodeSize, DataSizeRO, DataSizeRW); MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); } // Symbols found in this object StringMap<SymbolLoc> LocalSymbols; // Used sections from the object file ObjSectionToIDMap LocalSections; // Common symbols requiring allocation, with their sizes and alignments CommonSymbolMap CommonSymbols; // Maximum required total memory to allocate all common symbols uint64_t CommonSize = 0; // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); for (symbol_iterator I = Obj->begin_symbols(), E = Obj->end_symbols(); I != E; ++I) { object::SymbolRef::Type SymType; StringRef Name; Check(I->getType(SymType)); Check(I->getName(Name)); uint32_t Flags = I->getFlags(); bool IsCommon = Flags & SymbolRef::SF_Common; if (IsCommon) { // Add the common symbols to a list. We'll allocate them all below. uint32_t Align; Check(I->getAlignment(Align)); uint64_t Size = 0; Check(I->getSize(Size)); CommonSize += Size + Align; CommonSymbols[*I] = CommonSymbolInfo(Size, Align); } else { if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || SymType == object::SymbolRef::ST_Unknown) { uint64_t FileOffset; StringRef SectionData; bool IsCode; section_iterator SI = Obj->end_sections(); Check(I->getFileOffset(FileOffset)); Check(I->getSection(SI)); if (SI == Obj->end_sections()) continue; Check(SI->getContents(SectionData)); Check(SI->isText(IsCode)); const uint8_t *SymPtr = (const uint8_t *)Obj->getData().data() + (uintptr_t)FileOffset; uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t *)SectionData.begin()); unsigned SectionID = findOrEmitSection(*Obj, *SI, IsCode, LocalSections); LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset) << " flags: " << Flags << " SID: " << SectionID << " Offset: " << format("%p", SectOffset)); GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset); } } DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); } // Allocate common symbols if (CommonSize != 0) emitCommonSymbols(*Obj, CommonSymbols, CommonSize, LocalSymbols); // Parse and process relocations DEBUG(dbgs() << "Parse relocations:\n"); for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections(); SI != SE; ++SI) { unsigned SectionID = 0; StubMap Stubs; section_iterator RelocatedSection = SI->getRelocatedSection(); if (SI->relocation_empty() && !ProcessAllSections) continue; bool IsCode = false; Check(RelocatedSection->isText(IsCode)); SectionID = findOrEmitSection(*Obj, *RelocatedSection, IsCode, LocalSections); DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); for (relocation_iterator I = SI->relocation_begin(), E = SI->relocation_end(); I != E;) I = processRelocationRef(SectionID, I, *Obj, LocalSections, LocalSymbols, Stubs); } // Give the subclasses a chance to tie-up any loose ends. finalizeLoad(LocalSections); return Obj.release(); }