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