1321369Sdim//===- ObjectFile.cpp - File format independent object file ---------------===//
2218885Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6218885Sdim//
7218885Sdim//===----------------------------------------------------------------------===//
8218885Sdim//
9218885Sdim// This file defines a file format independent ObjectFile class.
10218885Sdim//
11218885Sdim//===----------------------------------------------------------------------===//
12218885Sdim
13314564Sdim#include "llvm/Object/ObjectFile.h"
14321369Sdim#include "llvm/ADT/StringRef.h"
15321369Sdim#include "llvm/BinaryFormat/Magic.h"
16321369Sdim#include "llvm/Object/Binary.h"
17280031Sdim#include "llvm/Object/COFF.h"
18321369Sdim#include "llvm/Object/Error.h"
19280031Sdim#include "llvm/Object/MachO.h"
20314564Sdim#include "llvm/Object/Wasm.h"
21321369Sdim#include "llvm/Support/Error.h"
22218885Sdim#include "llvm/Support/ErrorHandling.h"
23321369Sdim#include "llvm/Support/ErrorOr.h"
24261991Sdim#include "llvm/Support/FileSystem.h"
25218885Sdim#include "llvm/Support/MemoryBuffer.h"
26276479Sdim#include "llvm/Support/raw_ostream.h"
27321369Sdim#include <algorithm>
28321369Sdim#include <cstdint>
29321369Sdim#include <memory>
30276479Sdim#include <system_error>
31218885Sdim
32218885Sdimusing namespace llvm;
33218885Sdimusing namespace object;
34218885Sdim
35360784Sdimraw_ostream &object::operator<<(raw_ostream &OS, const SectionedAddress &Addr) {
36360784Sdim  OS << "SectionedAddress{" << format_hex(Addr.Address, 10);
37360784Sdim  if (Addr.SectionIndex != SectionedAddress::UndefSection)
38360784Sdim    OS << ", " << Addr.SectionIndex;
39360784Sdim  return OS << "}";
40360784Sdim}
41360784Sdim
42321369Sdimvoid ObjectFile::anchor() {}
43234353Sdim
44280031SdimObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source)
45280031Sdim    : SymbolicFile(Type, Source) {}
46276479Sdim
47288943Sdimbool SectionRef::containsSymbol(SymbolRef S) const {
48309124Sdim  Expected<section_iterator> SymSec = S.getSection();
49309124Sdim  if (!SymSec) {
50309124Sdim    // TODO: Actually report errors helpfully.
51309124Sdim    consumeError(SymSec.takeError());
52288943Sdim    return false;
53309124Sdim  }
54296417Sdim  return *this == **SymSec;
55288943Sdim}
56288943Sdim
57288943Sdimuint64_t ObjectFile::getSymbolValue(DataRefImpl Ref) const {
58288943Sdim  uint32_t Flags = getSymbolFlags(Ref);
59288943Sdim  if (Flags & SymbolRef::SF_Undefined)
60288943Sdim    return 0;
61288943Sdim  if (Flags & SymbolRef::SF_Common)
62288943Sdim    return getCommonSymbolSize(Ref);
63288943Sdim  return getSymbolValueImpl(Ref);
64288943Sdim}
65288943Sdim
66353358SdimError ObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const {
67309124Sdim  Expected<StringRef> Name = getSymbolName(Symb);
68309124Sdim  if (!Name)
69353358Sdim    return Name.takeError();
70288943Sdim  OS << *Name;
71353358Sdim  return Error::success();
72218885Sdim}
73218885Sdim
74288943Sdimuint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; }
75251662Sdim
76309124Sdimbool ObjectFile::isSectionBitcode(DataRefImpl Sec) const {
77360784Sdim  Expected<StringRef> NameOrErr = getSectionName(Sec);
78360784Sdim  if (NameOrErr)
79353358Sdim    return *NameOrErr == ".llvmbc";
80360784Sdim  consumeError(NameOrErr.takeError());
81309124Sdim  return false;
82309124Sdim}
83309124Sdim
84327952Sdimbool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; }
85327952Sdim
86344779Sdimbool ObjectFile::isBerkeleyText(DataRefImpl Sec) const {
87344779Sdim  return isSectionText(Sec);
88344779Sdim}
89344779Sdim
90344779Sdimbool ObjectFile::isBerkeleyData(DataRefImpl Sec) const {
91344779Sdim  return isSectionData(Sec);
92344779Sdim}
93344779Sdim
94360784SdimExpected<section_iterator>
95360784SdimObjectFile::getRelocatedSection(DataRefImpl Sec) const {
96261991Sdim  return section_iterator(SectionRef(Sec, this));
97261991Sdim}
98261991Sdim
99327952SdimTriple ObjectFile::makeTriple() const {
100327952Sdim  Triple TheTriple;
101327952Sdim  auto Arch = getArch();
102327952Sdim  TheTriple.setArch(Triple::ArchType(Arch));
103327952Sdim
104327952Sdim  // For ARM targets, try to use the build attributes to build determine
105327952Sdim  // the build target. Target features are also added, but later during
106327952Sdim  // disassembly.
107327952Sdim  if (Arch == Triple::arm || Arch == Triple::armeb)
108327952Sdim    setARMSubArch(TheTriple);
109327952Sdim
110327952Sdim  // TheTriple defaults to ELF, and COFF doesn't have an environment:
111327952Sdim  // the best we can do here is indicate that it is mach-o.
112327952Sdim  if (isMachO())
113327952Sdim    TheTriple.setObjectFormat(Triple::MachO);
114327952Sdim
115327952Sdim  if (isCOFF()) {
116360784Sdim    const auto COFFObj = cast<COFFObjectFile>(this);
117327952Sdim    if (COFFObj->getArch() == Triple::thumb)
118327952Sdim      TheTriple.setTriple("thumbv7-windows");
119327952Sdim  }
120327952Sdim
121327952Sdim  return TheTriple;
122327952Sdim}
123327952Sdim
124309124SdimExpected<std::unique_ptr<ObjectFile>>
125321369SdimObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) {
126280031Sdim  StringRef Data = Object.getBuffer();
127321369Sdim  if (Type == file_magic::unknown)
128321369Sdim    Type = identify_magic(Data);
129261991Sdim
130261991Sdim  switch (Type) {
131321369Sdim  case file_magic::unknown:
132321369Sdim  case file_magic::bitcode:
133321369Sdim  case file_magic::coff_cl_gl_object:
134321369Sdim  case file_magic::archive:
135321369Sdim  case file_magic::macho_universal_binary:
136321369Sdim  case file_magic::windows_resource:
137341825Sdim  case file_magic::pdb:
138353358Sdim  case file_magic::minidump:
139309124Sdim    return errorCodeToError(object_error::invalid_file_type);
140360784Sdim  case file_magic::tapi_file:
141360784Sdim    return errorCodeToError(object_error::invalid_file_type);
142321369Sdim  case file_magic::elf:
143321369Sdim  case file_magic::elf_relocatable:
144321369Sdim  case file_magic::elf_executable:
145321369Sdim  case file_magic::elf_shared_object:
146321369Sdim  case file_magic::elf_core:
147327952Sdim    return createELFObjectFile(Object);
148321369Sdim  case file_magic::macho_object:
149321369Sdim  case file_magic::macho_executable:
150321369Sdim  case file_magic::macho_fixed_virtual_memory_shared_lib:
151321369Sdim  case file_magic::macho_core:
152321369Sdim  case file_magic::macho_preload_executable:
153321369Sdim  case file_magic::macho_dynamically_linked_shared_lib:
154321369Sdim  case file_magic::macho_dynamic_linker:
155321369Sdim  case file_magic::macho_bundle:
156321369Sdim  case file_magic::macho_dynamically_linked_shared_lib_stub:
157321369Sdim  case file_magic::macho_dsym_companion:
158321369Sdim  case file_magic::macho_kext_bundle:
159261991Sdim    return createMachOObjectFile(Object);
160321369Sdim  case file_magic::coff_object:
161321369Sdim  case file_magic::coff_import_library:
162321369Sdim  case file_magic::pecoff_executable:
163327952Sdim    return createCOFFObjectFile(Object);
164353358Sdim  case file_magic::xcoff_object_32:
165353358Sdim    return createXCOFFObjectFile(Object, Binary::ID_XCOFF32);
166353358Sdim  case file_magic::xcoff_object_64:
167353358Sdim    return createXCOFFObjectFile(Object, Binary::ID_XCOFF64);
168321369Sdim  case file_magic::wasm_object:
169314564Sdim    return createWasmObjectFile(Object);
170261991Sdim  }
171261991Sdim  llvm_unreachable("Unexpected Object File Type");
172218885Sdim}
173218885Sdim
174309124SdimExpected<OwningBinary<ObjectFile>>
175280031SdimObjectFile::createObjectFile(StringRef ObjectPath) {
176276479Sdim  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
177276479Sdim      MemoryBuffer::getFile(ObjectPath);
178276479Sdim  if (std::error_code EC = FileOrErr.getError())
179309124Sdim    return errorCodeToError(EC);
180280031Sdim  std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get());
181280031Sdim
182309124Sdim  Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
183280031Sdim      createObjectFile(Buffer->getMemBufferRef());
184314564Sdim  if (Error Err = ObjOrErr.takeError())
185314564Sdim    return std::move(Err);
186280031Sdim  std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
187280031Sdim
188280031Sdim  return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer));
189218885Sdim}
190