1d341c932SEugene Zelenko //===- ObjectFile.cpp - File format independent object file ---------------===//
2fe5ee802SMichael J. Spencer //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe5ee802SMichael J. Spencer //
7fe5ee802SMichael J. Spencer //===----------------------------------------------------------------------===//
8fe5ee802SMichael J. Spencer //
9fe5ee802SMichael J. Spencer // This file defines a file format independent ObjectFile class.
10fe5ee802SMichael J. Spencer //
11fe5ee802SMichael J. Spencer //===----------------------------------------------------------------------===//
12fe5ee802SMichael J. Spencer
136bda14b3SChandler Carruth #include "llvm/Object/ObjectFile.h"
14d341c932SEugene Zelenko #include "llvm/ADT/StringRef.h"
15264b5d9eSZachary Turner #include "llvm/BinaryFormat/Magic.h"
16d341c932SEugene Zelenko #include "llvm/Object/Binary.h"
17437b0d58SRafael Espindola #include "llvm/Object/COFF.h"
18d341c932SEugene Zelenko #include "llvm/Object/Error.h"
19437b0d58SRafael Espindola #include "llvm/Object/MachO.h"
202c6f75ddSDerek Schuff #include "llvm/Object/Wasm.h"
21d341c932SEugene Zelenko #include "llvm/Support/Error.h"
22fe5ee802SMichael J. Spencer #include "llvm/Support/ErrorHandling.h"
23d341c932SEugene Zelenko #include "llvm/Support/ErrorOr.h"
24e72c195fSserge-sans-paille #include "llvm/Support/Format.h"
25fe5ee802SMichael J. Spencer #include "llvm/Support/MemoryBuffer.h"
26b1f8a5a5SAaron Ballman #include "llvm/Support/raw_ostream.h"
27d341c932SEugene Zelenko #include <cstdint>
28d341c932SEugene Zelenko #include <memory>
29a6e9c3e4SRafael Espindola #include <system_error>
30fe5ee802SMichael J. Spencer
31f177d16fSMichael J. Spencer using namespace llvm;
32f177d16fSMichael J. Spencer using namespace object;
33fe5ee802SMichael J. Spencer
operator <<(raw_ostream & OS,const SectionedAddress & Addr)34c0fc29c4SPavel Labath raw_ostream &object::operator<<(raw_ostream &OS, const SectionedAddress &Addr) {
35c0fc29c4SPavel Labath OS << "SectionedAddress{" << format_hex(Addr.Address, 10);
36c0fc29c4SPavel Labath if (Addr.SectionIndex != SectionedAddress::UndefSection)
37c0fc29c4SPavel Labath OS << ", " << Addr.SectionIndex;
38c0fc29c4SPavel Labath return OS << "}";
39c0fc29c4SPavel Labath }
40c0fc29c4SPavel Labath
anchor()41a379b181SDavid Blaikie void ObjectFile::anchor() {}
42a379b181SDavid Blaikie
ObjectFile(unsigned int Type,MemoryBufferRef Source)4348af1c2aSRafael Espindola ObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source)
4448af1c2aSRafael Espindola : SymbolicFile(Type, Source) {}
45f12b8282SRafael Espindola
containsSymbol(SymbolRef S) const46e9c58c74SRafael Espindola bool SectionRef::containsSymbol(SymbolRef S) const {
477bd8d994SKevin Enderby Expected<section_iterator> SymSec = S.getSection();
487bd8d994SKevin Enderby if (!SymSec) {
497bd8d994SKevin Enderby // TODO: Actually report errors helpfully.
507bd8d994SKevin Enderby consumeError(SymSec.takeError());
51e9c58c74SRafael Espindola return false;
527bd8d994SKevin Enderby }
538bab889bSRafael Espindola return *this == **SymSec;
54e9c58c74SRafael Espindola }
55e9c58c74SRafael Espindola
getSymbolValue(DataRefImpl Ref) const56ff6a0b6aSXing GUO Expected<uint64_t> ObjectFile::getSymbolValue(DataRefImpl Ref) const {
572410fb46SDuncan P. N. Exon Smith uint32_t Flags;
582410fb46SDuncan P. N. Exon Smith if (Error E = getSymbolFlags(Ref).moveInto(Flags))
59ff6a0b6aSXing GUO // TODO: Test this error.
602410fb46SDuncan P. N. Exon Smith return std::move(E);
612410fb46SDuncan P. N. Exon Smith
622410fb46SDuncan P. N. Exon Smith if (Flags & SymbolRef::SF_Undefined)
632410fb46SDuncan P. N. Exon Smith return 0;
642410fb46SDuncan P. N. Exon Smith if (Flags & SymbolRef::SF_Common)
652410fb46SDuncan P. N. Exon Smith return getCommonSymbolSize(Ref);
66be8b0ea8SRafael Espindola return getSymbolValueImpl(Ref);
67be8b0ea8SRafael Espindola }
68be8b0ea8SRafael Espindola
printSymbolName(raw_ostream & OS,DataRefImpl Symb) const69e357ca82SFangrui Song Error ObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const {
7081e8b7d9SKevin Enderby Expected<StringRef> Name = getSymbolName(Symb);
7181e8b7d9SKevin Enderby if (!Name)
72e357ca82SFangrui Song return Name.takeError();
735d0c2ffaSRafael Espindola OS << *Name;
74e357ca82SFangrui Song return Error::success();
75f12b8282SRafael Espindola }
76fe5ee802SMichael J. Spencer
getSymbolAlignment(DataRefImpl DRI) const77a4d22472SRafael Espindola uint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; }
78e4dd2e01SRafael Espindola
isSectionBitcode(DataRefImpl Sec) const79f2fe0141SSteven Wu bool ObjectFile::isSectionBitcode(DataRefImpl Sec) const {
8078e8011aSGeorge Rimar Expected<StringRef> NameOrErr = getSectionName(Sec);
8178e8011aSGeorge Rimar if (NameOrErr)
828be28cdcSFangrui Song return *NameOrErr == ".llvmbc";
8378e8011aSGeorge Rimar consumeError(NameOrErr.takeError());
84f2fe0141SSteven Wu return false;
85f2fe0141SSteven Wu }
86f2fe0141SSteven Wu
isSectionStripped(DataRefImpl Sec) const878af2387bSJonas Devlieghere bool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; }
888af2387bSJonas Devlieghere
isBerkeleyText(DataRefImpl Sec) const894888c4abSJordan Rupprecht bool ObjectFile::isBerkeleyText(DataRefImpl Sec) const {
904888c4abSJordan Rupprecht return isSectionText(Sec);
914888c4abSJordan Rupprecht }
924888c4abSJordan Rupprecht
isBerkeleyData(DataRefImpl Sec) const934888c4abSJordan Rupprecht bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const {
944888c4abSJordan Rupprecht return isSectionData(Sec);
954888c4abSJordan Rupprecht }
964888c4abSJordan Rupprecht
isDebugSection(DataRefImpl Sec) const97bf809cd1SEsme-Yi bool ObjectFile::isDebugSection(DataRefImpl Sec) const { return false; }
9829d253c4SDjordje Todorovic
992bf01dcbSGeorge Rimar Expected<section_iterator>
getRelocatedSection(DataRefImpl Sec) const1002bf01dcbSGeorge Rimar ObjectFile::getRelocatedSection(DataRefImpl Sec) const {
1014f60a38fSRafael Espindola return section_iterator(SectionRef(Sec, this));
1024f60a38fSRafael Espindola }
1034f60a38fSRafael Espindola
makeTriple() const104de62046dSVlad Tsyrklevich Triple ObjectFile::makeTriple() const {
105de62046dSVlad Tsyrklevich Triple TheTriple;
106de62046dSVlad Tsyrklevich auto Arch = getArch();
107de62046dSVlad Tsyrklevich TheTriple.setArch(Triple::ArchType(Arch));
108de62046dSVlad Tsyrklevich
109de62046dSVlad Tsyrklevich // For ARM targets, try to use the build attributes to build determine
110de62046dSVlad Tsyrklevich // the build target. Target features are also added, but later during
111de62046dSVlad Tsyrklevich // disassembly.
112de62046dSVlad Tsyrklevich if (Arch == Triple::arm || Arch == Triple::armeb)
113de62046dSVlad Tsyrklevich setARMSubArch(TheTriple);
114de62046dSVlad Tsyrklevich
115de62046dSVlad Tsyrklevich // TheTriple defaults to ELF, and COFF doesn't have an environment:
116478af447SHubert Tong // something we can do here is indicate that it is mach-o.
117478af447SHubert Tong if (isMachO()) {
118de62046dSVlad Tsyrklevich TheTriple.setObjectFormat(Triple::MachO);
119478af447SHubert Tong } else if (isCOFF()) {
120bc9a1b37SSimon Pilgrim const auto COFFObj = cast<COFFObjectFile>(this);
121de62046dSVlad Tsyrklevich if (COFFObj->getArch() == Triple::thumb)
122de62046dSVlad Tsyrklevich TheTriple.setTriple("thumbv7-windows");
123478af447SHubert Tong } else if (isXCOFF()) {
124478af447SHubert Tong // XCOFF implies AIX.
125478af447SHubert Tong TheTriple.setOS(Triple::AIX);
126478af447SHubert Tong TheTriple.setObjectFormat(Triple::XCOFF);
127de62046dSVlad Tsyrklevich }
128de62046dSVlad Tsyrklevich
129de62046dSVlad Tsyrklevich return TheTriple;
130de62046dSVlad Tsyrklevich }
131de62046dSVlad Tsyrklevich
1323fcdf6aeSKevin Enderby Expected<std::unique_ptr<ObjectFile>>
createObjectFile(MemoryBufferRef Object,file_magic Type,bool InitContent)13399a6401aSGeorgii Rymar ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,
13499a6401aSGeorgii Rymar bool InitContent) {
13548af1c2aSRafael Espindola StringRef Data = Object.getBuffer();
136264b5d9eSZachary Turner if (Type == file_magic::unknown)
137264b5d9eSZachary Turner Type = identify_magic(Data);
13851cc3602SRafael Espindola
139cd81b909SRafael Espindola switch (Type) {
140264b5d9eSZachary Turner case file_magic::unknown:
141264b5d9eSZachary Turner case file_magic::bitcode:
142264b5d9eSZachary Turner case file_magic::coff_cl_gl_object:
143264b5d9eSZachary Turner case file_magic::archive:
144264b5d9eSZachary Turner case file_magic::macho_universal_binary:
145264b5d9eSZachary Turner case file_magic::windows_resource:
146aac28f31SZachary Turner case file_magic::pdb:
147581d79a4SPavel Labath case file_magic::minidump:
1480977f31cSAnirudh Prasad case file_magic::goff_object:
14924ebdb6cSJoseph Huber case file_magic::cuda_fatbinary:
150*afd2f7e9SJoseph Huber case file_magic::offload_binary:
15119fb52cbSChris Bieneman case file_magic::dxcontainer_object:
1523fcdf6aeSKevin Enderby return errorCodeToError(object_error::invalid_file_type);
153359840a6SCyndy Ishida case file_magic::tapi_file:
154359840a6SCyndy Ishida return errorCodeToError(object_error::invalid_file_type);
155264b5d9eSZachary Turner case file_magic::elf:
156264b5d9eSZachary Turner case file_magic::elf_relocatable:
157264b5d9eSZachary Turner case file_magic::elf_executable:
158264b5d9eSZachary Turner case file_magic::elf_shared_object:
159264b5d9eSZachary Turner case file_magic::elf_core:
16099a6401aSGeorgii Rymar return createELFObjectFile(Object, InitContent);
161264b5d9eSZachary Turner case file_magic::macho_object:
162264b5d9eSZachary Turner case file_magic::macho_executable:
163264b5d9eSZachary Turner case file_magic::macho_fixed_virtual_memory_shared_lib:
164264b5d9eSZachary Turner case file_magic::macho_core:
165264b5d9eSZachary Turner case file_magic::macho_preload_executable:
166264b5d9eSZachary Turner case file_magic::macho_dynamically_linked_shared_lib:
167264b5d9eSZachary Turner case file_magic::macho_dynamic_linker:
168264b5d9eSZachary Turner case file_magic::macho_bundle:
169264b5d9eSZachary Turner case file_magic::macho_dynamically_linked_shared_lib_stub:
170264b5d9eSZachary Turner case file_magic::macho_dsym_companion:
171264b5d9eSZachary Turner case file_magic::macho_kext_bundle:
1723fcdf6aeSKevin Enderby return createMachOObjectFile(Object);
173264b5d9eSZachary Turner case file_magic::coff_object:
174264b5d9eSZachary Turner case file_magic::coff_import_library:
175264b5d9eSZachary Turner case file_magic::pecoff_executable:
17612db383eSRafael Espindola return createCOFFObjectFile(Object);
177ab2eb2bfSHubert Tong case file_magic::xcoff_object_32:
178837ae69fSSean Fertile return createXCOFFObjectFile(Object, Binary::ID_XCOFF32);
179837ae69fSSean Fertile case file_magic::xcoff_object_64:
180837ae69fSSean Fertile return createXCOFFObjectFile(Object, Binary::ID_XCOFF64);
181264b5d9eSZachary Turner case file_magic::wasm_object:
1822c6f75ddSDerek Schuff return createWasmObjectFile(Object);
183fe5ee802SMichael J. Spencer }
184cd81b909SRafael Espindola llvm_unreachable("Unexpected Object File Type");
185fe5ee802SMichael J. Spencer }
186fe5ee802SMichael J. Spencer
1873fcdf6aeSKevin Enderby Expected<OwningBinary<ObjectFile>>
createObjectFile(StringRef ObjectPath)188437b0d58SRafael Espindola ObjectFile::createObjectFile(StringRef ObjectPath) {
189adf21f2aSRafael Espindola ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
190adf21f2aSRafael Espindola MemoryBuffer::getFile(ObjectPath);
191adf21f2aSRafael Espindola if (std::error_code EC = FileOrErr.getError())
1923fcdf6aeSKevin Enderby return errorCodeToError(EC);
19348af1c2aSRafael Espindola std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get());
19448af1c2aSRafael Espindola
1953fcdf6aeSKevin Enderby Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
19648af1c2aSRafael Espindola createObjectFile(Buffer->getMemBufferRef());
197b7c9deb5SJustin Bogner if (Error Err = ObjOrErr.takeError())
198c55cf4afSBill Wendling return std::move(Err);
19948af1c2aSRafael Espindola std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
20048af1c2aSRafael Espindola
20148af1c2aSRafael Espindola return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer));
202fe5ee802SMichael J. Spencer }
2039b3af5e7SAugusto Noronha
isReflectionSectionStrippable(llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind) const2049b3af5e7SAugusto Noronha bool ObjectFile::isReflectionSectionStrippable(
2059b3af5e7SAugusto Noronha llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind)
2069b3af5e7SAugusto Noronha const {
2079b3af5e7SAugusto Noronha using llvm::binaryformat::Swift5ReflectionSectionKind;
2089b3af5e7SAugusto Noronha return ReflectionSectionKind == Swift5ReflectionSectionKind::fieldmd ||
2099b3af5e7SAugusto Noronha ReflectionSectionKind == Swift5ReflectionSectionKind::reflstr ||
2109b3af5e7SAugusto Noronha ReflectionSectionKind == Swift5ReflectionSectionKind::assocty;
2119b3af5e7SAugusto Noronha }
212