10b57cec5SDimitry Andric //===- ObjectFile.cpp - File format independent object file ---------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines a file format independent ObjectFile class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 140b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 150b57cec5SDimitry Andric #include "llvm/BinaryFormat/Magic.h" 160b57cec5SDimitry Andric #include "llvm/Object/Binary.h" 170b57cec5SDimitry Andric #include "llvm/Object/COFF.h" 180b57cec5SDimitry Andric #include "llvm/Object/Error.h" 190b57cec5SDimitry Andric #include "llvm/Object/MachO.h" 200b57cec5SDimitry Andric #include "llvm/Object/Wasm.h" 210b57cec5SDimitry Andric #include "llvm/Support/Error.h" 220b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 230b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h" 2481ad6265SDimitry Andric #include "llvm/Support/Format.h" 250b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 260b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 270b57cec5SDimitry Andric #include <cstdint> 280b57cec5SDimitry Andric #include <memory> 290b57cec5SDimitry Andric #include <system_error> 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric using namespace llvm; 320b57cec5SDimitry Andric using namespace object; 330b57cec5SDimitry Andric 34480093f4SDimitry Andric raw_ostream &object::operator<<(raw_ostream &OS, const SectionedAddress &Addr) { 35480093f4SDimitry Andric OS << "SectionedAddress{" << format_hex(Addr.Address, 10); 36480093f4SDimitry Andric if (Addr.SectionIndex != SectionedAddress::UndefSection) 37480093f4SDimitry Andric OS << ", " << Addr.SectionIndex; 38480093f4SDimitry Andric return OS << "}"; 39480093f4SDimitry Andric } 40480093f4SDimitry Andric 410b57cec5SDimitry Andric void ObjectFile::anchor() {} 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric ObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source) 440b57cec5SDimitry Andric : SymbolicFile(Type, Source) {} 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric bool SectionRef::containsSymbol(SymbolRef S) const { 470b57cec5SDimitry Andric Expected<section_iterator> SymSec = S.getSection(); 480b57cec5SDimitry Andric if (!SymSec) { 490b57cec5SDimitry Andric // TODO: Actually report errors helpfully. 500b57cec5SDimitry Andric consumeError(SymSec.takeError()); 510b57cec5SDimitry Andric return false; 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric return *this == **SymSec; 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric 565ffd83dbSDimitry Andric Expected<uint64_t> ObjectFile::getSymbolValue(DataRefImpl Ref) const { 57349cc55cSDimitry Andric uint32_t Flags; 58349cc55cSDimitry Andric if (Error E = getSymbolFlags(Ref).moveInto(Flags)) 595ffd83dbSDimitry Andric // TODO: Test this error. 60349cc55cSDimitry Andric return std::move(E); 61349cc55cSDimitry Andric 62349cc55cSDimitry Andric if (Flags & SymbolRef::SF_Undefined) 63349cc55cSDimitry Andric return 0; 64349cc55cSDimitry Andric if (Flags & SymbolRef::SF_Common) 65349cc55cSDimitry Andric return getCommonSymbolSize(Ref); 660b57cec5SDimitry Andric return getSymbolValueImpl(Ref); 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric Error ObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const { 700b57cec5SDimitry Andric Expected<StringRef> Name = getSymbolName(Symb); 710b57cec5SDimitry Andric if (!Name) 720b57cec5SDimitry Andric return Name.takeError(); 730b57cec5SDimitry Andric OS << *Name; 740b57cec5SDimitry Andric return Error::success(); 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric uint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric bool ObjectFile::isSectionBitcode(DataRefImpl Sec) const { 808bcb0991SDimitry Andric Expected<StringRef> NameOrErr = getSectionName(Sec); 818bcb0991SDimitry Andric if (NameOrErr) 82*fe013be4SDimitry Andric return *NameOrErr == ".llvmbc" || *NameOrErr == ".llvm.lto"; 838bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 840b57cec5SDimitry Andric return false; 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric bool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric bool ObjectFile::isBerkeleyText(DataRefImpl Sec) const { 900b57cec5SDimitry Andric return isSectionText(Sec); 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const { 940b57cec5SDimitry Andric return isSectionData(Sec); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 97fe6060f1SDimitry Andric bool ObjectFile::isDebugSection(DataRefImpl Sec) const { return false; } 985ffd83dbSDimitry Andric 99bdd1243dSDimitry Andric bool ObjectFile::hasDebugInfo() const { 100bdd1243dSDimitry Andric return any_of(sections(), 101bdd1243dSDimitry Andric [](SectionRef Sec) { return Sec.isDebugSection(); }); 102bdd1243dSDimitry Andric } 103bdd1243dSDimitry Andric 1048bcb0991SDimitry Andric Expected<section_iterator> 1058bcb0991SDimitry Andric ObjectFile::getRelocatedSection(DataRefImpl Sec) const { 1060b57cec5SDimitry Andric return section_iterator(SectionRef(Sec, this)); 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric Triple ObjectFile::makeTriple() const { 1100b57cec5SDimitry Andric Triple TheTriple; 1110b57cec5SDimitry Andric auto Arch = getArch(); 1120b57cec5SDimitry Andric TheTriple.setArch(Triple::ArchType(Arch)); 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric // For ARM targets, try to use the build attributes to build determine 1150b57cec5SDimitry Andric // the build target. Target features are also added, but later during 1160b57cec5SDimitry Andric // disassembly. 1170b57cec5SDimitry Andric if (Arch == Triple::arm || Arch == Triple::armeb) 1180b57cec5SDimitry Andric setARMSubArch(TheTriple); 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric // TheTriple defaults to ELF, and COFF doesn't have an environment: 1215ffd83dbSDimitry Andric // something we can do here is indicate that it is mach-o. 1225ffd83dbSDimitry Andric if (isMachO()) { 1230b57cec5SDimitry Andric TheTriple.setObjectFormat(Triple::MachO); 1245ffd83dbSDimitry Andric } else if (isCOFF()) { 1258bcb0991SDimitry Andric const auto COFFObj = cast<COFFObjectFile>(this); 1260b57cec5SDimitry Andric if (COFFObj->getArch() == Triple::thumb) 1270b57cec5SDimitry Andric TheTriple.setTriple("thumbv7-windows"); 1285ffd83dbSDimitry Andric } else if (isXCOFF()) { 1295ffd83dbSDimitry Andric // XCOFF implies AIX. 1305ffd83dbSDimitry Andric TheTriple.setOS(Triple::AIX); 1315ffd83dbSDimitry Andric TheTriple.setObjectFormat(Triple::XCOFF); 1320b57cec5SDimitry Andric } 133*fe013be4SDimitry Andric else if (isGOFF()) { 134*fe013be4SDimitry Andric TheTriple.setOS(Triple::ZOS); 135*fe013be4SDimitry Andric TheTriple.setObjectFormat(Triple::GOFF); 136*fe013be4SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric return TheTriple; 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>> 142e8d8bef9SDimitry Andric ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type, 143e8d8bef9SDimitry Andric bool InitContent) { 1440b57cec5SDimitry Andric StringRef Data = Object.getBuffer(); 1450b57cec5SDimitry Andric if (Type == file_magic::unknown) 1460b57cec5SDimitry Andric Type = identify_magic(Data); 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric switch (Type) { 1490b57cec5SDimitry Andric case file_magic::unknown: 1500b57cec5SDimitry Andric case file_magic::bitcode: 1510b57cec5SDimitry Andric case file_magic::coff_cl_gl_object: 1520b57cec5SDimitry Andric case file_magic::archive: 1530b57cec5SDimitry Andric case file_magic::macho_universal_binary: 1540b57cec5SDimitry Andric case file_magic::windows_resource: 1550b57cec5SDimitry Andric case file_magic::pdb: 1560b57cec5SDimitry Andric case file_magic::minidump: 157fe6060f1SDimitry Andric case file_magic::goff_object: 15881ad6265SDimitry Andric case file_magic::cuda_fatbinary: 15981ad6265SDimitry Andric case file_magic::offload_binary: 16081ad6265SDimitry Andric case file_magic::dxcontainer_object: 1610b57cec5SDimitry Andric return errorCodeToError(object_error::invalid_file_type); 1628bcb0991SDimitry Andric case file_magic::tapi_file: 1638bcb0991SDimitry Andric return errorCodeToError(object_error::invalid_file_type); 1640b57cec5SDimitry Andric case file_magic::elf: 1650b57cec5SDimitry Andric case file_magic::elf_relocatable: 1660b57cec5SDimitry Andric case file_magic::elf_executable: 1670b57cec5SDimitry Andric case file_magic::elf_shared_object: 1680b57cec5SDimitry Andric case file_magic::elf_core: 169e8d8bef9SDimitry Andric return createELFObjectFile(Object, InitContent); 1700b57cec5SDimitry Andric case file_magic::macho_object: 1710b57cec5SDimitry Andric case file_magic::macho_executable: 1720b57cec5SDimitry Andric case file_magic::macho_fixed_virtual_memory_shared_lib: 1730b57cec5SDimitry Andric case file_magic::macho_core: 1740b57cec5SDimitry Andric case file_magic::macho_preload_executable: 1750b57cec5SDimitry Andric case file_magic::macho_dynamically_linked_shared_lib: 1760b57cec5SDimitry Andric case file_magic::macho_dynamic_linker: 1770b57cec5SDimitry Andric case file_magic::macho_bundle: 1780b57cec5SDimitry Andric case file_magic::macho_dynamically_linked_shared_lib_stub: 1790b57cec5SDimitry Andric case file_magic::macho_dsym_companion: 1800b57cec5SDimitry Andric case file_magic::macho_kext_bundle: 181bdd1243dSDimitry Andric case file_magic::macho_file_set: 1820b57cec5SDimitry Andric return createMachOObjectFile(Object); 1830b57cec5SDimitry Andric case file_magic::coff_object: 1840b57cec5SDimitry Andric case file_magic::coff_import_library: 1850b57cec5SDimitry Andric case file_magic::pecoff_executable: 1860b57cec5SDimitry Andric return createCOFFObjectFile(Object); 1870b57cec5SDimitry Andric case file_magic::xcoff_object_32: 1880b57cec5SDimitry Andric return createXCOFFObjectFile(Object, Binary::ID_XCOFF32); 1890b57cec5SDimitry Andric case file_magic::xcoff_object_64: 1900b57cec5SDimitry Andric return createXCOFFObjectFile(Object, Binary::ID_XCOFF64); 1910b57cec5SDimitry Andric case file_magic::wasm_object: 1920b57cec5SDimitry Andric return createWasmObjectFile(Object); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric llvm_unreachable("Unexpected Object File Type"); 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric Expected<OwningBinary<ObjectFile>> 1980b57cec5SDimitry Andric ObjectFile::createObjectFile(StringRef ObjectPath) { 1990b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 2000b57cec5SDimitry Andric MemoryBuffer::getFile(ObjectPath); 2010b57cec5SDimitry Andric if (std::error_code EC = FileOrErr.getError()) 2020b57cec5SDimitry Andric return errorCodeToError(EC); 2030b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get()); 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 2060b57cec5SDimitry Andric createObjectFile(Buffer->getMemBufferRef()); 2070b57cec5SDimitry Andric if (Error Err = ObjOrErr.takeError()) 2080b57cec5SDimitry Andric return std::move(Err); 2090b57cec5SDimitry Andric std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get()); 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer)); 2120b57cec5SDimitry Andric } 21381ad6265SDimitry Andric 21481ad6265SDimitry Andric bool ObjectFile::isReflectionSectionStrippable( 21581ad6265SDimitry Andric llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind) 21681ad6265SDimitry Andric const { 21781ad6265SDimitry Andric using llvm::binaryformat::Swift5ReflectionSectionKind; 21881ad6265SDimitry Andric return ReflectionSectionKind == Swift5ReflectionSectionKind::fieldmd || 21981ad6265SDimitry Andric ReflectionSectionKind == Swift5ReflectionSectionKind::reflstr || 22081ad6265SDimitry Andric ReflectionSectionKind == Swift5ReflectionSectionKind::assocty; 22181ad6265SDimitry Andric } 222