brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · 20e6af1 Raw
201 lines · c
1//===- Target.h -------------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLD_MACHO_TARGET_H10#define LLD_MACHO_TARGET_H11 12#include "MachOStructs.h"13#include "Relocations.h"14 15#include "llvm/ADT/BitmaskEnum.h"16#include "llvm/BinaryFormat/MachO.h"17#include "llvm/Support/MathExtras.h"18#include "llvm/Support/MemoryBuffer.h"19 20#include <cstddef>21#include <cstdint>22 23#include "mach-o/compact_unwind_encoding.h"24 25namespace lld::macho {26LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();27 28class Symbol;29class Defined;30class DylibSymbol;31class InputSection;32class ObjFile;33 34static_assert(static_cast<uint32_t>(UNWIND_X86_64_MODE_MASK) ==35                  static_cast<uint32_t>(UNWIND_X86_MODE_MASK) &&36              static_cast<uint32_t>(UNWIND_ARM64_MODE_MASK) ==37                  static_cast<uint32_t>(UNWIND_X86_64_MODE_MASK));38 39// Since the mode masks have the same value on all targets, define40// a common one for convenience.41constexpr uint32_t UNWIND_MODE_MASK = UNWIND_X86_64_MODE_MASK;42 43class TargetInfo {44public:45  template <class LP> TargetInfo(LP) {46    // Having these values available in TargetInfo allows us to access them47    // without having to resort to templates.48    magic = LP::magic;49    pageZeroSize = LP::pageZeroSize;50    headerSize = sizeof(typename LP::mach_header);51    wordSize = LP::wordSize;52    p2WordSize = llvm::ConstantLog2<LP::wordSize>();53  }54 55  virtual ~TargetInfo() = default;56 57  // Validate the relocation structure and get its addend.58  virtual int64_t59  getEmbeddedAddend(llvm::MemoryBufferRef, uint64_t offset,60                    const llvm::MachO::relocation_info) const = 0;61  virtual void relocateOne(uint8_t *loc, const Reloc &, uint64_t va,62                           uint64_t relocVA) const = 0;63 64  // Write code for lazy binding. See the comments on StubsSection for more65  // details.66  virtual void writeStub(uint8_t *buf, const Symbol &,67                         uint64_t pointerVA) const = 0;68  virtual void writeStubHelperHeader(uint8_t *buf) const = 0;69  virtual void writeStubHelperEntry(uint8_t *buf, const Symbol &,70                                    uint64_t entryAddr) const = 0;71 72  virtual void writeObjCMsgSendStub(uint8_t *buf, Symbol *sym,73                                    uint64_t stubsAddr, uint64_t &stubOffset,74                                    uint64_t selrefVA,75                                    Symbol *objcMsgSend) const = 0;76 77  // Init 'thunk' so that it be a direct jump to 'branchTarget'.78  virtual void initICFSafeThunkBody(InputSection *thunk,79                                    Symbol *targetSym) const {80    llvm_unreachable("target does not support ICF safe thunks");81  }82 83  // Given a thunk for which `initICFSafeThunkBody` was called, return the84  // branchTarget it was initialized with.85  virtual Symbol *getThunkBranchTarget(InputSection *thunk) const {86    llvm_unreachable("target does not support ICF safe thunks");87  }88 89  virtual uint32_t getICFSafeThunkSize() const {90    llvm_unreachable("target does not support ICF safe thunks");91  }92 93  // Symbols may be referenced via either the GOT or the stubs section,94  // depending on the relocation type. prepareSymbolRelocation() will set up the95  // GOT/stubs entries, and resolveSymbolVA() will return the addresses of those96  // entries. resolveSymbolVA() may also relax the target instructions to save97  // on a level of address indirection.98  virtual void relaxGotLoad(uint8_t *loc, uint8_t type) const = 0;99 100  virtual uint64_t getPageSize() const = 0;101 102  virtual void populateThunk(InputSection *thunk, Symbol *funcSym) {103    llvm_unreachable("target does not use thunks");104  }105 106  const RelocAttrs &getRelocAttrs(uint8_t type) const {107    assert(type < relocAttrs.size() && "invalid relocation type");108    if (type >= relocAttrs.size())109      return invalidRelocAttrs;110    return relocAttrs[type];111  }112 113  bool hasAttr(uint8_t type, RelocAttrBits bit) const {114    return getRelocAttrs(type).hasAttr(bit);115  }116 117  bool usesThunks() const { return thunkSize > 0; }118 119  // For now, handleDtraceReloc only implements -no_dtrace_dof, and ensures120  // that the linking would not fail even when there are user-provided dtrace121  // symbols. However, unlike ld64, lld currently does not emit __dof sections.122  virtual void handleDtraceReloc(const Symbol *sym, const Reloc &r,123                                 uint8_t *loc) const {124    llvm_unreachable("Unsupported architecture for dtrace symbols");125  }126 127  uint32_t magic;128  llvm::MachO::CPUType cpuType;129  uint32_t cpuSubtype;130 131  uint64_t pageZeroSize;132  size_t headerSize;133  size_t stubSize;134  size_t stubHelperHeaderSize;135  size_t stubHelperEntrySize;136  size_t objcStubsFastSize;137  size_t objcStubsSmallSize;138  size_t objcStubsFastAlignment;139  size_t objcStubsSmallAlignment;140  uint8_t p2WordSize;141  size_t wordSize;142 143  size_t thunkSize = 0;144  uint64_t forwardBranchRange = 0;145  uint64_t backwardBranchRange = 0;146 147  uint32_t modeDwarfEncoding;148  uint8_t subtractorRelocType;149  uint8_t unsignedRelocType;150 151  llvm::ArrayRef<RelocAttrs> relocAttrs;152 153  // We contrive this value as sufficiently far from any valid address that it154  // will always be out-of-range for any architecture. UINT64_MAX is not a155  // good choice because it is (a) only 1 away from wrapping to 0, and (b) the156  // tombstone value for DenseMap<> and caused weird assertions for me.157  static constexpr uint64_t outOfRangeVA = 0xfull << 60;158};159 160TargetInfo *createX86_64TargetInfo();161TargetInfo *createARM64TargetInfo();162TargetInfo *createARM64_32TargetInfo();163 164struct LP64 {165  using mach_header = llvm::MachO::mach_header_64;166  using nlist = structs::nlist_64;167  using segment_command = llvm::MachO::segment_command_64;168  using section = llvm::MachO::section_64;169  using encryption_info_command = llvm::MachO::encryption_info_command_64;170 171  static constexpr uint32_t magic = llvm::MachO::MH_MAGIC_64;172  static constexpr uint32_t segmentLCType = llvm::MachO::LC_SEGMENT_64;173  static constexpr uint32_t encryptionInfoLCType =174      llvm::MachO::LC_ENCRYPTION_INFO_64;175 176  static constexpr uint64_t pageZeroSize = 1ull << 32;177  static constexpr size_t wordSize = 8;178};179 180struct ILP32 {181  using mach_header = llvm::MachO::mach_header;182  using nlist = structs::nlist;183  using segment_command = llvm::MachO::segment_command;184  using section = llvm::MachO::section;185  using encryption_info_command = llvm::MachO::encryption_info_command;186 187  static constexpr uint32_t magic = llvm::MachO::MH_MAGIC;188  static constexpr uint32_t segmentLCType = llvm::MachO::LC_SEGMENT;189  static constexpr uint32_t encryptionInfoLCType =190      llvm::MachO::LC_ENCRYPTION_INFO;191 192  static constexpr uint64_t pageZeroSize = 1ull << 12;193  static constexpr size_t wordSize = 4;194};195 196extern TargetInfo *target;197 198} // namespace lld::macho199 200#endif201