DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj) : IsLittleEndian(Obj.isLittleEndian()), AddressSize(Obj.getBytesInAddress()) { for (const SectionRef &Section : Obj.sections()) { StringRef name; Section.getName(name); // Skip BSS and Virtual sections, they aren't interesting. bool IsBSS = Section.isBSS(); if (IsBSS) continue; bool IsVirtual = Section.isVirtual(); if (IsVirtual) continue; StringRef data; Section.getContents(data); name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes. // Check if debug info section is compressed with zlib. if (name.startswith("zdebug_")) { uint64_t OriginalSize; if (!zlib::isAvailable() || !consumeCompressedDebugSectionHeader(data, OriginalSize)) continue; UncompressedSections.resize(UncompressedSections.size() + 1); if (zlib::uncompress(data, UncompressedSections.back(), OriginalSize) != zlib::StatusOK) { UncompressedSections.pop_back(); continue; } // Make data point to uncompressed section contents and save its contents. name = name.substr(1); data = UncompressedSections.back(); } StringRef *SectionData = StringSwitch<StringRef *>(name) .Case("debug_info", &InfoSection.Data) .Case("debug_abbrev", &AbbrevSection) .Case("debug_loc", &LocSection.Data) .Case("debug_line", &LineSection.Data) .Case("debug_aranges", &ARangeSection) .Case("debug_frame", &DebugFrameSection) .Case("debug_str", &StringSection) .Case("debug_ranges", &RangeSection) .Case("debug_pubnames", &PubNamesSection) .Case("debug_pubtypes", &PubTypesSection) .Case("debug_gnu_pubnames", &GnuPubNamesSection) .Case("debug_gnu_pubtypes", &GnuPubTypesSection) .Case("debug_info.dwo", &InfoDWOSection.Data) .Case("debug_abbrev.dwo", &AbbrevDWOSection) .Case("debug_loc.dwo", &LocDWOSection.Data) .Case("debug_line.dwo", &LineDWOSection.Data) .Case("debug_str.dwo", &StringDWOSection) .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) .Case("debug_addr", &AddrSection) .Case("apple_names", &AppleNamesSection.Data) .Case("apple_types", &AppleTypesSection.Data) .Case("apple_namespaces", &AppleNamespacesSection.Data) .Case("apple_namespac", &AppleNamespacesSection.Data) .Case("apple_objc", &AppleObjCSection.Data) // Any more debug info sections go here. .Default(nullptr); if (SectionData) { *SectionData = data; if (name == "debug_ranges") { // FIXME: Use the other dwo range section when we emit it. RangeDWOSection = data; } } else if (name == "debug_types") { // Find debug_types data by section rather than name as there are // multiple, comdat grouped, debug_types sections. TypesSections[Section].Data = data; } else if (name == "debug_types.dwo") { TypesDWOSections[Section].Data = data; } section_iterator RelocatedSection = Section.getRelocatedSection(); if (RelocatedSection == Obj.section_end()) continue; StringRef RelSecName; RelocatedSection->getName(RelSecName); RelSecName = RelSecName.substr( RelSecName.find_first_not_of("._")); // Skip . and _ prefixes. // TODO: Add support for relocations in other sections as needed. // Record relocations for the debug_info and debug_line sections. RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName) .Case("debug_info", &InfoSection.Relocs) .Case("debug_loc", &LocSection.Relocs) .Case("debug_info.dwo", &InfoDWOSection.Relocs) .Case("debug_line", &LineSection.Relocs) .Case("apple_names", &AppleNamesSection.Relocs) .Case("apple_types", &AppleTypesSection.Relocs) .Case("apple_namespaces", &AppleNamespacesSection.Relocs) .Case("apple_namespac", &AppleNamespacesSection.Relocs) .Case("apple_objc", &AppleObjCSection.Relocs) .Default(nullptr); if (!Map) { // Find debug_types relocs by section rather than name as there are // multiple, comdat grouped, debug_types sections. if (RelSecName == "debug_types") Map = &TypesSections[*RelocatedSection].Relocs; else if (RelSecName == "debug_types.dwo") Map = &TypesDWOSections[*RelocatedSection].Relocs; else continue; } if (Section.relocation_begin() != Section.relocation_end()) { uint64_t SectionSize = RelocatedSection->getSize(); for (const RelocationRef &Reloc : Section.relocations()) { uint64_t Address; Reloc.getOffset(Address); uint64_t Type; Reloc.getType(Type); uint64_t SymAddr = 0; object::symbol_iterator Sym = Reloc.getSymbol(); if (Sym != Obj.symbol_end()) Sym->getAddress(SymAddr); object::RelocVisitor V(Obj); object::RelocToApply R(V.visit(Type, Reloc, SymAddr)); if (V.error()) { SmallString<32> Name; std::error_code ec(Reloc.getTypeName(Name)); if (ec) { errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n"; } errs() << "error: failed to compute relocation: " << Name << "\n"; continue; } if (Address + R.Width > SectionSize) { errs() << "error: " << R.Width << "-byte relocation starting " << Address << " bytes into section " << name << " which is " << SectionSize << " bytes long.\n"; continue; } if (R.Width > 8) { errs() << "error: can't handle a relocation of more than 8 bytes at " "a time.\n"; continue; } DEBUG(dbgs() << "Writing " << format("%p", R.Value) << " at " << format("%p", Address) << " with width " << format("%d", R.Width) << "\n"); Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value))); } } } }
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L) : IsLittleEndian(Obj.isLittleEndian()), AddressSize(Obj.getBytesInAddress()) { for (const SectionRef &Section : Obj.sections()) { StringRef name; Section.getName(name); // Skip BSS and Virtual sections, they aren't interesting. bool IsBSS = Section.isBSS(); if (IsBSS) continue; bool IsVirtual = Section.isVirtual(); if (IsVirtual) continue; StringRef data; // Try to obtain an already relocated version of this section. // Else use the unrelocated section from the object file. We'll have to // apply relocations ourselves later. if (!L || !L->getLoadedSectionContents(name,data)) Section.getContents(data); name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes. // Check if debug info section is compressed with zlib. if (name.startswith("zdebug_")) { uint64_t OriginalSize; if (!zlib::isAvailable() || !consumeCompressedDebugSectionHeader(data, OriginalSize)) continue; UncompressedSections.resize(UncompressedSections.size() + 1); if (zlib::uncompress(data, UncompressedSections.back(), OriginalSize) != zlib::StatusOK) { UncompressedSections.pop_back(); continue; } // Make data point to uncompressed section contents and save its contents. name = name.substr(1); data = UncompressedSections.back(); } StringRef *SectionData = StringSwitch<StringRef *>(name) .Case("debug_info", &InfoSection.Data) .Case("debug_abbrev", &AbbrevSection) .Case("debug_loc", &LocSection.Data) .Case("debug_line", &LineSection.Data) .Case("debug_aranges", &ARangeSection) .Case("debug_frame", &DebugFrameSection) .Case("debug_str", &StringSection) .Case("debug_ranges", &RangeSection) .Case("debug_pubnames", &PubNamesSection) .Case("debug_pubtypes", &PubTypesSection) .Case("debug_gnu_pubnames", &GnuPubNamesSection) .Case("debug_gnu_pubtypes", &GnuPubTypesSection) .Case("debug_info.dwo", &InfoDWOSection.Data) .Case("debug_abbrev.dwo", &AbbrevDWOSection) .Case("debug_loc.dwo", &LocDWOSection.Data) .Case("debug_line.dwo", &LineDWOSection.Data) .Case("debug_str.dwo", &StringDWOSection) .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) .Case("debug_addr", &AddrSection) .Case("apple_names", &AppleNamesSection.Data) .Case("apple_types", &AppleTypesSection.Data) .Case("apple_namespaces", &AppleNamespacesSection.Data) .Case("apple_namespac", &AppleNamespacesSection.Data) .Case("apple_objc", &AppleObjCSection.Data) // Any more debug info sections go here. .Default(nullptr); if (SectionData) { *SectionData = data; if (name == "debug_ranges") { // FIXME: Use the other dwo range section when we emit it. RangeDWOSection = data; } } else if (name == "debug_types") { // Find debug_types data by section rather than name as there are // multiple, comdat grouped, debug_types sections. TypesSections[Section].Data = data; } else if (name == "debug_types.dwo") { TypesDWOSections[Section].Data = data; } section_iterator RelocatedSection = Section.getRelocatedSection(); if (RelocatedSection == Obj.section_end()) continue; StringRef RelSecName; StringRef RelSecData; RelocatedSection->getName(RelSecName); // If the section we're relocating was relocated already by the JIT, // then we used the relocated version above, so we do not need to process // relocations for it now. if (L && L->getLoadedSectionContents(RelSecName,RelSecData)) continue; RelSecName = RelSecName.substr( RelSecName.find_first_not_of("._")); // Skip . and _ prefixes. // TODO: Add support for relocations in other sections as needed. // Record relocations for the debug_info and debug_line sections. RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName) .Case("debug_info", &InfoSection.Relocs) .Case("debug_loc", &LocSection.Relocs) .Case("debug_info.dwo", &InfoDWOSection.Relocs) .Case("debug_line", &LineSection.Relocs) .Case("apple_names", &AppleNamesSection.Relocs) .Case("apple_types", &AppleTypesSection.Relocs) .Case("apple_namespaces", &AppleNamespacesSection.Relocs) .Case("apple_namespac", &AppleNamespacesSection.Relocs) .Case("apple_objc", &AppleObjCSection.Relocs) .Default(nullptr); if (!Map) { // Find debug_types relocs by section rather than name as there are // multiple, comdat grouped, debug_types sections. if (RelSecName == "debug_types") Map = &TypesSections[*RelocatedSection].Relocs; else if (RelSecName == "debug_types.dwo") Map = &TypesDWOSections[*RelocatedSection].Relocs; else continue; } if (Section.relocation_begin() != Section.relocation_end()) { uint64_t SectionSize = RelocatedSection->getSize(); for (const RelocationRef &Reloc : Section.relocations()) { uint64_t Address; Reloc.getOffset(Address); uint64_t Type; Reloc.getType(Type); uint64_t SymAddr = 0; uint64_t SectionLoadAddress = 0; object::symbol_iterator Sym = Reloc.getSymbol(); object::section_iterator RSec = Obj.section_end(); // First calculate the address of the symbol or section as it appears // in the objct file if (Sym != Obj.symbol_end()) { Sym->getAddress(SymAddr); // Also remember what section this symbol is in for later Sym->getSection(RSec); } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) { // MachO also has relocations that point to sections and // scattered relocations. // FIXME: We are not handling scattered relocations, do we have to? RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl()); SymAddr = RSec->getAddress(); } // If we are given load addresses for the sections, we need to adjust: // SymAddr = (Address of Symbol Or Section in File) - // (Address of Section in File) + // (Load Address of Section) if (L != nullptr && RSec != Obj.section_end()) { // RSec is now either the section being targetted or the section // containing the symbol being targetted. In either case, // we need to perform the same computation. StringRef SecName; RSec->getName(SecName); SectionLoadAddress = L->getSectionLoadAddress(SecName); if (SectionLoadAddress != 0) SymAddr += SectionLoadAddress - RSec->getAddress(); } object::RelocVisitor V(Obj); object::RelocToApply R(V.visit(Type, Reloc, SymAddr)); if (V.error()) { SmallString<32> Name; std::error_code ec(Reloc.getTypeName(Name)); if (ec) { errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n"; } errs() << "error: failed to compute relocation: " << Name << "\n"; continue; } if (Address + R.Width > SectionSize) { errs() << "error: " << R.Width << "-byte relocation starting " << Address << " bytes into section " << name << " which is " << SectionSize << " bytes long.\n"; continue; } if (R.Width > 8) { errs() << "error: can't handle a relocation of more than 8 bytes at " "a time.\n"; continue; } DEBUG(dbgs() << "Writing " << format("%p", R.Value) << " at " << format("%p", Address) << " with width " << format("%d", R.Width) << "\n"); Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value))); } } } }
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L) : IsLittleEndian(Obj.isLittleEndian()), AddressSize(Obj.getBytesInAddress()) { for (const SectionRef &Section : Obj.sections()) { StringRef name; Section.getName(name); // Skip BSS and Virtual sections, they aren't interesting. bool IsBSS = Section.isBSS(); if (IsBSS) continue; bool IsVirtual = Section.isVirtual(); if (IsVirtual) continue; StringRef data; section_iterator RelocatedSection = Section.getRelocatedSection(); // Try to obtain an already relocated version of this section. // Else use the unrelocated section from the object file. We'll have to // apply relocations ourselves later. if (!L || !L->getLoadedSectionContents(*RelocatedSection,data)) Section.getContents(data); name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes. bool ZLibStyleCompressed = Section.isCompressed(); if (ZLibStyleCompressed || name.startswith("zdebug_")) { SmallString<32> Out; if (!tryDecompress(name, data, Out, ZLibStyleCompressed, IsLittleEndian, AddressSize == 8)) continue; UncompressedSections.emplace_back(std::move(Out)); data = UncompressedSections.back(); } StringRef *SectionData = StringSwitch<StringRef *>(name) .Case("debug_info", &InfoSection.Data) .Case("debug_abbrev", &AbbrevSection) .Case("debug_loc", &LocSection.Data) .Case("debug_line", &LineSection.Data) .Case("debug_aranges", &ARangeSection) .Case("debug_frame", &DebugFrameSection) .Case("eh_frame", &EHFrameSection) .Case("debug_str", &StringSection) .Case("debug_ranges", &RangeSection) .Case("debug_macinfo", &MacinfoSection) .Case("debug_pubnames", &PubNamesSection) .Case("debug_pubtypes", &PubTypesSection) .Case("debug_gnu_pubnames", &GnuPubNamesSection) .Case("debug_gnu_pubtypes", &GnuPubTypesSection) .Case("debug_info.dwo", &InfoDWOSection.Data) .Case("debug_abbrev.dwo", &AbbrevDWOSection) .Case("debug_loc.dwo", &LocDWOSection.Data) .Case("debug_line.dwo", &LineDWOSection.Data) .Case("debug_str.dwo", &StringDWOSection) .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) .Case("debug_addr", &AddrSection) .Case("apple_names", &AppleNamesSection.Data) .Case("apple_types", &AppleTypesSection.Data) .Case("apple_namespaces", &AppleNamespacesSection.Data) .Case("apple_namespac", &AppleNamespacesSection.Data) .Case("apple_objc", &AppleObjCSection.Data) .Case("debug_cu_index", &CUIndexSection) .Case("debug_tu_index", &TUIndexSection) // Any more debug info sections go here. .Default(nullptr); if (SectionData) { *SectionData = data; if (name == "debug_ranges") { // FIXME: Use the other dwo range section when we emit it. RangeDWOSection = data; } } else if (name == "debug_types") { // Find debug_types data by section rather than name as there are // multiple, comdat grouped, debug_types sections. TypesSections[Section].Data = data; } else if (name == "debug_types.dwo") { TypesDWOSections[Section].Data = data; } if (RelocatedSection == Obj.section_end()) continue; StringRef RelSecName; StringRef RelSecData; RelocatedSection->getName(RelSecName); // If the section we're relocating was relocated already by the JIT, // then we used the relocated version above, so we do not need to process // relocations for it now. if (L && L->getLoadedSectionContents(*RelocatedSection,RelSecData)) continue; // In Mach-o files, the relocations do not need to be applied if // there is no load offset to apply. The value read at the // relocation point already factors in the section address // (actually applying the relocations will produce wrong results // as the section address will be added twice). if (!L && isa<MachOObjectFile>(&Obj)) continue; RelSecName = RelSecName.substr( RelSecName.find_first_not_of("._")); // Skip . and _ prefixes. // TODO: Add support for relocations in other sections as needed. // Record relocations for the debug_info and debug_line sections. RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName) .Case("debug_info", &InfoSection.Relocs) .Case("debug_loc", &LocSection.Relocs) .Case("debug_info.dwo", &InfoDWOSection.Relocs) .Case("debug_line", &LineSection.Relocs) .Case("apple_names", &AppleNamesSection.Relocs) .Case("apple_types", &AppleTypesSection.Relocs) .Case("apple_namespaces", &AppleNamespacesSection.Relocs) .Case("apple_namespac", &AppleNamespacesSection.Relocs) .Case("apple_objc", &AppleObjCSection.Relocs) .Default(nullptr); if (!Map) { // Find debug_types relocs by section rather than name as there are // multiple, comdat grouped, debug_types sections. if (RelSecName == "debug_types") Map = &TypesSections[*RelocatedSection].Relocs; else if (RelSecName == "debug_types.dwo") Map = &TypesDWOSections[*RelocatedSection].Relocs; else continue; } if (Section.relocation_begin() != Section.relocation_end()) { uint64_t SectionSize = RelocatedSection->getSize(); for (const RelocationRef &Reloc : Section.relocations()) { uint64_t Address = Reloc.getOffset(); uint64_t Type = Reloc.getType(); uint64_t SymAddr = 0; uint64_t SectionLoadAddress = 0; object::symbol_iterator Sym = Reloc.getSymbol(); object::section_iterator RSec = Obj.section_end(); // First calculate the address of the symbol or section as it appears // in the objct file if (Sym != Obj.symbol_end()) { ErrorOr<uint64_t> SymAddrOrErr = Sym->getAddress(); if (std::error_code EC = SymAddrOrErr.getError()) { errs() << "error: failed to compute symbol address: " << EC.message() << '\n'; continue; } SymAddr = *SymAddrOrErr; // Also remember what section this symbol is in for later auto SectOrErr = Sym->getSection(); if (!SectOrErr) { std::string Buf; raw_string_ostream OS(Buf); logAllUnhandledErrors(SectOrErr.takeError(), OS, ""); OS.flush(); errs() << "error: failed to get symbol section: " << Buf << '\n'; continue; } RSec = *SectOrErr; } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) { // MachO also has relocations that point to sections and // scattered relocations. auto RelocInfo = MObj->getRelocation(Reloc.getRawDataRefImpl()); if (MObj->isRelocationScattered(RelocInfo)) { // FIXME: it's not clear how to correctly handle scattered // relocations. continue; } else { RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl()); SymAddr = RSec->getAddress(); } } // If we are given load addresses for the sections, we need to adjust: // SymAddr = (Address of Symbol Or Section in File) - // (Address of Section in File) + // (Load Address of Section) if (L != nullptr && RSec != Obj.section_end()) { // RSec is now either the section being targeted or the section // containing the symbol being targeted. In either case, // we need to perform the same computation. StringRef SecName; RSec->getName(SecName); // llvm::dbgs() << "Name: '" << SecName // << "', RSec: " << RSec->getRawDataRefImpl() // << ", Section: " << Section.getRawDataRefImpl() << "\n"; SectionLoadAddress = L->getSectionLoadAddress(*RSec); if (SectionLoadAddress != 0) SymAddr += SectionLoadAddress - RSec->getAddress(); } object::RelocVisitor V(Obj); object::RelocToApply R(V.visit(Type, Reloc, SymAddr)); if (V.error()) { SmallString<32> Name; Reloc.getTypeName(Name); errs() << "error: failed to compute relocation: " << Name << "\n"; continue; } if (Address + R.Width > SectionSize) { errs() << "error: " << R.Width << "-byte relocation starting " << Address << " bytes into section " << name << " which is " << SectionSize << " bytes long.\n"; continue; } if (R.Width > 8) { errs() << "error: can't handle a relocation of more than 8 bytes at " "a time.\n"; continue; } DEBUG(dbgs() << "Writing " << format("%p", R.Value) << " at " << format("%p", Address) << " with width " << format("%d", R.Width) << "\n"); Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value))); } } } }
std::pair<unsigned, unsigned> RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { MutexGuard locked(lock); // Grab the first Section ID. We'll use this later to construct the underlying // range for the returned LoadedObjectInfo. unsigned SectionsAddedBeginIdx = Sections.size(); // Save information about our target Arch = (Triple::ArchType)Obj.getArch(); IsTargetLittleEndian = Obj.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); } // 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.symbol_begin(), E = Obj.symbol_end(); 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. if (!GlobalSymbolTable.count(Name)) { 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 SectOffset; StringRef SectionData; section_iterator SI = Obj.section_end(); Check(getOffset(*I, SectOffset)); Check(I->getSection(SI)); if (SI == Obj.section_end()) continue; Check(SI->getContents(SectionData)); bool IsCode = SI->isText(); unsigned SectionID = findOrEmitSection(Obj, *SI, IsCode, LocalSections); DEBUG(dbgs() << "\tOffset: " << format("%p", (uintptr_t)SectOffset) << " flags: " << Flags << " SID: " << SectionID); GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset); } } DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); } // Allocate common symbols if (CommonSize != 0) emitCommonSymbols(Obj, CommonSymbols, CommonSize, GlobalSymbolTable); // Parse and process relocations DEBUG(dbgs() << "Parse relocations:\n"); for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { unsigned SectionID = 0; StubMap Stubs; section_iterator RelocatedSection = SI->getRelocatedSection(); relocation_iterator I = SI->relocation_begin(); relocation_iterator E = SI->relocation_end(); if (I == E && !ProcessAllSections) continue; bool IsCode = RelocatedSection->isText(); SectionID = findOrEmitSection(Obj, *RelocatedSection, IsCode, LocalSections); DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); for (; I != E;) I = processRelocationRef(SectionID, I, Obj, LocalSections, Stubs); // If there is an attached checker, notify it about the stubs for this // section so that they can be verified. if (Checker) Checker->registerStubMap(Obj.getFileName(), SectionID, Stubs); } // Give the subclasses a chance to tie-up any loose ends. finalizeLoad(Obj, LocalSections); unsigned SectionsAddedEndIdx = Sections.size(); return std::make_pair(SectionsAddedBeginIdx, SectionsAddedEndIdx); }
std::pair<unsigned, unsigned> RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { MutexGuard locked(lock); // Grab the first Section ID. We'll use this later to construct the underlying // range for the returned LoadedObjectInfo. unsigned SectionsAddedBeginIdx = Sections.size(); // Save information about our target Arch = (Triple::ArchType)Obj.getArch(); IsTargetLittleEndian = Obj.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); } // Used sections from the object file ObjSectionToIDMap LocalSections; // Common symbols requiring allocation, with their sizes and alignments CommonSymbolList CommonSymbols; // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { uint32_t Flags = I->getFlags(); bool IsCommon = Flags & SymbolRef::SF_Common; bool IsWeak = Flags & SymbolRef::SF_Weak; if (IsCommon) { CommonSymbols.push_back(*I); } else { object::SymbolRef::Type SymType; Check(I->getType(SymType)); if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || SymType == object::SymbolRef::ST_Unknown) { StringRef Name; uint64_t SectOffset; Check(I->getName(Name)); Check(getOffset(*I, SectOffset)); section_iterator SI = Obj.section_end(); Check(I->getSection(SI)); if (SI == Obj.section_end()) continue; StringRef SectionData; Check(SI->getContents(SectionData)); // TODO: It make make sense to delay emitting the section for weak // symbols until they are actually required, but that's not possible // currently, because we only know whether we will need the symbol // in resolveRelocations, which happens after we have already finalized // the Load. bool IsCode = SI->isText(); unsigned SectionID = findOrEmitSection(Obj, *SI, IsCode, LocalSections); DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << " SID: " << SectionID << " Offset: " << format("%p", (uintptr_t)SectOffset) << " flags: " << Flags << "\n"); SymbolInfo::Visibility Vis = (Flags & SymbolRef::SF_Exported) ? SymbolInfo::Default : SymbolInfo::Hidden; if (!IsWeak) { GlobalSymbolTable[Name] = SymbolInfo(SectionID, SectOffset, Vis); } else { WeakSymbolTable[Name] = SymbolInfo(SectionID, SectOffset, Vis); } } } } // Allocate common symbols emitCommonSymbols(Obj, CommonSymbols); // Parse and process relocations DEBUG(dbgs() << "Parse relocations:\n"); for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { unsigned SectionID = 0; StubMap Stubs; section_iterator RelocatedSection = SI->getRelocatedSection(); relocation_iterator I = SI->relocation_begin(); relocation_iterator E = SI->relocation_end(); if (I == E && !ProcessAllSections) continue; bool IsCode = RelocatedSection->isText(); SectionID = findOrEmitSection(Obj, *RelocatedSection, IsCode, LocalSections); DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); for (; I != E;) I = processRelocationRef(SectionID, I, Obj, LocalSections, Stubs); // If there is an attached checker, notify it about the stubs for this // section so that they can be verified. if (Checker) Checker->registerStubMap(Obj.getFileName(), SectionID, Stubs); } // Give the subclasses a chance to tie-up any loose ends. finalizeLoad(Obj, LocalSections); unsigned SectionsAddedEndIdx = Sections.size(); return std::make_pair(SectionsAddedBeginIdx, SectionsAddedEndIdx); }