xref: /freebsd-src/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
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 
operator <<(raw_ostream & OS,const SectionedAddress & Addr)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 
anchor()410b57cec5SDimitry Andric void ObjectFile::anchor() {}
420b57cec5SDimitry Andric 
ObjectFile(unsigned int Type,MemoryBufferRef Source)430b57cec5SDimitry Andric ObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source)
440b57cec5SDimitry Andric     : SymbolicFile(Type, Source) {}
450b57cec5SDimitry Andric 
containsSymbol(SymbolRef S) const460b57cec5SDimitry 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 
getSymbolValue(DataRefImpl Ref) const565ffd83dbSDimitry 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 
printSymbolName(raw_ostream & OS,DataRefImpl Symb) const690b57cec5SDimitry 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 
getSymbolAlignment(DataRefImpl DRI) const770b57cec5SDimitry Andric uint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; }
780b57cec5SDimitry Andric 
isSectionBitcode(DataRefImpl Sec) const790b57cec5SDimitry Andric bool ObjectFile::isSectionBitcode(DataRefImpl Sec) const {
808bcb0991SDimitry Andric   Expected<StringRef> NameOrErr = getSectionName(Sec);
818bcb0991SDimitry Andric   if (NameOrErr)
825f757f3fSDimitry Andric     return *NameOrErr == ".llvm.lto";
838bcb0991SDimitry Andric   consumeError(NameOrErr.takeError());
840b57cec5SDimitry Andric   return false;
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
isSectionStripped(DataRefImpl Sec) const870b57cec5SDimitry Andric bool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; }
880b57cec5SDimitry Andric 
isBerkeleyText(DataRefImpl Sec) const890b57cec5SDimitry Andric bool ObjectFile::isBerkeleyText(DataRefImpl Sec) const {
900b57cec5SDimitry Andric   return isSectionText(Sec);
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric 
isBerkeleyData(DataRefImpl Sec) const930b57cec5SDimitry Andric bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const {
940b57cec5SDimitry Andric   return isSectionData(Sec);
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric 
isDebugSection(DataRefImpl Sec) const97fe6060f1SDimitry Andric bool ObjectFile::isDebugSection(DataRefImpl Sec) const { return false; }
985ffd83dbSDimitry Andric 
hasDebugInfo() const99bdd1243dSDimitry 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>
getRelocatedSection(DataRefImpl Sec) const1058bcb0991SDimitry Andric ObjectFile::getRelocatedSection(DataRefImpl Sec) const {
1060b57cec5SDimitry Andric   return section_iterator(SectionRef(Sec, this));
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
makeTriple() const1090b57cec5SDimitry Andric Triple ObjectFile::makeTriple() const {
1100b57cec5SDimitry Andric   Triple TheTriple;
1110b57cec5SDimitry Andric   auto Arch = getArch();
1120b57cec5SDimitry Andric   TheTriple.setArch(Triple::ArchType(Arch));
1130b57cec5SDimitry Andric 
1141db9f3b2SDimitry Andric   auto OS = getOS();
1151db9f3b2SDimitry Andric   if (OS != Triple::UnknownOS)
1161db9f3b2SDimitry Andric     TheTriple.setOS(OS);
1171db9f3b2SDimitry Andric 
1180b57cec5SDimitry Andric   // For ARM targets, try to use the build attributes to build determine
1190b57cec5SDimitry Andric   // the build target. Target features are also added, but later during
1200b57cec5SDimitry Andric   // disassembly.
1210b57cec5SDimitry Andric   if (Arch == Triple::arm || Arch == Triple::armeb)
1220b57cec5SDimitry Andric     setARMSubArch(TheTriple);
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   // TheTriple defaults to ELF, and COFF doesn't have an environment:
1255ffd83dbSDimitry Andric   // something we can do here is indicate that it is mach-o.
1265ffd83dbSDimitry Andric   if (isMachO()) {
1270b57cec5SDimitry Andric     TheTriple.setObjectFormat(Triple::MachO);
1285ffd83dbSDimitry Andric   } else if (isCOFF()) {
1298bcb0991SDimitry Andric     const auto COFFObj = cast<COFFObjectFile>(this);
1300b57cec5SDimitry Andric     if (COFFObj->getArch() == Triple::thumb)
1310b57cec5SDimitry Andric       TheTriple.setTriple("thumbv7-windows");
1325ffd83dbSDimitry Andric   } else if (isXCOFF()) {
1335ffd83dbSDimitry Andric     // XCOFF implies AIX.
1345ffd83dbSDimitry Andric     TheTriple.setOS(Triple::AIX);
1355ffd83dbSDimitry Andric     TheTriple.setObjectFormat(Triple::XCOFF);
1361db9f3b2SDimitry Andric   } else if (isGOFF()) {
13706c3fb27SDimitry Andric     TheTriple.setOS(Triple::ZOS);
13806c3fb27SDimitry Andric     TheTriple.setObjectFormat(Triple::GOFF);
1391db9f3b2SDimitry Andric   } else if (TheTriple.isAMDGPU()) {
1401db9f3b2SDimitry Andric     TheTriple.setVendor(Triple::AMD);
1411db9f3b2SDimitry Andric   } else if (TheTriple.isNVPTX()) {
1421db9f3b2SDimitry Andric     TheTriple.setVendor(Triple::NVIDIA);
14306c3fb27SDimitry Andric   }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   return TheTriple;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>>
createObjectFile(MemoryBufferRef Object,file_magic Type,bool InitContent)149e8d8bef9SDimitry Andric ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,
150e8d8bef9SDimitry Andric                              bool InitContent) {
1510b57cec5SDimitry Andric   StringRef Data = Object.getBuffer();
1520b57cec5SDimitry Andric   if (Type == file_magic::unknown)
1530b57cec5SDimitry Andric     Type = identify_magic(Data);
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   switch (Type) {
1560b57cec5SDimitry Andric   case file_magic::unknown:
1570b57cec5SDimitry Andric   case file_magic::bitcode:
158*7a6dacacSDimitry Andric   case file_magic::clang_ast:
1590b57cec5SDimitry Andric   case file_magic::coff_cl_gl_object:
1600b57cec5SDimitry Andric   case file_magic::archive:
1610b57cec5SDimitry Andric   case file_magic::macho_universal_binary:
1620b57cec5SDimitry Andric   case file_magic::windows_resource:
1630b57cec5SDimitry Andric   case file_magic::pdb:
1640b57cec5SDimitry Andric   case file_magic::minidump:
165fe6060f1SDimitry Andric   case file_magic::goff_object:
16681ad6265SDimitry Andric   case file_magic::cuda_fatbinary:
16781ad6265SDimitry Andric   case file_magic::offload_binary:
16881ad6265SDimitry Andric   case file_magic::dxcontainer_object:
1695f757f3fSDimitry Andric   case file_magic::offload_bundle:
1705f757f3fSDimitry Andric   case file_magic::offload_bundle_compressed:
1715f757f3fSDimitry Andric   case file_magic::spirv_object:
1720b57cec5SDimitry Andric     return errorCodeToError(object_error::invalid_file_type);
1738bcb0991SDimitry Andric   case file_magic::tapi_file:
1748bcb0991SDimitry Andric     return errorCodeToError(object_error::invalid_file_type);
1750b57cec5SDimitry Andric   case file_magic::elf:
1760b57cec5SDimitry Andric   case file_magic::elf_relocatable:
1770b57cec5SDimitry Andric   case file_magic::elf_executable:
1780b57cec5SDimitry Andric   case file_magic::elf_shared_object:
1790b57cec5SDimitry Andric   case file_magic::elf_core:
180e8d8bef9SDimitry Andric     return createELFObjectFile(Object, InitContent);
1810b57cec5SDimitry Andric   case file_magic::macho_object:
1820b57cec5SDimitry Andric   case file_magic::macho_executable:
1830b57cec5SDimitry Andric   case file_magic::macho_fixed_virtual_memory_shared_lib:
1840b57cec5SDimitry Andric   case file_magic::macho_core:
1850b57cec5SDimitry Andric   case file_magic::macho_preload_executable:
1860b57cec5SDimitry Andric   case file_magic::macho_dynamically_linked_shared_lib:
1870b57cec5SDimitry Andric   case file_magic::macho_dynamic_linker:
1880b57cec5SDimitry Andric   case file_magic::macho_bundle:
1890b57cec5SDimitry Andric   case file_magic::macho_dynamically_linked_shared_lib_stub:
1900b57cec5SDimitry Andric   case file_magic::macho_dsym_companion:
1910b57cec5SDimitry Andric   case file_magic::macho_kext_bundle:
192bdd1243dSDimitry Andric   case file_magic::macho_file_set:
1930b57cec5SDimitry Andric     return createMachOObjectFile(Object);
1940b57cec5SDimitry Andric   case file_magic::coff_object:
1950b57cec5SDimitry Andric   case file_magic::coff_import_library:
1960b57cec5SDimitry Andric   case file_magic::pecoff_executable:
1970b57cec5SDimitry Andric     return createCOFFObjectFile(Object);
1980b57cec5SDimitry Andric   case file_magic::xcoff_object_32:
1990b57cec5SDimitry Andric     return createXCOFFObjectFile(Object, Binary::ID_XCOFF32);
2000b57cec5SDimitry Andric   case file_magic::xcoff_object_64:
2010b57cec5SDimitry Andric     return createXCOFFObjectFile(Object, Binary::ID_XCOFF64);
2020b57cec5SDimitry Andric   case file_magic::wasm_object:
2030b57cec5SDimitry Andric     return createWasmObjectFile(Object);
2040b57cec5SDimitry Andric   }
2050b57cec5SDimitry Andric   llvm_unreachable("Unexpected Object File Type");
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric Expected<OwningBinary<ObjectFile>>
createObjectFile(StringRef ObjectPath)2090b57cec5SDimitry Andric ObjectFile::createObjectFile(StringRef ObjectPath) {
2100b57cec5SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
2110b57cec5SDimitry Andric       MemoryBuffer::getFile(ObjectPath);
2120b57cec5SDimitry Andric   if (std::error_code EC = FileOrErr.getError())
2130b57cec5SDimitry Andric     return errorCodeToError(EC);
2140b57cec5SDimitry Andric   std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get());
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
2170b57cec5SDimitry Andric       createObjectFile(Buffer->getMemBufferRef());
2180b57cec5SDimitry Andric   if (Error Err = ObjOrErr.takeError())
2190b57cec5SDimitry Andric     return std::move(Err);
2200b57cec5SDimitry Andric   std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer));
2230b57cec5SDimitry Andric }
22481ad6265SDimitry Andric 
isReflectionSectionStrippable(llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind) const22581ad6265SDimitry Andric bool ObjectFile::isReflectionSectionStrippable(
22681ad6265SDimitry Andric     llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind)
22781ad6265SDimitry Andric     const {
22881ad6265SDimitry Andric   using llvm::binaryformat::Swift5ReflectionSectionKind;
22981ad6265SDimitry Andric   return ReflectionSectionKind == Swift5ReflectionSectionKind::fieldmd ||
23081ad6265SDimitry Andric          ReflectionSectionKind == Swift5ReflectionSectionKind::reflstr ||
23181ad6265SDimitry Andric          ReflectionSectionKind == Swift5ReflectionSectionKind::assocty;
23281ad6265SDimitry Andric }
233