/// Retrieve the section named \a SecName in \a Obj. /// /// To accommodate for platform discrepancies, the name passed should be /// (for example) 'debug_info' to match either '__debug_info' or '.debug_info'. /// This function will strip the initial platform-specific characters. static Optional<object::SectionRef> getSectionByName(const object::ObjectFile &Obj, StringRef SecName) { for (const object::SectionRef &Section : Obj.sections()) { StringRef SectionName; Section.getName(SectionName); SectionName = SectionName.substr(SectionName.find_first_not_of("._")); if (SectionName != SecName) continue; return Section; } return None; }
void StackMapJITEventListener::NotifyObjectEmitted(const object::ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &LoadedObj) { std::error_code errorCode; for (const object::SectionRef& section: Obj.sections()) { StringRef name; errorCode = section.getName(name); assert(!errorCode); if (name == ".llvm_stackmaps") { uint64_t stackMapAddress = LoadedObj.getSectionLoadAddress(name); assert(stackMapAddress > 0); uint64_t expectedSize = section.getSize(); // check is made by the callee StackMap *map = parseStackMapFromAddress(stackMapAddress, expectedSize); Maps->push_back(map); } } }
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))); } } } }