1321369Sdim//===- ObjectFile.cpp - File format independent object file ---------------===// 2218885Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6218885Sdim// 7218885Sdim//===----------------------------------------------------------------------===// 8218885Sdim// 9218885Sdim// This file defines a file format independent ObjectFile class. 10218885Sdim// 11218885Sdim//===----------------------------------------------------------------------===// 12218885Sdim 13314564Sdim#include "llvm/Object/ObjectFile.h" 14321369Sdim#include "llvm/ADT/StringRef.h" 15321369Sdim#include "llvm/BinaryFormat/Magic.h" 16321369Sdim#include "llvm/Object/Binary.h" 17280031Sdim#include "llvm/Object/COFF.h" 18321369Sdim#include "llvm/Object/Error.h" 19280031Sdim#include "llvm/Object/MachO.h" 20314564Sdim#include "llvm/Object/Wasm.h" 21321369Sdim#include "llvm/Support/Error.h" 22218885Sdim#include "llvm/Support/ErrorHandling.h" 23321369Sdim#include "llvm/Support/ErrorOr.h" 24261991Sdim#include "llvm/Support/FileSystem.h" 25218885Sdim#include "llvm/Support/MemoryBuffer.h" 26276479Sdim#include "llvm/Support/raw_ostream.h" 27321369Sdim#include <algorithm> 28321369Sdim#include <cstdint> 29321369Sdim#include <memory> 30276479Sdim#include <system_error> 31218885Sdim 32218885Sdimusing namespace llvm; 33218885Sdimusing namespace object; 34218885Sdim 35360784Sdimraw_ostream &object::operator<<(raw_ostream &OS, const SectionedAddress &Addr) { 36360784Sdim OS << "SectionedAddress{" << format_hex(Addr.Address, 10); 37360784Sdim if (Addr.SectionIndex != SectionedAddress::UndefSection) 38360784Sdim OS << ", " << Addr.SectionIndex; 39360784Sdim return OS << "}"; 40360784Sdim} 41360784Sdim 42321369Sdimvoid ObjectFile::anchor() {} 43234353Sdim 44280031SdimObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source) 45280031Sdim : SymbolicFile(Type, Source) {} 46276479Sdim 47288943Sdimbool SectionRef::containsSymbol(SymbolRef S) const { 48309124Sdim Expected<section_iterator> SymSec = S.getSection(); 49309124Sdim if (!SymSec) { 50309124Sdim // TODO: Actually report errors helpfully. 51309124Sdim consumeError(SymSec.takeError()); 52288943Sdim return false; 53309124Sdim } 54296417Sdim return *this == **SymSec; 55288943Sdim} 56288943Sdim 57288943Sdimuint64_t ObjectFile::getSymbolValue(DataRefImpl Ref) const { 58288943Sdim uint32_t Flags = getSymbolFlags(Ref); 59288943Sdim if (Flags & SymbolRef::SF_Undefined) 60288943Sdim return 0; 61288943Sdim if (Flags & SymbolRef::SF_Common) 62288943Sdim return getCommonSymbolSize(Ref); 63288943Sdim return getSymbolValueImpl(Ref); 64288943Sdim} 65288943Sdim 66353358SdimError ObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const { 67309124Sdim Expected<StringRef> Name = getSymbolName(Symb); 68309124Sdim if (!Name) 69353358Sdim return Name.takeError(); 70288943Sdim OS << *Name; 71353358Sdim return Error::success(); 72218885Sdim} 73218885Sdim 74288943Sdimuint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; } 75251662Sdim 76309124Sdimbool ObjectFile::isSectionBitcode(DataRefImpl Sec) const { 77360784Sdim Expected<StringRef> NameOrErr = getSectionName(Sec); 78360784Sdim if (NameOrErr) 79353358Sdim return *NameOrErr == ".llvmbc"; 80360784Sdim consumeError(NameOrErr.takeError()); 81309124Sdim return false; 82309124Sdim} 83309124Sdim 84327952Sdimbool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; } 85327952Sdim 86344779Sdimbool ObjectFile::isBerkeleyText(DataRefImpl Sec) const { 87344779Sdim return isSectionText(Sec); 88344779Sdim} 89344779Sdim 90344779Sdimbool ObjectFile::isBerkeleyData(DataRefImpl Sec) const { 91344779Sdim return isSectionData(Sec); 92344779Sdim} 93344779Sdim 94360784SdimExpected<section_iterator> 95360784SdimObjectFile::getRelocatedSection(DataRefImpl Sec) const { 96261991Sdim return section_iterator(SectionRef(Sec, this)); 97261991Sdim} 98261991Sdim 99327952SdimTriple ObjectFile::makeTriple() const { 100327952Sdim Triple TheTriple; 101327952Sdim auto Arch = getArch(); 102327952Sdim TheTriple.setArch(Triple::ArchType(Arch)); 103327952Sdim 104327952Sdim // For ARM targets, try to use the build attributes to build determine 105327952Sdim // the build target. Target features are also added, but later during 106327952Sdim // disassembly. 107327952Sdim if (Arch == Triple::arm || Arch == Triple::armeb) 108327952Sdim setARMSubArch(TheTriple); 109327952Sdim 110327952Sdim // TheTriple defaults to ELF, and COFF doesn't have an environment: 111327952Sdim // the best we can do here is indicate that it is mach-o. 112327952Sdim if (isMachO()) 113327952Sdim TheTriple.setObjectFormat(Triple::MachO); 114327952Sdim 115327952Sdim if (isCOFF()) { 116360784Sdim const auto COFFObj = cast<COFFObjectFile>(this); 117327952Sdim if (COFFObj->getArch() == Triple::thumb) 118327952Sdim TheTriple.setTriple("thumbv7-windows"); 119327952Sdim } 120327952Sdim 121327952Sdim return TheTriple; 122327952Sdim} 123327952Sdim 124309124SdimExpected<std::unique_ptr<ObjectFile>> 125321369SdimObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) { 126280031Sdim StringRef Data = Object.getBuffer(); 127321369Sdim if (Type == file_magic::unknown) 128321369Sdim Type = identify_magic(Data); 129261991Sdim 130261991Sdim switch (Type) { 131321369Sdim case file_magic::unknown: 132321369Sdim case file_magic::bitcode: 133321369Sdim case file_magic::coff_cl_gl_object: 134321369Sdim case file_magic::archive: 135321369Sdim case file_magic::macho_universal_binary: 136321369Sdim case file_magic::windows_resource: 137341825Sdim case file_magic::pdb: 138353358Sdim case file_magic::minidump: 139309124Sdim return errorCodeToError(object_error::invalid_file_type); 140360784Sdim case file_magic::tapi_file: 141360784Sdim return errorCodeToError(object_error::invalid_file_type); 142321369Sdim case file_magic::elf: 143321369Sdim case file_magic::elf_relocatable: 144321369Sdim case file_magic::elf_executable: 145321369Sdim case file_magic::elf_shared_object: 146321369Sdim case file_magic::elf_core: 147327952Sdim return createELFObjectFile(Object); 148321369Sdim case file_magic::macho_object: 149321369Sdim case file_magic::macho_executable: 150321369Sdim case file_magic::macho_fixed_virtual_memory_shared_lib: 151321369Sdim case file_magic::macho_core: 152321369Sdim case file_magic::macho_preload_executable: 153321369Sdim case file_magic::macho_dynamically_linked_shared_lib: 154321369Sdim case file_magic::macho_dynamic_linker: 155321369Sdim case file_magic::macho_bundle: 156321369Sdim case file_magic::macho_dynamically_linked_shared_lib_stub: 157321369Sdim case file_magic::macho_dsym_companion: 158321369Sdim case file_magic::macho_kext_bundle: 159261991Sdim return createMachOObjectFile(Object); 160321369Sdim case file_magic::coff_object: 161321369Sdim case file_magic::coff_import_library: 162321369Sdim case file_magic::pecoff_executable: 163327952Sdim return createCOFFObjectFile(Object); 164353358Sdim case file_magic::xcoff_object_32: 165353358Sdim return createXCOFFObjectFile(Object, Binary::ID_XCOFF32); 166353358Sdim case file_magic::xcoff_object_64: 167353358Sdim return createXCOFFObjectFile(Object, Binary::ID_XCOFF64); 168321369Sdim case file_magic::wasm_object: 169314564Sdim return createWasmObjectFile(Object); 170261991Sdim } 171261991Sdim llvm_unreachable("Unexpected Object File Type"); 172218885Sdim} 173218885Sdim 174309124SdimExpected<OwningBinary<ObjectFile>> 175280031SdimObjectFile::createObjectFile(StringRef ObjectPath) { 176276479Sdim ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 177276479Sdim MemoryBuffer::getFile(ObjectPath); 178276479Sdim if (std::error_code EC = FileOrErr.getError()) 179309124Sdim return errorCodeToError(EC); 180280031Sdim std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get()); 181280031Sdim 182309124Sdim Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 183280031Sdim createObjectFile(Buffer->getMemBufferRef()); 184314564Sdim if (Error Err = ObjOrErr.takeError()) 185314564Sdim return std::move(Err); 186280031Sdim std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get()); 187280031Sdim 188280031Sdim return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer)); 189218885Sdim} 190