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"
240b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
250b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
260b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
270b57cec5SDimitry Andric #include <algorithm>
280b57cec5SDimitry Andric #include <cstdint>
290b57cec5SDimitry Andric #include <memory>
300b57cec5SDimitry Andric #include <system_error>
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric using namespace llvm;
330b57cec5SDimitry Andric using namespace object;
340b57cec5SDimitry Andric 
operator <<(raw_ostream & OS,const SectionedAddress & Addr)35480093f4SDimitry Andric raw_ostream &object::operator<<(raw_ostream &OS, const SectionedAddress &Addr) {
36480093f4SDimitry Andric   OS << "SectionedAddress{" << format_hex(Addr.Address, 10);
37480093f4SDimitry Andric   if (Addr.SectionIndex != SectionedAddress::UndefSection)
38480093f4SDimitry Andric     OS << ", " << Addr.SectionIndex;
39480093f4SDimitry Andric   return OS << "}";
40480093f4SDimitry Andric }
41480093f4SDimitry Andric 
anchor()420b57cec5SDimitry Andric void ObjectFile::anchor() {}
430b57cec5SDimitry Andric 
ObjectFile(unsigned int Type,MemoryBufferRef Source)440b57cec5SDimitry Andric ObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source)
450b57cec5SDimitry Andric     : SymbolicFile(Type, Source) {}
460b57cec5SDimitry Andric 
containsSymbol(SymbolRef S) const470b57cec5SDimitry Andric bool SectionRef::containsSymbol(SymbolRef S) const {
480b57cec5SDimitry Andric   Expected<section_iterator> SymSec = S.getSection();
490b57cec5SDimitry Andric   if (!SymSec) {
500b57cec5SDimitry Andric     // TODO: Actually report errors helpfully.
510b57cec5SDimitry Andric     consumeError(SymSec.takeError());
520b57cec5SDimitry Andric     return false;
530b57cec5SDimitry Andric   }
540b57cec5SDimitry Andric   return *this == **SymSec;
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric 
getSymbolValue(DataRefImpl Ref) const575ffd83dbSDimitry Andric Expected<uint64_t> ObjectFile::getSymbolValue(DataRefImpl Ref) const {
585ffd83dbSDimitry Andric   if (Expected<uint32_t> FlagsOrErr = getSymbolFlags(Ref)) {
595ffd83dbSDimitry Andric     if (*FlagsOrErr & SymbolRef::SF_Undefined)
600b57cec5SDimitry Andric       return 0;
615ffd83dbSDimitry Andric     if (*FlagsOrErr & SymbolRef::SF_Common)
620b57cec5SDimitry Andric       return getCommonSymbolSize(Ref);
635ffd83dbSDimitry Andric   } else
645ffd83dbSDimitry Andric     // TODO: Test this error.
655ffd83dbSDimitry Andric     return FlagsOrErr.takeError();
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)
820b57cec5SDimitry Andric     return *NameOrErr == ".llvmbc";
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) const97*5f7ddb14SDimitry Andric bool ObjectFile::isDebugSection(DataRefImpl Sec) const { return false; }
985ffd83dbSDimitry Andric 
998bcb0991SDimitry Andric Expected<section_iterator>
getRelocatedSection(DataRefImpl Sec) const1008bcb0991SDimitry Andric ObjectFile::getRelocatedSection(DataRefImpl Sec) const {
1010b57cec5SDimitry Andric   return section_iterator(SectionRef(Sec, this));
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
makeTriple() const1040b57cec5SDimitry Andric Triple ObjectFile::makeTriple() const {
1050b57cec5SDimitry Andric   Triple TheTriple;
1060b57cec5SDimitry Andric   auto Arch = getArch();
1070b57cec5SDimitry Andric   TheTriple.setArch(Triple::ArchType(Arch));
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   // For ARM targets, try to use the build attributes to build determine
1100b57cec5SDimitry Andric   // the build target. Target features are also added, but later during
1110b57cec5SDimitry Andric   // disassembly.
1120b57cec5SDimitry Andric   if (Arch == Triple::arm || Arch == Triple::armeb)
1130b57cec5SDimitry Andric     setARMSubArch(TheTriple);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   // TheTriple defaults to ELF, and COFF doesn't have an environment:
1165ffd83dbSDimitry Andric   // something we can do here is indicate that it is mach-o.
1175ffd83dbSDimitry Andric   if (isMachO()) {
1180b57cec5SDimitry Andric     TheTriple.setObjectFormat(Triple::MachO);
1195ffd83dbSDimitry Andric   } else if (isCOFF()) {
1208bcb0991SDimitry Andric     const auto COFFObj = cast<COFFObjectFile>(this);
1210b57cec5SDimitry Andric     if (COFFObj->getArch() == Triple::thumb)
1220b57cec5SDimitry Andric       TheTriple.setTriple("thumbv7-windows");
1235ffd83dbSDimitry Andric   } else if (isXCOFF()) {
1245ffd83dbSDimitry Andric     // XCOFF implies AIX.
1255ffd83dbSDimitry Andric     TheTriple.setOS(Triple::AIX);
1265ffd83dbSDimitry Andric     TheTriple.setObjectFormat(Triple::XCOFF);
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   return TheTriple;
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>>
createObjectFile(MemoryBufferRef Object,file_magic Type,bool InitContent)133af732203SDimitry Andric ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,
134af732203SDimitry Andric                              bool InitContent) {
1350b57cec5SDimitry Andric   StringRef Data = Object.getBuffer();
1360b57cec5SDimitry Andric   if (Type == file_magic::unknown)
1370b57cec5SDimitry Andric     Type = identify_magic(Data);
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   switch (Type) {
1400b57cec5SDimitry Andric   case file_magic::unknown:
1410b57cec5SDimitry Andric   case file_magic::bitcode:
1420b57cec5SDimitry Andric   case file_magic::coff_cl_gl_object:
1430b57cec5SDimitry Andric   case file_magic::archive:
1440b57cec5SDimitry Andric   case file_magic::macho_universal_binary:
1450b57cec5SDimitry Andric   case file_magic::windows_resource:
1460b57cec5SDimitry Andric   case file_magic::pdb:
1470b57cec5SDimitry Andric   case file_magic::minidump:
148*5f7ddb14SDimitry Andric   case file_magic::goff_object:
1490b57cec5SDimitry Andric     return errorCodeToError(object_error::invalid_file_type);
1508bcb0991SDimitry Andric   case file_magic::tapi_file:
1518bcb0991SDimitry Andric     return errorCodeToError(object_error::invalid_file_type);
1520b57cec5SDimitry Andric   case file_magic::elf:
1530b57cec5SDimitry Andric   case file_magic::elf_relocatable:
1540b57cec5SDimitry Andric   case file_magic::elf_executable:
1550b57cec5SDimitry Andric   case file_magic::elf_shared_object:
1560b57cec5SDimitry Andric   case file_magic::elf_core:
157af732203SDimitry Andric     return createELFObjectFile(Object, InitContent);
1580b57cec5SDimitry Andric   case file_magic::macho_object:
1590b57cec5SDimitry Andric   case file_magic::macho_executable:
1600b57cec5SDimitry Andric   case file_magic::macho_fixed_virtual_memory_shared_lib:
1610b57cec5SDimitry Andric   case file_magic::macho_core:
1620b57cec5SDimitry Andric   case file_magic::macho_preload_executable:
1630b57cec5SDimitry Andric   case file_magic::macho_dynamically_linked_shared_lib:
1640b57cec5SDimitry Andric   case file_magic::macho_dynamic_linker:
1650b57cec5SDimitry Andric   case file_magic::macho_bundle:
1660b57cec5SDimitry Andric   case file_magic::macho_dynamically_linked_shared_lib_stub:
1670b57cec5SDimitry Andric   case file_magic::macho_dsym_companion:
1680b57cec5SDimitry Andric   case file_magic::macho_kext_bundle:
1690b57cec5SDimitry Andric     return createMachOObjectFile(Object);
1700b57cec5SDimitry Andric   case file_magic::coff_object:
1710b57cec5SDimitry Andric   case file_magic::coff_import_library:
1720b57cec5SDimitry Andric   case file_magic::pecoff_executable:
1730b57cec5SDimitry Andric     return createCOFFObjectFile(Object);
1740b57cec5SDimitry Andric   case file_magic::xcoff_object_32:
1750b57cec5SDimitry Andric     return createXCOFFObjectFile(Object, Binary::ID_XCOFF32);
1760b57cec5SDimitry Andric   case file_magic::xcoff_object_64:
1770b57cec5SDimitry Andric     return createXCOFFObjectFile(Object, Binary::ID_XCOFF64);
1780b57cec5SDimitry Andric   case file_magic::wasm_object:
1790b57cec5SDimitry Andric     return createWasmObjectFile(Object);
1800b57cec5SDimitry Andric   }
1810b57cec5SDimitry Andric   llvm_unreachable("Unexpected Object File Type");
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric Expected<OwningBinary<ObjectFile>>
createObjectFile(StringRef ObjectPath)1850b57cec5SDimitry Andric ObjectFile::createObjectFile(StringRef ObjectPath) {
1860b57cec5SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
1870b57cec5SDimitry Andric       MemoryBuffer::getFile(ObjectPath);
1880b57cec5SDimitry Andric   if (std::error_code EC = FileOrErr.getError())
1890b57cec5SDimitry Andric     return errorCodeToError(EC);
1900b57cec5SDimitry Andric   std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get());
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
1930b57cec5SDimitry Andric       createObjectFile(Buffer->getMemBufferRef());
1940b57cec5SDimitry Andric   if (Error Err = ObjOrErr.takeError())
1950b57cec5SDimitry Andric     return std::move(Err);
1960b57cec5SDimitry Andric   std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer));
1990b57cec5SDimitry Andric }
200