1d99dafe2SDimitry Andric //===- ObjectFile.cpp - File format independent object file ---------------===//
2cf099d11SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cf099d11SDimitry Andric //
7cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
8cf099d11SDimitry Andric //
9cf099d11SDimitry Andric // This file defines a file format independent ObjectFile class.
10cf099d11SDimitry Andric //
11cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
12cf099d11SDimitry Andric
137ab83427SDimitry Andric #include "llvm/Object/ObjectFile.h"
14d99dafe2SDimitry Andric #include "llvm/ADT/StringRef.h"
157ab83427SDimitry Andric #include "llvm/BinaryFormat/Magic.h"
16d99dafe2SDimitry Andric #include "llvm/Object/Binary.h"
1767c32a98SDimitry Andric #include "llvm/Object/COFF.h"
18d99dafe2SDimitry Andric #include "llvm/Object/Error.h"
1967c32a98SDimitry Andric #include "llvm/Object/MachO.h"
20b915e9e0SDimitry Andric #include "llvm/Object/Wasm.h"
21d99dafe2SDimitry Andric #include "llvm/Support/Error.h"
22cf099d11SDimitry Andric #include "llvm/Support/ErrorHandling.h"
23d99dafe2SDimitry Andric #include "llvm/Support/ErrorOr.h"
24145449b1SDimitry Andric #include "llvm/Support/Format.h"
25cf099d11SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
265ca98fd9SDimitry Andric #include "llvm/Support/raw_ostream.h"
27d99dafe2SDimitry Andric #include <cstdint>
28d99dafe2SDimitry Andric #include <memory>
295ca98fd9SDimitry Andric #include <system_error>
30cf099d11SDimitry Andric
31cf099d11SDimitry Andric using namespace llvm;
32cf099d11SDimitry Andric using namespace object;
33cf099d11SDimitry Andric
operator <<(raw_ostream & OS,const SectionedAddress & Addr)34706b4fc4SDimitry Andric raw_ostream &object::operator<<(raw_ostream &OS, const SectionedAddress &Addr) {
35706b4fc4SDimitry Andric OS << "SectionedAddress{" << format_hex(Addr.Address, 10);
36706b4fc4SDimitry Andric if (Addr.SectionIndex != SectionedAddress::UndefSection)
37706b4fc4SDimitry Andric OS << ", " << Addr.SectionIndex;
38706b4fc4SDimitry Andric return OS << "}";
39706b4fc4SDimitry Andric }
40706b4fc4SDimitry Andric
anchor()4163faed5bSDimitry Andric void ObjectFile::anchor() {}
4263faed5bSDimitry Andric
ObjectFile(unsigned int Type,MemoryBufferRef Source)4367c32a98SDimitry Andric ObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source)
4467c32a98SDimitry Andric : SymbolicFile(Type, Source) {}
455ca98fd9SDimitry Andric
containsSymbol(SymbolRef S) const461a82d4c0SDimitry Andric bool SectionRef::containsSymbol(SymbolRef S) const {
4701095a5dSDimitry Andric Expected<section_iterator> SymSec = S.getSection();
4801095a5dSDimitry Andric if (!SymSec) {
4901095a5dSDimitry Andric // TODO: Actually report errors helpfully.
5001095a5dSDimitry Andric consumeError(SymSec.takeError());
511a82d4c0SDimitry Andric return false;
5201095a5dSDimitry Andric }
53dd58ef01SDimitry Andric return *this == **SymSec;
541a82d4c0SDimitry Andric }
551a82d4c0SDimitry Andric
getSymbolValue(DataRefImpl Ref) const56cfca06d7SDimitry Andric Expected<uint64_t> ObjectFile::getSymbolValue(DataRefImpl Ref) const {
57c0981da4SDimitry Andric uint32_t Flags;
58c0981da4SDimitry Andric if (Error E = getSymbolFlags(Ref).moveInto(Flags))
59cfca06d7SDimitry Andric // TODO: Test this error.
60c0981da4SDimitry Andric return std::move(E);
61c0981da4SDimitry Andric
62c0981da4SDimitry Andric if (Flags & SymbolRef::SF_Undefined)
63c0981da4SDimitry Andric return 0;
64c0981da4SDimitry Andric if (Flags & SymbolRef::SF_Common)
65c0981da4SDimitry Andric return getCommonSymbolSize(Ref);
66ee8648bdSDimitry Andric return getSymbolValueImpl(Ref);
67ee8648bdSDimitry Andric }
68ee8648bdSDimitry Andric
printSymbolName(raw_ostream & OS,DataRefImpl Symb) const69e6d15924SDimitry Andric Error ObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const {
7001095a5dSDimitry Andric Expected<StringRef> Name = getSymbolName(Symb);
7101095a5dSDimitry Andric if (!Name)
72e6d15924SDimitry Andric return Name.takeError();
731a82d4c0SDimitry Andric OS << *Name;
74e6d15924SDimitry Andric return Error::success();
75cf099d11SDimitry Andric }
76cf099d11SDimitry Andric
getSymbolAlignment(DataRefImpl DRI) const7785d8b2bbSDimitry Andric uint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; }
7859d6cff9SDimitry Andric
isSectionBitcode(DataRefImpl Sec) const7901095a5dSDimitry Andric bool ObjectFile::isSectionBitcode(DataRefImpl Sec) const {
801d5ae102SDimitry Andric Expected<StringRef> NameOrErr = getSectionName(Sec);
811d5ae102SDimitry Andric if (NameOrErr)
82b1c73532SDimitry Andric return *NameOrErr == ".llvm.lto";
831d5ae102SDimitry Andric consumeError(NameOrErr.takeError());
8401095a5dSDimitry Andric return false;
8501095a5dSDimitry Andric }
8601095a5dSDimitry Andric
isSectionStripped(DataRefImpl Sec) const87044eb2f6SDimitry Andric bool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; }
88044eb2f6SDimitry Andric
isBerkeleyText(DataRefImpl Sec) const89d8e91e46SDimitry Andric bool ObjectFile::isBerkeleyText(DataRefImpl Sec) const {
90d8e91e46SDimitry Andric return isSectionText(Sec);
91d8e91e46SDimitry Andric }
92d8e91e46SDimitry Andric
isBerkeleyData(DataRefImpl Sec) const93d8e91e46SDimitry Andric bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const {
94d8e91e46SDimitry Andric return isSectionData(Sec);
95d8e91e46SDimitry Andric }
96d8e91e46SDimitry Andric
isDebugSection(DataRefImpl Sec) const97344a3780SDimitry Andric bool ObjectFile::isDebugSection(DataRefImpl Sec) const { return false; }
98cfca06d7SDimitry Andric
hasDebugInfo() const99e3b55780SDimitry Andric bool ObjectFile::hasDebugInfo() const {
100e3b55780SDimitry Andric return any_of(sections(),
101e3b55780SDimitry Andric [](SectionRef Sec) { return Sec.isDebugSection(); });
102e3b55780SDimitry Andric }
103e3b55780SDimitry Andric
1041d5ae102SDimitry Andric Expected<section_iterator>
getRelocatedSection(DataRefImpl Sec) const1051d5ae102SDimitry Andric ObjectFile::getRelocatedSection(DataRefImpl Sec) const {
106f8af5cf6SDimitry Andric return section_iterator(SectionRef(Sec, this));
107cf099d11SDimitry Andric }
108f8af5cf6SDimitry Andric
makeTriple() const109044eb2f6SDimitry Andric Triple ObjectFile::makeTriple() const {
110044eb2f6SDimitry Andric Triple TheTriple;
111044eb2f6SDimitry Andric auto Arch = getArch();
112044eb2f6SDimitry Andric TheTriple.setArch(Triple::ArchType(Arch));
113044eb2f6SDimitry Andric
114aca2e42cSDimitry Andric auto OS = getOS();
115aca2e42cSDimitry Andric if (OS != Triple::UnknownOS)
116aca2e42cSDimitry Andric TheTriple.setOS(OS);
117aca2e42cSDimitry Andric
118044eb2f6SDimitry Andric // For ARM targets, try to use the build attributes to build determine
119044eb2f6SDimitry Andric // the build target. Target features are also added, but later during
120044eb2f6SDimitry Andric // disassembly.
121044eb2f6SDimitry Andric if (Arch == Triple::arm || Arch == Triple::armeb)
122044eb2f6SDimitry Andric setARMSubArch(TheTriple);
123044eb2f6SDimitry Andric
124044eb2f6SDimitry Andric // TheTriple defaults to ELF, and COFF doesn't have an environment:
125cfca06d7SDimitry Andric // something we can do here is indicate that it is mach-o.
126cfca06d7SDimitry Andric if (isMachO()) {
127044eb2f6SDimitry Andric TheTriple.setObjectFormat(Triple::MachO);
128cfca06d7SDimitry Andric } else if (isCOFF()) {
1291d5ae102SDimitry Andric const auto COFFObj = cast<COFFObjectFile>(this);
130044eb2f6SDimitry Andric if (COFFObj->getArch() == Triple::thumb)
131044eb2f6SDimitry Andric TheTriple.setTriple("thumbv7-windows");
132cfca06d7SDimitry Andric } else if (isXCOFF()) {
133cfca06d7SDimitry Andric // XCOFF implies AIX.
134cfca06d7SDimitry Andric TheTriple.setOS(Triple::AIX);
135cfca06d7SDimitry Andric TheTriple.setObjectFormat(Triple::XCOFF);
136aca2e42cSDimitry Andric } else if (isGOFF()) {
1377fa27ce4SDimitry Andric TheTriple.setOS(Triple::ZOS);
1387fa27ce4SDimitry Andric TheTriple.setObjectFormat(Triple::GOFF);
139aca2e42cSDimitry Andric } else if (TheTriple.isAMDGPU()) {
140aca2e42cSDimitry Andric TheTriple.setVendor(Triple::AMD);
141aca2e42cSDimitry Andric } else if (TheTriple.isNVPTX()) {
142aca2e42cSDimitry Andric TheTriple.setVendor(Triple::NVIDIA);
1437fa27ce4SDimitry Andric }
144044eb2f6SDimitry Andric
145044eb2f6SDimitry Andric return TheTriple;
146044eb2f6SDimitry Andric }
147044eb2f6SDimitry Andric
14801095a5dSDimitry Andric Expected<std::unique_ptr<ObjectFile>>
createObjectFile(MemoryBufferRef Object,file_magic Type,bool InitContent)149b60736ecSDimitry Andric ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,
150b60736ecSDimitry Andric bool InitContent) {
15167c32a98SDimitry Andric StringRef Data = Object.getBuffer();
1527ab83427SDimitry Andric if (Type == file_magic::unknown)
1537ab83427SDimitry Andric Type = identify_magic(Data);
154f8af5cf6SDimitry Andric
155f8af5cf6SDimitry Andric switch (Type) {
1567ab83427SDimitry Andric case file_magic::unknown:
1577ab83427SDimitry Andric case file_magic::bitcode:
1584df029ccSDimitry Andric case file_magic::clang_ast:
1597ab83427SDimitry Andric case file_magic::coff_cl_gl_object:
1607ab83427SDimitry Andric case file_magic::archive:
1617ab83427SDimitry Andric case file_magic::macho_universal_binary:
1627ab83427SDimitry Andric case file_magic::windows_resource:
163eb11fae6SDimitry Andric case file_magic::pdb:
164e6d15924SDimitry Andric case file_magic::minidump:
165344a3780SDimitry Andric case file_magic::goff_object:
166145449b1SDimitry Andric case file_magic::cuda_fatbinary:
167145449b1SDimitry Andric case file_magic::offload_binary:
168145449b1SDimitry Andric case file_magic::dxcontainer_object:
169b1c73532SDimitry Andric case file_magic::offload_bundle:
170b1c73532SDimitry Andric case file_magic::offload_bundle_compressed:
171312c0ed1SDimitry Andric case file_magic::spirv_object:
17201095a5dSDimitry Andric return errorCodeToError(object_error::invalid_file_type);
1731d5ae102SDimitry Andric case file_magic::tapi_file:
1741d5ae102SDimitry Andric return errorCodeToError(object_error::invalid_file_type);
1757ab83427SDimitry Andric case file_magic::elf:
1767ab83427SDimitry Andric case file_magic::elf_relocatable:
1777ab83427SDimitry Andric case file_magic::elf_executable:
1787ab83427SDimitry Andric case file_magic::elf_shared_object:
1797ab83427SDimitry Andric case file_magic::elf_core:
180b60736ecSDimitry Andric return createELFObjectFile(Object, InitContent);
1817ab83427SDimitry Andric case file_magic::macho_object:
1827ab83427SDimitry Andric case file_magic::macho_executable:
1837ab83427SDimitry Andric case file_magic::macho_fixed_virtual_memory_shared_lib:
1847ab83427SDimitry Andric case file_magic::macho_core:
1857ab83427SDimitry Andric case file_magic::macho_preload_executable:
1867ab83427SDimitry Andric case file_magic::macho_dynamically_linked_shared_lib:
1877ab83427SDimitry Andric case file_magic::macho_dynamic_linker:
1887ab83427SDimitry Andric case file_magic::macho_bundle:
1897ab83427SDimitry Andric case file_magic::macho_dynamically_linked_shared_lib_stub:
1907ab83427SDimitry Andric case file_magic::macho_dsym_companion:
1917ab83427SDimitry Andric case file_magic::macho_kext_bundle:
192e3b55780SDimitry Andric case file_magic::macho_file_set:
193f8af5cf6SDimitry Andric return createMachOObjectFile(Object);
1947ab83427SDimitry Andric case file_magic::coff_object:
1957ab83427SDimitry Andric case file_magic::coff_import_library:
1967ab83427SDimitry Andric case file_magic::pecoff_executable:
197044eb2f6SDimitry Andric return createCOFFObjectFile(Object);
198e6d15924SDimitry Andric case file_magic::xcoff_object_32:
199e6d15924SDimitry Andric return createXCOFFObjectFile(Object, Binary::ID_XCOFF32);
200e6d15924SDimitry Andric case file_magic::xcoff_object_64:
201e6d15924SDimitry Andric return createXCOFFObjectFile(Object, Binary::ID_XCOFF64);
2027ab83427SDimitry Andric case file_magic::wasm_object:
203b915e9e0SDimitry Andric return createWasmObjectFile(Object);
204f8af5cf6SDimitry Andric }
205f8af5cf6SDimitry Andric llvm_unreachable("Unexpected Object File Type");
206cf099d11SDimitry Andric }
207cf099d11SDimitry Andric
20801095a5dSDimitry Andric Expected<OwningBinary<ObjectFile>>
createObjectFile(StringRef ObjectPath)20967c32a98SDimitry Andric ObjectFile::createObjectFile(StringRef ObjectPath) {
2105ca98fd9SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
2115ca98fd9SDimitry Andric MemoryBuffer::getFile(ObjectPath);
2125ca98fd9SDimitry Andric if (std::error_code EC = FileOrErr.getError())
21301095a5dSDimitry Andric return errorCodeToError(EC);
21467c32a98SDimitry Andric std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get());
21567c32a98SDimitry Andric
21601095a5dSDimitry Andric Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
21767c32a98SDimitry Andric createObjectFile(Buffer->getMemBufferRef());
218b915e9e0SDimitry Andric if (Error Err = ObjOrErr.takeError())
219b915e9e0SDimitry Andric return std::move(Err);
22067c32a98SDimitry Andric std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
22167c32a98SDimitry Andric
22267c32a98SDimitry Andric return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer));
223cf099d11SDimitry Andric }
224145449b1SDimitry Andric
isReflectionSectionStrippable(llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind) const225145449b1SDimitry Andric bool ObjectFile::isReflectionSectionStrippable(
226145449b1SDimitry Andric llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind)
227145449b1SDimitry Andric const {
228145449b1SDimitry Andric using llvm::binaryformat::Swift5ReflectionSectionKind;
229145449b1SDimitry Andric return ReflectionSectionKind == Swift5ReflectionSectionKind::fieldmd ||
230145449b1SDimitry Andric ReflectionSectionKind == Swift5ReflectionSectionKind::reflstr ||
231145449b1SDimitry Andric ReflectionSectionKind == Swift5ReflectionSectionKind::assocty;
232145449b1SDimitry Andric }
233