Eugene Zelenko | 86bfc78 | 2017-04-19 23:02:10 +0000 | [diff] [blame] | 1 | //===- ObjectFile.cpp - File format independent object file ---------------===// |
Michael J. Spencer | 68b3f0c | 2010-11-15 03:21:41 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file defines a file format independent ObjectFile class. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
Chandler Carruth | e3e43d9 | 2017-06-06 11:49:48 +0000 | [diff] [blame] | 14 | #include "llvm/Object/ObjectFile.h" |
Eugene Zelenko | 86bfc78 | 2017-04-19 23:02:10 +0000 | [diff] [blame] | 15 | #include "llvm/ADT/StringRef.h" |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 16 | #include "llvm/BinaryFormat/Magic.h" |
Eugene Zelenko | 86bfc78 | 2017-04-19 23:02:10 +0000 | [diff] [blame] | 17 | #include "llvm/Object/Binary.h" |
Rafael Espindola | 79002da | 2014-07-31 03:12:45 +0000 | [diff] [blame] | 18 | #include "llvm/Object/COFF.h" |
Eugene Zelenko | 86bfc78 | 2017-04-19 23:02:10 +0000 | [diff] [blame] | 19 | #include "llvm/Object/Error.h" |
Rafael Espindola | 79002da | 2014-07-31 03:12:45 +0000 | [diff] [blame] | 20 | #include "llvm/Object/MachO.h" |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 21 | #include "llvm/Object/Wasm.h" |
Eugene Zelenko | 86bfc78 | 2017-04-19 23:02:10 +0000 | [diff] [blame] | 22 | #include "llvm/Support/Error.h" |
Michael J. Spencer | 68b3f0c | 2010-11-15 03:21:41 +0000 | [diff] [blame] | 23 | #include "llvm/Support/ErrorHandling.h" |
Eugene Zelenko | 86bfc78 | 2017-04-19 23:02:10 +0000 | [diff] [blame] | 24 | #include "llvm/Support/ErrorOr.h" |
Rafael Espindola | d27a978 | 2013-06-11 15:19:04 +0000 | [diff] [blame] | 25 | #include "llvm/Support/FileSystem.h" |
Michael J. Spencer | 68b3f0c | 2010-11-15 03:21:41 +0000 | [diff] [blame] | 26 | #include "llvm/Support/MemoryBuffer.h" |
Aaron Ballman | 100aba2 | 2014-02-21 20:42:18 +0000 | [diff] [blame] | 27 | #include "llvm/Support/raw_ostream.h" |
Eugene Zelenko | 86bfc78 | 2017-04-19 23:02:10 +0000 | [diff] [blame] | 28 | #include <algorithm> |
| 29 | #include <cstdint> |
| 30 | #include <memory> |
Rafael Espindola | d5132f9 | 2014-06-12 17:38:55 +0000 | [diff] [blame] | 31 | #include <system_error> |
Michael J. Spencer | 68b3f0c | 2010-11-15 03:21:41 +0000 | [diff] [blame] | 32 | |
Michael J. Spencer | 88af6b9 | 2010-11-16 01:06:51 +0000 | [diff] [blame] | 33 | using namespace llvm; |
| 34 | using namespace object; |
Michael J. Spencer | 68b3f0c | 2010-11-15 03:21:41 +0000 | [diff] [blame] | 35 | |
Eugene Zelenko | 86bfc78 | 2017-04-19 23:02:10 +0000 | [diff] [blame] | 36 | void ObjectFile::anchor() {} |
David Blaikie | 2d24e2a | 2011-12-20 02:50:00 +0000 | [diff] [blame] | 37 | |
Rafael Espindola | 548f2b6 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 38 | ObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source) |
| 39 | : SymbolicFile(Type, Source) {} |
Rafael Espindola | 91f86b7 | 2014-02-21 20:10:59 +0000 | [diff] [blame] | 40 | |
Rafael Espindola | d231306 | 2015-06-30 20:18:49 +0000 | [diff] [blame] | 41 | bool SectionRef::containsSymbol(SymbolRef S) const { |
Kevin Enderby | a486dca | 2016-05-02 20:28:12 +0000 | [diff] [blame] | 42 | Expected<section_iterator> SymSec = S.getSection(); |
| 43 | if (!SymSec) { |
| 44 | // TODO: Actually report errors helpfully. |
| 45 | consumeError(SymSec.takeError()); |
Rafael Espindola | d231306 | 2015-06-30 20:18:49 +0000 | [diff] [blame] | 46 | return false; |
Kevin Enderby | a486dca | 2016-05-02 20:28:12 +0000 | [diff] [blame] | 47 | } |
Rafael Espindola | e84d8c1 | 2015-08-07 23:27:14 +0000 | [diff] [blame] | 48 | return *this == **SymSec; |
Rafael Espindola | d231306 | 2015-06-30 20:18:49 +0000 | [diff] [blame] | 49 | } |
| 50 | |
Rafael Espindola | 7b7c81c | 2015-07-07 17:12:59 +0000 | [diff] [blame] | 51 | uint64_t ObjectFile::getSymbolValue(DataRefImpl Ref) const { |
| 52 | uint32_t Flags = getSymbolFlags(Ref); |
| 53 | if (Flags & SymbolRef::SF_Undefined) |
| 54 | return 0; |
| 55 | if (Flags & SymbolRef::SF_Common) |
| 56 | return getCommonSymbolSize(Ref); |
| 57 | return getSymbolValueImpl(Ref); |
| 58 | } |
| 59 | |
Rafael Espindola | 4e2b922 | 2014-06-13 02:24:39 +0000 | [diff] [blame] | 60 | std::error_code ObjectFile::printSymbolName(raw_ostream &OS, |
| 61 | DataRefImpl Symb) const { |
Kevin Enderby | 813e0cf | 2016-04-20 21:24:34 +0000 | [diff] [blame] | 62 | Expected<StringRef> Name = getSymbolName(Symb); |
| 63 | if (!Name) |
| 64 | return errorToErrorCode(Name.takeError()); |
Rafael Espindola | 8a80641 | 2015-07-02 20:55:21 +0000 | [diff] [blame] | 65 | OS << *Name; |
Rui Ueyama | eae4673 | 2015-06-09 15:20:42 +0000 | [diff] [blame] | 66 | return std::error_code(); |
Rafael Espindola | 91f86b7 | 2014-02-21 20:10:59 +0000 | [diff] [blame] | 67 | } |
Michael J. Spencer | 68b3f0c | 2010-11-15 03:21:41 +0000 | [diff] [blame] | 68 | |
Rafael Espindola | 64afb83 | 2015-05-31 23:52:50 +0000 | [diff] [blame] | 69 | uint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; } |
Rafael Espindola | 59a0e79 | 2013-04-29 22:24:22 +0000 | [diff] [blame] | 70 | |
Steven Wu | b9de197 | 2016-02-29 19:40:10 +0000 | [diff] [blame] | 71 | bool ObjectFile::isSectionBitcode(DataRefImpl Sec) const { |
| 72 | StringRef SectName; |
| 73 | if (!getSectionName(Sec, SectName)) |
| 74 | return SectName == ".llvmbc"; |
| 75 | return false; |
| 76 | } |
| 77 | |
Jonas Devlieghere | ac9a500 | 2017-09-26 14:22:35 +0000 | [diff] [blame] | 78 | bool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; } |
| 79 | |
Jordan Rupprecht | 91c6885 | 2018-12-13 19:40:12 +0000 | [diff] [blame] | 80 | bool ObjectFile::isBerkeleyText(DataRefImpl Sec) const { |
| 81 | return isSectionText(Sec); |
| 82 | } |
| 83 | |
| 84 | bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const { |
| 85 | return isSectionData(Sec); |
| 86 | } |
| 87 | |
Rafael Espindola | 7486d92 | 2013-05-30 03:05:14 +0000 | [diff] [blame] | 88 | section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const { |
| 89 | return section_iterator(SectionRef(Sec, this)); |
| 90 | } |
| 91 | |
Vlad Tsyrklevich | b261c46 | 2017-09-19 02:22:48 +0000 | [diff] [blame] | 92 | Triple ObjectFile::makeTriple() const { |
| 93 | Triple TheTriple; |
| 94 | auto Arch = getArch(); |
| 95 | TheTriple.setArch(Triple::ArchType(Arch)); |
| 96 | |
| 97 | // For ARM targets, try to use the build attributes to build determine |
| 98 | // the build target. Target features are also added, but later during |
| 99 | // disassembly. |
| 100 | if (Arch == Triple::arm || Arch == Triple::armeb) |
| 101 | setARMSubArch(TheTriple); |
| 102 | |
| 103 | // TheTriple defaults to ELF, and COFF doesn't have an environment: |
| 104 | // the best we can do here is indicate that it is mach-o. |
| 105 | if (isMachO()) |
| 106 | TheTriple.setObjectFormat(Triple::MachO); |
| 107 | |
| 108 | if (isCOFF()) { |
| 109 | const auto COFFObj = dyn_cast<COFFObjectFile>(this); |
| 110 | if (COFFObj->getArch() == Triple::thumb) |
| 111 | TheTriple.setTriple("thumbv7-windows"); |
| 112 | } |
| 113 | |
| 114 | return TheTriple; |
| 115 | } |
| 116 | |
Kevin Enderby | c6bf9be | 2016-04-06 22:14:09 +0000 | [diff] [blame] | 117 | Expected<std::unique_ptr<ObjectFile>> |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 118 | ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) { |
Rafael Espindola | 548f2b6 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 119 | StringRef Data = Object.getBuffer(); |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 120 | if (Type == file_magic::unknown) |
| 121 | Type = identify_magic(Data); |
Rafael Espindola | 825fc31 | 2014-01-22 00:14:49 +0000 | [diff] [blame] | 122 | |
Rafael Espindola | d27a978 | 2013-06-11 15:19:04 +0000 | [diff] [blame] | 123 | switch (Type) { |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 124 | case file_magic::unknown: |
| 125 | case file_magic::bitcode: |
| 126 | case file_magic::coff_cl_gl_object: |
| 127 | case file_magic::archive: |
| 128 | case file_magic::macho_universal_binary: |
| 129 | case file_magic::windows_resource: |
Zachary Turner | a896ada | 2018-03-07 18:58:33 +0000 | [diff] [blame] | 130 | case file_magic::pdb: |
Kevin Enderby | c6bf9be | 2016-04-06 22:14:09 +0000 | [diff] [blame] | 131 | return errorCodeToError(object_error::invalid_file_type); |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 132 | case file_magic::elf: |
| 133 | case file_magic::elf_relocatable: |
| 134 | case file_magic::elf_executable: |
| 135 | case file_magic::elf_shared_object: |
| 136 | case file_magic::elf_core: |
Rafael Espindola | e2d20cb | 2017-10-10 20:00:07 +0000 | [diff] [blame] | 137 | return createELFObjectFile(Object); |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 138 | case file_magic::macho_object: |
| 139 | case file_magic::macho_executable: |
| 140 | case file_magic::macho_fixed_virtual_memory_shared_lib: |
| 141 | case file_magic::macho_core: |
| 142 | case file_magic::macho_preload_executable: |
| 143 | case file_magic::macho_dynamically_linked_shared_lib: |
| 144 | case file_magic::macho_dynamic_linker: |
| 145 | case file_magic::macho_bundle: |
| 146 | case file_magic::macho_dynamically_linked_shared_lib_stub: |
| 147 | case file_magic::macho_dsym_companion: |
| 148 | case file_magic::macho_kext_bundle: |
Kevin Enderby | c6bf9be | 2016-04-06 22:14:09 +0000 | [diff] [blame] | 149 | return createMachOObjectFile(Object); |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 150 | case file_magic::coff_object: |
| 151 | case file_magic::coff_import_library: |
| 152 | case file_magic::pecoff_executable: |
Rafael Espindola | e2d20cb | 2017-10-10 20:00:07 +0000 | [diff] [blame] | 153 | return createCOFFObjectFile(Object); |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 154 | case file_magic::wasm_object: |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 155 | return createWasmObjectFile(Object); |
Michael J. Spencer | 68b3f0c | 2010-11-15 03:21:41 +0000 | [diff] [blame] | 156 | } |
Rafael Espindola | d27a978 | 2013-06-11 15:19:04 +0000 | [diff] [blame] | 157 | llvm_unreachable("Unexpected Object File Type"); |
Michael J. Spencer | 68b3f0c | 2010-11-15 03:21:41 +0000 | [diff] [blame] | 158 | } |
| 159 | |
Kevin Enderby | c6bf9be | 2016-04-06 22:14:09 +0000 | [diff] [blame] | 160 | Expected<OwningBinary<ObjectFile>> |
Rafael Espindola | 79002da | 2014-07-31 03:12:45 +0000 | [diff] [blame] | 161 | ObjectFile::createObjectFile(StringRef ObjectPath) { |
Rafael Espindola | 7cba2a9 | 2014-07-06 17:43:13 +0000 | [diff] [blame] | 162 | ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = |
| 163 | MemoryBuffer::getFile(ObjectPath); |
| 164 | if (std::error_code EC = FileOrErr.getError()) |
Kevin Enderby | c6bf9be | 2016-04-06 22:14:09 +0000 | [diff] [blame] | 165 | return errorCodeToError(EC); |
Rafael Espindola | 548f2b6 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 166 | std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get()); |
| 167 | |
Kevin Enderby | c6bf9be | 2016-04-06 22:14:09 +0000 | [diff] [blame] | 168 | Expected<std::unique_ptr<ObjectFile>> ObjOrErr = |
Rafael Espindola | 548f2b6 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 169 | createObjectFile(Buffer->getMemBufferRef()); |
Justin Bogner | b3c2bab | 2016-10-18 05:17:23 +0000 | [diff] [blame] | 170 | if (Error Err = ObjOrErr.takeError()) |
| 171 | return std::move(Err); |
Rafael Espindola | 548f2b6 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 172 | std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get()); |
| 173 | |
| 174 | return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer)); |
Michael J. Spencer | 68b3f0c | 2010-11-15 03:21:41 +0000 | [diff] [blame] | 175 | } |