// compute stub buffer size for the given section unsigned RuntimeDyldImpl::computeSectionStubBufSize(const ObjectFile &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.section_begin(), SE = Obj.section_end(); 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; }
void ObjectLoadListener::recordRelocations( const ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &L) { for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { section_iterator Section = SI->getRelocatedSection(); if (Section == SE) { continue; } StringRef SectionName; std::error_code ErrorCode = Section->getName(SectionName); if (ErrorCode) { assert(false && ErrorCode.message().c_str()); } if (SectionName.startswith(".debug") || SectionName.startswith(".rela.debug") || !SectionName.compare(".pdata") || SectionName.startswith(".eh_frame") || SectionName.startswith(".rela.eh_frame")) { // Skip sections whose contents are not directly reported to the EE continue; } relocation_iterator I = SI->relocation_begin(); relocation_iterator E = SI->relocation_end(); for (; I != E; ++I) { symbol_iterator Symbol = I->getSymbol(); assert(Symbol != Obj.symbol_end()); ErrorOr<section_iterator> SymbolSectionOrErr = Symbol->getSection(); assert(!SymbolSectionOrErr.getError()); object::section_iterator SymbolSection = *SymbolSectionOrErr; const bool IsExtern = SymbolSection == Obj.section_end(); uint64_t RelType = I->getType(); uint64_t Offset = I->getOffset(); uint8_t *RelocationTarget; if (IsExtern) { // This is an external symbol. Verify that it's one we created for // a global variable and report the relocation via Jit interface. ErrorOr<StringRef> NameOrError = Symbol->getName(); assert(NameOrError); StringRef TargetName = NameOrError.get(); auto MapIter = Context->NameToHandleMap.find(TargetName); if (MapIter == Context->NameToHandleMap.end()) { // The xdata gets a pointer to our personality routine, which we // dummied up. We can safely skip it since the EE isn't actually // going to use the value (it inserts the correct one before handing // the xdata off to the OS). assert(!TargetName.compare("ProcessCLRException")); assert(SectionName.startswith(".xdata")); continue; } else { assert(MapIter->second == Context->NameToHandleMap[TargetName]); RelocationTarget = (uint8_t *)MapIter->second; } } else { RelocationTarget = (uint8_t *)(L.getSectionLoadAddress(*SymbolSection) + Symbol->getValue()); } uint64_t Addend = 0; uint64_t EERelType = getRelocationType(RelType); uint64_t SectionAddress = L.getSectionLoadAddress(*Section); assert(SectionAddress != 0); uint8_t *FixupAddress = (uint8_t *)(SectionAddress + Offset); if (Obj.isELF()) { // Addend is part of the relocation ELFRelocationRef ElfReloc(*I); ErrorOr<uint64_t> ElfAddend = ElfReloc.getAddend(); assert(!ElfAddend.getError()); Addend = ElfAddend.get(); } else { // Addend is read from the location to be fixed up Addend = getRelocationAddend(RelType, FixupAddress); } Context->JitInfo->recordRelocation(FixupAddress, RelocationTarget + Addend, EERelType); } } }
void ObjectLoadListener::recordRelocations( const ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &L) { for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { section_iterator Section = SI->getRelocatedSection(); if (Section == SE) { continue; } StringRef SectionName; std::error_code ErrorCode = Section->getName(SectionName); if (ErrorCode) { assert(false && ErrorCode.message().c_str()); } if (SectionName.startswith(".debug") || SectionName.startswith(".rela.debug") || !SectionName.compare(".pdata") || SectionName.startswith(".eh_frame") || SectionName.startswith(".rela.eh_frame")) { // Skip sections whose contents are not directly reported to the EE continue; } relocation_iterator I = SI->relocation_begin(); relocation_iterator E = SI->relocation_end(); for (; I != E; ++I) { symbol_iterator Symbol = I->getSymbol(); assert(Symbol != Obj.symbol_end()); ErrorOr<section_iterator> SymbolSectionOrErr = Symbol->getSection(); assert(!SymbolSectionOrErr.getError()); object::section_iterator SymbolSection = *SymbolSectionOrErr; const bool IsExtern = SymbolSection == Obj.section_end(); uint64_t RelType = I->getType(); uint64_t Offset = I->getOffset(); uint8_t *RelocationTarget = nullptr; if (IsExtern) { // This is an external symbol. Verify that it's one we created for // a global variable and report the relocation via Jit interface. ErrorOr<StringRef> NameOrError = Symbol->getName(); assert(NameOrError); StringRef TargetName = NameOrError.get(); assert(Context->NameToHandleMap.count(TargetName) == 1); RelocationTarget = (uint8_t *)Context->NameToHandleMap[TargetName]; } else { RelocationTarget = (uint8_t *)(L.getSectionLoadAddress(*SymbolSection) + Symbol->getValue()); } uint64_t Addend = 0; uint64_t EERelType = getRelocationType(RelType); uint64_t SectionAddress = L.getSectionLoadAddress(*Section); assert(SectionAddress != 0); uint8_t *FixupAddress = (uint8_t *)(SectionAddress + Offset); if (Obj.isELF()) { // Addend is part of the relocation ELFRelocationRef ElfReloc(*I); ErrorOr<uint64_t> ElfAddend = ElfReloc.getAddend(); assert(!ElfAddend.getError()); Addend = ElfAddend.get(); } else { // Addend is read from the location to be fixed up Addend = getRelocationAddend(RelType, FixupAddress); } Context->JitInfo->recordRelocation(FixupAddress, RelocationTarget + Addend, EERelType); } } }
// Compute an upper bound of the memory size that is required to load all // sections void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &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.section_begin(), SE = Obj.section_end(); 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.symbol_begin(), E = Obj.symbol_end(); 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); }
static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) { assert(LoadObjects || !UseDebugObj); // Load any dylibs requested on the command line. loadDylibs(); // If we don't have any input files, read from stdin. if (!InputFileList.size()) InputFileList.push_back("-"); for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { // Instantiate a dynamic linker. TrivialMemoryManager MemMgr; RuntimeDyld Dyld(MemMgr, MemMgr); // Load the input memory buffer. ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer = MemoryBuffer::getFileOrSTDIN(InputFileList[i]); if (std::error_code EC = InputBuffer.getError()) return Error("unable to read input: '" + EC.message() + "'"); ErrorOr<std::unique_ptr<ObjectFile>> MaybeObj( ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef())); if (std::error_code EC = MaybeObj.getError()) return Error("unable to create object file: '" + EC.message() + "'"); ObjectFile &Obj = **MaybeObj; OwningBinary<ObjectFile> DebugObj; std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo = nullptr; ObjectFile *SymbolObj = &Obj; if (LoadObjects) { // Load the object file LoadedObjInfo = Dyld.loadObject(Obj); if (Dyld.hasError()) return Error(Dyld.getErrorString()); // Resolve all the relocations we can. Dyld.resolveRelocations(); if (UseDebugObj) { DebugObj = LoadedObjInfo->getObjectForDebug(Obj); SymbolObj = DebugObj.getBinary(); LoadedObjInfo.reset(); } } std::unique_ptr<DIContext> Context( new DWARFContextInMemory(*SymbolObj,LoadedObjInfo.get())); std::vector<std::pair<SymbolRef, uint64_t>> SymAddr = object::computeSymbolSizes(*SymbolObj); // Use symbol info to iterate functions in the object. for (const auto &P : SymAddr) { object::SymbolRef Sym = P.first; if (Sym.getType() == object::SymbolRef::ST_Function) { ErrorOr<StringRef> Name = Sym.getName(); if (!Name) continue; ErrorOr<uint64_t> AddrOrErr = Sym.getAddress(); if (!AddrOrErr) continue; uint64_t Addr = *AddrOrErr; uint64_t Size = P.second; // If we're not using the debug object, compute the address of the // symbol in memory (rather than that in the unrelocated object file) // and use that to query the DWARFContext. if (!UseDebugObj && LoadObjects) { object::section_iterator Sec(SymbolObj->section_end()); Sym.getSection(Sec); StringRef SecName; Sec->getName(SecName); uint64_t SectionLoadAddress = LoadedObjInfo->getSectionLoadAddress(*Sec); if (SectionLoadAddress != 0) Addr += SectionLoadAddress - Sec->getAddress(); } outs() << "Function: " << *Name << ", Size = " << Size << ", Addr = " << Addr << "\n"; DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size); DILineInfoTable::iterator Begin = Lines.begin(); DILineInfoTable::iterator End = Lines.end(); for (DILineInfoTable::iterator It = Begin; It != End; ++It) { outs() << " Line info @ " << It->first - Addr << ": " << It->second.FileName << ", line:" << It->second.Line << "\n"; } } } } return 0; }