16bc11b14SDimitry Andric //===- ObjectFile.cpp - File format independent object file ---------------===//
22754fe60SDimitry Andric //
32754fe60SDimitry Andric //                     The LLVM Compiler Infrastructure
42754fe60SDimitry Andric //
52754fe60SDimitry Andric // This file is distributed under the University of Illinois Open Source
62754fe60SDimitry Andric // License. See LICENSE.TXT for details.
72754fe60SDimitry Andric //
82754fe60SDimitry Andric //===----------------------------------------------------------------------===//
92754fe60SDimitry Andric //
102754fe60SDimitry Andric // This file defines a file format independent ObjectFile class.
112754fe60SDimitry Andric //
122754fe60SDimitry Andric //===----------------------------------------------------------------------===//
132754fe60SDimitry Andric 
14db17bf38SDimitry Andric #include "llvm/Object/ObjectFile.h"
156bc11b14SDimitry Andric #include "llvm/ADT/StringRef.h"
16db17bf38SDimitry Andric #include "llvm/BinaryFormat/Magic.h"
176bc11b14SDimitry Andric #include "llvm/Object/Binary.h"
1839d628a0SDimitry Andric #include "llvm/Object/COFF.h"
196bc11b14SDimitry Andric #include "llvm/Object/Error.h"
2039d628a0SDimitry Andric #include "llvm/Object/MachO.h"
21d88c1a5aSDimitry Andric #include "llvm/Object/Wasm.h"
226bc11b14SDimitry Andric #include "llvm/Support/Error.h"
232754fe60SDimitry Andric #include "llvm/Support/ErrorHandling.h"
246bc11b14SDimitry Andric #include "llvm/Support/ErrorOr.h"
25f785676fSDimitry Andric #include "llvm/Support/FileSystem.h"
262754fe60SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
2791bc56edSDimitry Andric #include "llvm/Support/raw_ostream.h"
286bc11b14SDimitry Andric #include <algorithm>
296bc11b14SDimitry Andric #include <cstdint>
306bc11b14SDimitry Andric #include <memory>
3191bc56edSDimitry Andric #include <system_error>
322754fe60SDimitry Andric 
332754fe60SDimitry Andric using namespace llvm;
342754fe60SDimitry Andric using namespace object;
352754fe60SDimitry Andric 
anchor()36dff0c46cSDimitry Andric void ObjectFile::anchor() {}
37dff0c46cSDimitry Andric 
ObjectFile(unsigned int Type,MemoryBufferRef Source)3839d628a0SDimitry Andric ObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source)
3939d628a0SDimitry Andric     : SymbolicFile(Type, Source) {}
4091bc56edSDimitry Andric 
containsSymbol(SymbolRef S) const413dac3a9bSDimitry Andric bool SectionRef::containsSymbol(SymbolRef S) const {
423ca95b02SDimitry Andric   Expected<section_iterator> SymSec = S.getSection();
433ca95b02SDimitry Andric   if (!SymSec) {
443ca95b02SDimitry Andric     // TODO: Actually report errors helpfully.
453ca95b02SDimitry Andric     consumeError(SymSec.takeError());
463dac3a9bSDimitry Andric     return false;
473ca95b02SDimitry Andric   }
487d523365SDimitry Andric   return *this == **SymSec;
493dac3a9bSDimitry Andric }
503dac3a9bSDimitry Andric 
getSymbolValue(DataRefImpl Ref) const51875ed548SDimitry Andric uint64_t ObjectFile::getSymbolValue(DataRefImpl Ref) const {
52875ed548SDimitry Andric   uint32_t Flags = getSymbolFlags(Ref);
53875ed548SDimitry Andric   if (Flags & SymbolRef::SF_Undefined)
54875ed548SDimitry Andric     return 0;
55875ed548SDimitry Andric   if (Flags & SymbolRef::SF_Common)
56875ed548SDimitry Andric     return getCommonSymbolSize(Ref);
57875ed548SDimitry Andric   return getSymbolValueImpl(Ref);
58875ed548SDimitry Andric }
59875ed548SDimitry Andric 
printSymbolName(raw_ostream & OS,DataRefImpl Symb) const6091bc56edSDimitry Andric std::error_code ObjectFile::printSymbolName(raw_ostream &OS,
6191bc56edSDimitry Andric                                             DataRefImpl Symb) const {
623ca95b02SDimitry Andric   Expected<StringRef> Name = getSymbolName(Symb);
633ca95b02SDimitry Andric   if (!Name)
643ca95b02SDimitry Andric     return errorToErrorCode(Name.takeError());
653dac3a9bSDimitry Andric   OS << *Name;
6697bc6c73SDimitry Andric   return std::error_code();
672754fe60SDimitry Andric }
682754fe60SDimitry Andric 
getSymbolAlignment(DataRefImpl DRI) const6997bc6c73SDimitry Andric uint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; }
70284c1978SDimitry Andric 
isSectionBitcode(DataRefImpl Sec) const713ca95b02SDimitry Andric bool ObjectFile::isSectionBitcode(DataRefImpl Sec) const {
723ca95b02SDimitry Andric   StringRef SectName;
733ca95b02SDimitry Andric   if (!getSectionName(Sec, SectName))
743ca95b02SDimitry Andric     return SectName == ".llvmbc";
753ca95b02SDimitry Andric   return false;
763ca95b02SDimitry Andric }
773ca95b02SDimitry Andric 
isSectionStripped(DataRefImpl Sec) const782cab237bSDimitry Andric bool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; }
792cab237bSDimitry Andric 
isBerkeleyText(DataRefImpl Sec) const80*b5893f02SDimitry Andric bool ObjectFile::isBerkeleyText(DataRefImpl Sec) const {
81*b5893f02SDimitry Andric   return isSectionText(Sec);
82*b5893f02SDimitry Andric }
83*b5893f02SDimitry Andric 
isBerkeleyData(DataRefImpl Sec) const84*b5893f02SDimitry Andric bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const {
85*b5893f02SDimitry Andric   return isSectionData(Sec);
86*b5893f02SDimitry Andric }
87*b5893f02SDimitry Andric 
getRelocatedSection(DataRefImpl Sec) const88f785676fSDimitry Andric section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const {
89f785676fSDimitry Andric   return section_iterator(SectionRef(Sec, this));
902754fe60SDimitry Andric }
91f785676fSDimitry Andric 
makeTriple() const922cab237bSDimitry Andric Triple ObjectFile::makeTriple() const {
932cab237bSDimitry Andric   Triple TheTriple;
942cab237bSDimitry Andric   auto Arch = getArch();
952cab237bSDimitry Andric   TheTriple.setArch(Triple::ArchType(Arch));
962cab237bSDimitry Andric 
972cab237bSDimitry Andric   // For ARM targets, try to use the build attributes to build determine
982cab237bSDimitry Andric   // the build target. Target features are also added, but later during
992cab237bSDimitry Andric   // disassembly.
1002cab237bSDimitry Andric   if (Arch == Triple::arm || Arch == Triple::armeb)
1012cab237bSDimitry Andric     setARMSubArch(TheTriple);
1022cab237bSDimitry Andric 
1032cab237bSDimitry Andric   // TheTriple defaults to ELF, and COFF doesn't have an environment:
1042cab237bSDimitry Andric   // the best we can do here is indicate that it is mach-o.
1052cab237bSDimitry Andric   if (isMachO())
1062cab237bSDimitry Andric     TheTriple.setObjectFormat(Triple::MachO);
1072cab237bSDimitry Andric 
1082cab237bSDimitry Andric   if (isCOFF()) {
1092cab237bSDimitry Andric     const auto COFFObj = dyn_cast<COFFObjectFile>(this);
1102cab237bSDimitry Andric     if (COFFObj->getArch() == Triple::thumb)
1112cab237bSDimitry Andric       TheTriple.setTriple("thumbv7-windows");
1122cab237bSDimitry Andric   }
1132cab237bSDimitry Andric 
1142cab237bSDimitry Andric   return TheTriple;
1152cab237bSDimitry Andric }
1162cab237bSDimitry Andric 
1173ca95b02SDimitry Andric Expected<std::unique_ptr<ObjectFile>>
createObjectFile(MemoryBufferRef Object,file_magic Type)118db17bf38SDimitry Andric ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) {
11939d628a0SDimitry Andric   StringRef Data = Object.getBuffer();
120db17bf38SDimitry Andric   if (Type == file_magic::unknown)
121db17bf38SDimitry Andric     Type = identify_magic(Data);
122f785676fSDimitry Andric 
123f785676fSDimitry Andric   switch (Type) {
124db17bf38SDimitry Andric   case file_magic::unknown:
125db17bf38SDimitry Andric   case file_magic::bitcode:
126db17bf38SDimitry Andric   case file_magic::coff_cl_gl_object:
127db17bf38SDimitry Andric   case file_magic::archive:
128db17bf38SDimitry Andric   case file_magic::macho_universal_binary:
129db17bf38SDimitry Andric   case file_magic::windows_resource:
1304ba319b5SDimitry Andric   case file_magic::pdb:
1313ca95b02SDimitry Andric     return errorCodeToError(object_error::invalid_file_type);
132db17bf38SDimitry Andric   case file_magic::elf:
133db17bf38SDimitry Andric   case file_magic::elf_relocatable:
134db17bf38SDimitry Andric   case file_magic::elf_executable:
135db17bf38SDimitry Andric   case file_magic::elf_shared_object:
136db17bf38SDimitry Andric   case file_magic::elf_core:
1372cab237bSDimitry Andric     return createELFObjectFile(Object);
138db17bf38SDimitry Andric   case file_magic::macho_object:
139db17bf38SDimitry Andric   case file_magic::macho_executable:
140db17bf38SDimitry Andric   case file_magic::macho_fixed_virtual_memory_shared_lib:
141db17bf38SDimitry Andric   case file_magic::macho_core:
142db17bf38SDimitry Andric   case file_magic::macho_preload_executable:
143db17bf38SDimitry Andric   case file_magic::macho_dynamically_linked_shared_lib:
144db17bf38SDimitry Andric   case file_magic::macho_dynamic_linker:
145db17bf38SDimitry Andric   case file_magic::macho_bundle:
146db17bf38SDimitry Andric   case file_magic::macho_dynamically_linked_shared_lib_stub:
147db17bf38SDimitry Andric   case file_magic::macho_dsym_companion:
148db17bf38SDimitry Andric   case file_magic::macho_kext_bundle:
149f785676fSDimitry Andric     return createMachOObjectFile(Object);
150db17bf38SDimitry Andric   case file_magic::coff_object:
151db17bf38SDimitry Andric   case file_magic::coff_import_library:
152db17bf38SDimitry Andric   case file_magic::pecoff_executable:
1532cab237bSDimitry Andric     return createCOFFObjectFile(Object);
154db17bf38SDimitry Andric   case file_magic::wasm_object:
155d88c1a5aSDimitry Andric     return createWasmObjectFile(Object);
156f785676fSDimitry Andric   }
157f785676fSDimitry Andric   llvm_unreachable("Unexpected Object File Type");
1582754fe60SDimitry Andric }
1592754fe60SDimitry Andric 
1603ca95b02SDimitry Andric Expected<OwningBinary<ObjectFile>>
createObjectFile(StringRef ObjectPath)16139d628a0SDimitry Andric ObjectFile::createObjectFile(StringRef ObjectPath) {
16291bc56edSDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
16391bc56edSDimitry Andric       MemoryBuffer::getFile(ObjectPath);
16491bc56edSDimitry Andric   if (std::error_code EC = FileOrErr.getError())
1653ca95b02SDimitry Andric     return errorCodeToError(EC);
16639d628a0SDimitry Andric   std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get());
16739d628a0SDimitry Andric 
1683ca95b02SDimitry Andric   Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
16939d628a0SDimitry Andric       createObjectFile(Buffer->getMemBufferRef());
170d88c1a5aSDimitry Andric   if (Error Err = ObjOrErr.takeError())
171d88c1a5aSDimitry Andric     return std::move(Err);
17239d628a0SDimitry Andric   std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
17339d628a0SDimitry Andric 
17439d628a0SDimitry Andric   return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer));
1752754fe60SDimitry Andric }
176