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 
36dff0c46cSDimitry Andric void ObjectFile::anchor() {}
37dff0c46cSDimitry Andric 
3839d628a0SDimitry Andric ObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source)
3939d628a0SDimitry Andric     : SymbolicFile(Type, Source) {}
4091bc56edSDimitry Andric 
413dac3a9bSDimitry 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 
51875ed548SDimitry 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 
6091bc56edSDimitry 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 
6997bc6c73SDimitry Andric uint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; }
70284c1978SDimitry Andric 
713ca95b02SDimitry 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 
782cab237bSDimitry Andric bool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; }
792cab237bSDimitry Andric 
80f785676fSDimitry Andric section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const {
81f785676fSDimitry Andric   return section_iterator(SectionRef(Sec, this));
822754fe60SDimitry Andric }
83f785676fSDimitry Andric 
842cab237bSDimitry Andric Triple ObjectFile::makeTriple() const {
852cab237bSDimitry Andric   Triple TheTriple;
862cab237bSDimitry Andric   auto Arch = getArch();
872cab237bSDimitry Andric   TheTriple.setArch(Triple::ArchType(Arch));
882cab237bSDimitry Andric 
892cab237bSDimitry Andric   // For ARM targets, try to use the build attributes to build determine
902cab237bSDimitry Andric   // the build target. Target features are also added, but later during
912cab237bSDimitry Andric   // disassembly.
922cab237bSDimitry Andric   if (Arch == Triple::arm || Arch == Triple::armeb)
932cab237bSDimitry Andric     setARMSubArch(TheTriple);
942cab237bSDimitry Andric 
952cab237bSDimitry Andric   // TheTriple defaults to ELF, and COFF doesn't have an environment:
962cab237bSDimitry Andric   // the best we can do here is indicate that it is mach-o.
972cab237bSDimitry Andric   if (isMachO())
982cab237bSDimitry Andric     TheTriple.setObjectFormat(Triple::MachO);
992cab237bSDimitry Andric 
1002cab237bSDimitry Andric   if (isCOFF()) {
1012cab237bSDimitry Andric     const auto COFFObj = dyn_cast<COFFObjectFile>(this);
1022cab237bSDimitry Andric     if (COFFObj->getArch() == Triple::thumb)
1032cab237bSDimitry Andric       TheTriple.setTriple("thumbv7-windows");
1042cab237bSDimitry Andric   }
1052cab237bSDimitry Andric 
1062cab237bSDimitry Andric   return TheTriple;
1072cab237bSDimitry Andric }
1082cab237bSDimitry Andric 
1093ca95b02SDimitry Andric Expected<std::unique_ptr<ObjectFile>>
110db17bf38SDimitry Andric ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) {
11139d628a0SDimitry Andric   StringRef Data = Object.getBuffer();
112db17bf38SDimitry Andric   if (Type == file_magic::unknown)
113db17bf38SDimitry Andric     Type = identify_magic(Data);
114f785676fSDimitry Andric 
115f785676fSDimitry Andric   switch (Type) {
116db17bf38SDimitry Andric   case file_magic::unknown:
117db17bf38SDimitry Andric   case file_magic::bitcode:
118db17bf38SDimitry Andric   case file_magic::coff_cl_gl_object:
119db17bf38SDimitry Andric   case file_magic::archive:
120db17bf38SDimitry Andric   case file_magic::macho_universal_binary:
121db17bf38SDimitry Andric   case file_magic::windows_resource:
1223ca95b02SDimitry Andric     return errorCodeToError(object_error::invalid_file_type);
123db17bf38SDimitry Andric   case file_magic::elf:
124db17bf38SDimitry Andric   case file_magic::elf_relocatable:
125db17bf38SDimitry Andric   case file_magic::elf_executable:
126db17bf38SDimitry Andric   case file_magic::elf_shared_object:
127db17bf38SDimitry Andric   case file_magic::elf_core:
1282cab237bSDimitry Andric     return createELFObjectFile(Object);
129db17bf38SDimitry Andric   case file_magic::macho_object:
130db17bf38SDimitry Andric   case file_magic::macho_executable:
131db17bf38SDimitry Andric   case file_magic::macho_fixed_virtual_memory_shared_lib:
132db17bf38SDimitry Andric   case file_magic::macho_core:
133db17bf38SDimitry Andric   case file_magic::macho_preload_executable:
134db17bf38SDimitry Andric   case file_magic::macho_dynamically_linked_shared_lib:
135db17bf38SDimitry Andric   case file_magic::macho_dynamic_linker:
136db17bf38SDimitry Andric   case file_magic::macho_bundle:
137db17bf38SDimitry Andric   case file_magic::macho_dynamically_linked_shared_lib_stub:
138db17bf38SDimitry Andric   case file_magic::macho_dsym_companion:
139db17bf38SDimitry Andric   case file_magic::macho_kext_bundle:
140f785676fSDimitry Andric     return createMachOObjectFile(Object);
141db17bf38SDimitry Andric   case file_magic::coff_object:
142db17bf38SDimitry Andric   case file_magic::coff_import_library:
143db17bf38SDimitry Andric   case file_magic::pecoff_executable:
1442cab237bSDimitry Andric     return createCOFFObjectFile(Object);
145db17bf38SDimitry Andric   case file_magic::wasm_object:
146d88c1a5aSDimitry Andric     return createWasmObjectFile(Object);
147f785676fSDimitry Andric   }
148f785676fSDimitry Andric   llvm_unreachable("Unexpected Object File Type");
1492754fe60SDimitry Andric }
1502754fe60SDimitry Andric 
1513ca95b02SDimitry Andric Expected<OwningBinary<ObjectFile>>
15239d628a0SDimitry Andric ObjectFile::createObjectFile(StringRef ObjectPath) {
15391bc56edSDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
15491bc56edSDimitry Andric       MemoryBuffer::getFile(ObjectPath);
15591bc56edSDimitry Andric   if (std::error_code EC = FileOrErr.getError())
1563ca95b02SDimitry Andric     return errorCodeToError(EC);
15739d628a0SDimitry Andric   std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get());
15839d628a0SDimitry Andric 
1593ca95b02SDimitry Andric   Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
16039d628a0SDimitry Andric       createObjectFile(Buffer->getMemBufferRef());
161d88c1a5aSDimitry Andric   if (Error Err = ObjOrErr.takeError())
162d88c1a5aSDimitry Andric     return std::move(Err);
16339d628a0SDimitry Andric   std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
16439d628a0SDimitry Andric 
16539d628a0SDimitry Andric   return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer));
1662754fe60SDimitry Andric }
167