235 lines · cpp
1//===- ObjectFile.cpp - File format independent object file ---------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines a file format independent ObjectFile class.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/Object/ObjectFile.h"14#include "llvm/ADT/StringRef.h"15#include "llvm/BinaryFormat/Magic.h"16#include "llvm/Object/Binary.h"17#include "llvm/Object/COFF.h"18#include "llvm/Object/DXContainer.h"19#include "llvm/Object/Error.h"20#include "llvm/Object/MachO.h"21#include "llvm/Object/Wasm.h"22#include "llvm/Support/Error.h"23#include "llvm/Support/ErrorHandling.h"24#include "llvm/Support/ErrorOr.h"25#include "llvm/Support/Format.h"26#include "llvm/Support/MemoryBuffer.h"27#include "llvm/Support/raw_ostream.h"28#include <cstdint>29#include <memory>30#include <system_error>31 32using namespace llvm;33using namespace object;34 35raw_ostream &object::operator<<(raw_ostream &OS, const SectionedAddress &Addr) {36 OS << "SectionedAddress{" << format_hex(Addr.Address, 10);37 if (Addr.SectionIndex != SectionedAddress::UndefSection)38 OS << ", " << Addr.SectionIndex;39 return OS << "}";40}41 42void ObjectFile::anchor() {}43 44ObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source)45 : SymbolicFile(Type, Source) {}46 47bool SectionRef::containsSymbol(SymbolRef S) const {48 Expected<section_iterator> SymSec = S.getSection();49 if (!SymSec) {50 // TODO: Actually report errors helpfully.51 consumeError(SymSec.takeError());52 return false;53 }54 return *this == **SymSec;55}56 57Expected<uint64_t> ObjectFile::getSymbolValue(DataRefImpl Ref) const {58 uint32_t Flags;59 if (Error E = getSymbolFlags(Ref).moveInto(Flags))60 // TODO: Test this error.61 return std::move(E);62 63 if (Flags & SymbolRef::SF_Undefined)64 return 0;65 if (Flags & SymbolRef::SF_Common)66 return getCommonSymbolSize(Ref);67 return getSymbolValueImpl(Ref);68}69 70Error ObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const {71 Expected<StringRef> Name = getSymbolName(Symb);72 if (!Name)73 return Name.takeError();74 OS << *Name;75 return Error::success();76}77 78uint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; }79 80bool ObjectFile::isSectionBitcode(DataRefImpl Sec) const {81 Expected<StringRef> NameOrErr = getSectionName(Sec);82 if (NameOrErr)83 return *NameOrErr == ".llvm.lto";84 consumeError(NameOrErr.takeError());85 return false;86}87 88bool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; }89 90bool ObjectFile::isBerkeleyText(DataRefImpl Sec) const {91 return isSectionText(Sec);92}93 94bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const {95 return isSectionData(Sec);96}97 98bool ObjectFile::isDebugSection(DataRefImpl Sec) const { return false; }99 100bool ObjectFile::hasDebugInfo() const {101 return any_of(sections(),102 [](SectionRef Sec) { return Sec.isDebugSection(); });103}104 105Expected<section_iterator>106ObjectFile::getRelocatedSection(DataRefImpl Sec) const {107 return section_iterator(SectionRef(Sec, this));108}109 110Triple ObjectFile::makeTriple() const {111 Triple TheTriple;112 auto Arch = getArch();113 TheTriple.setArch(Triple::ArchType(Arch));114 115 auto OS = getOS();116 if (OS != Triple::UnknownOS)117 TheTriple.setOS(OS);118 119 // For ARM targets, try to use the build attributes to build determine120 // the build target. Target features are also added, but later during121 // disassembly.122 if (Arch == Triple::arm || Arch == Triple::armeb)123 setARMSubArch(TheTriple);124 125 // TheTriple defaults to ELF, and COFF doesn't have an environment:126 // something we can do here is indicate that it is mach-o.127 if (isMachO()) {128 TheTriple.setObjectFormat(Triple::MachO);129 } else if (isCOFF()) {130 const auto COFFObj = cast<COFFObjectFile>(this);131 if (COFFObj->getArch() == Triple::thumb)132 TheTriple.setTriple("thumbv7-windows");133 } else if (isXCOFF()) {134 // XCOFF implies AIX.135 TheTriple.setOS(Triple::AIX);136 TheTriple.setObjectFormat(Triple::XCOFF);137 } else if (isGOFF()) {138 TheTriple.setOS(Triple::ZOS);139 TheTriple.setObjectFormat(Triple::GOFF);140 } else if (TheTriple.isAMDGPU()) {141 TheTriple.setVendor(Triple::AMD);142 } else if (TheTriple.isNVPTX()) {143 TheTriple.setVendor(Triple::NVIDIA);144 }145 146 return TheTriple;147}148 149Expected<std::unique_ptr<ObjectFile>>150ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,151 bool InitContent) {152 StringRef Data = Object.getBuffer();153 if (Type == file_magic::unknown)154 Type = identify_magic(Data);155 156 switch (Type) {157 case file_magic::unknown:158 case file_magic::bitcode:159 case file_magic::clang_ast:160 case file_magic::coff_cl_gl_object:161 case file_magic::archive:162 case file_magic::macho_universal_binary:163 case file_magic::windows_resource:164 case file_magic::pdb:165 case file_magic::minidump:166 case file_magic::goff_object:167 case file_magic::cuda_fatbinary:168 case file_magic::offload_binary:169 case file_magic::offload_bundle:170 case file_magic::offload_bundle_compressed:171 case file_magic::spirv_object:172 return errorCodeToError(object_error::invalid_file_type);173 case file_magic::tapi_file:174 return errorCodeToError(object_error::invalid_file_type);175 case file_magic::elf:176 case file_magic::elf_relocatable:177 case file_magic::elf_executable:178 case file_magic::elf_shared_object:179 case file_magic::elf_core:180 return createELFObjectFile(Object, InitContent);181 case file_magic::macho_object:182 case file_magic::macho_executable:183 case file_magic::macho_fixed_virtual_memory_shared_lib:184 case file_magic::macho_core:185 case file_magic::macho_preload_executable:186 case file_magic::macho_dynamically_linked_shared_lib:187 case file_magic::macho_dynamic_linker:188 case file_magic::macho_bundle:189 case file_magic::macho_dynamically_linked_shared_lib_stub:190 case file_magic::macho_dsym_companion:191 case file_magic::macho_kext_bundle:192 case file_magic::macho_file_set:193 return createMachOObjectFile(Object);194 case file_magic::coff_object:195 case file_magic::coff_import_library:196 case file_magic::pecoff_executable:197 return createCOFFObjectFile(Object);198 case file_magic::xcoff_object_32:199 return createXCOFFObjectFile(Object, Binary::ID_XCOFF32);200 case file_magic::xcoff_object_64:201 return createXCOFFObjectFile(Object, Binary::ID_XCOFF64);202 case file_magic::wasm_object:203 return createWasmObjectFile(Object);204 case file_magic::dxcontainer_object:205 return createDXContainerObjectFile(Object);206 }207 llvm_unreachable("Unexpected Object File Type");208}209 210Expected<OwningBinary<ObjectFile>>211ObjectFile::createObjectFile(StringRef ObjectPath) {212 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =213 MemoryBuffer::getFile(ObjectPath);214 if (std::error_code EC = FileOrErr.getError())215 return errorCodeToError(EC);216 std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get());217 218 Expected<std::unique_ptr<ObjectFile>> ObjOrErr =219 createObjectFile(Buffer->getMemBufferRef());220 if (Error Err = ObjOrErr.takeError())221 return std::move(Err);222 std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());223 224 return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer));225}226 227bool ObjectFile::isReflectionSectionStrippable(228 llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind)229 const {230 using llvm::binaryformat::Swift5ReflectionSectionKind;231 return ReflectionSectionKind == Swift5ReflectionSectionKind::fieldmd ||232 ReflectionSectionKind == Swift5ReflectionSectionKind::reflstr ||233 ReflectionSectionKind == Swift5ReflectionSectionKind::assocty;234}235