std::vector<std::pair<SymbolRef, uint64_t>> llvm::object::computeSymbolSizes(const ObjectFile &O) { std::vector<std::pair<SymbolRef, uint64_t>> Ret; if (const auto *E = dyn_cast<ELFObjectFileBase>(&O)) { auto Syms = E->symbols(); if (Syms.begin() == Syms.end()) Syms = E->getDynamicSymbolIterators(); for (ELFSymbolRef Sym : Syms) Ret.push_back({Sym, Sym.getSize()}); return Ret; } // Collect sorted symbol addresses. Include dummy addresses for the end // of each section. std::vector<SymEntry> Addresses; unsigned SymNum = 0; for (symbol_iterator I = O.symbol_begin(), E = O.symbol_end(); I != E; ++I) { SymbolRef Sym = *I; uint64_t Value = Sym.getValue(); Addresses.push_back({I, Value, SymNum, getSymbolSectionID(O, Sym)}); ++SymNum; } for (SectionRef Sec : O.sections()) { uint64_t Address = Sec.getAddress(); uint64_t Size = Sec.getSize(); Addresses.push_back( {O.symbol_end(), Address + Size, 0, getSectionID(O, Sec)}); } array_pod_sort(Addresses.begin(), Addresses.end(), compareAddress); // Compute the size as the gap to the next symbol for (unsigned I = 0, N = Addresses.size() - 1; I < N; ++I) { auto &P = Addresses[I]; if (P.I == O.symbol_end()) continue; // If multiple symbol have the same address, give both the same size. unsigned NextI = I + 1; while (NextI < N && Addresses[NextI].Address == P.Address) ++NextI; uint64_t Size = Addresses[NextI].Address - P.Address; P.Address = Size; } // Assign the sorted symbols in the original order. Ret.resize(SymNum); for (SymEntry &P : Addresses) { if (P.I == O.symbol_end()) continue; Ret[P.Number] = {*P.I, P.Address}; } return Ret; }
// 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); }