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