1//===-- llvm/MC/MCELFObjectWriter.h - ELF Object Writer ---------*- C++ -*-===//
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#ifndef LLVM_MC_MCELFOBJECTWRITER_H
11#define LLVM_MC_MCELFOBJECTWRITER_H
12
13#include "llvm/ADT/Triple.h"
14#include "llvm/Support/DataTypes.h"
15#include "llvm/Support/ELF.h"
16#include <vector>
17
18namespace llvm {
19class MCAssembler;
20class MCFixup;
21class MCFragment;
22class MCObjectWriter;
23class MCSymbol;
24class MCSymbolELF;
25class MCValue;
26class raw_pwrite_stream;
27
28struct ELFRelocationEntry {
29  uint64_t Offset; // Where is the relocation.
30  const MCSymbolELF *Symbol; // The symbol to relocate with.
31  unsigned Type;   // The type of the relocation.
32  uint64_t Addend; // The addend to use.
33
34  ELFRelocationEntry(uint64_t Offset, const MCSymbolELF *Symbol, unsigned Type,
35                     uint64_t Addend)
36      : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {}
37};
38
39class MCELFObjectTargetWriter {
40  const uint8_t OSABI;
41  const uint16_t EMachine;
42  const unsigned HasRelocationAddend : 1;
43  const unsigned Is64Bit : 1;
44  const unsigned IsN64 : 1;
45
46protected:
47
48  MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_,
49                          uint16_t EMachine_,  bool HasRelocationAddend,
50                          bool IsN64=false);
51
52public:
53  static uint8_t getOSABI(Triple::OSType OSType) {
54    switch (OSType) {
55      case Triple::CloudABI:
56        return ELF::ELFOSABI_CLOUDABI;
57      case Triple::PS4:
58      case Triple::FreeBSD:
59        return ELF::ELFOSABI_FREEBSD;
60      default:
61        return ELF::ELFOSABI_NONE;
62    }
63  }
64
65  virtual ~MCELFObjectTargetWriter() {}
66
67  virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
68                                bool IsPCRel) const = 0;
69
70  virtual bool needsRelocateWithSymbol(const MCSymbol &Sym,
71                                       unsigned Type) const;
72
73  virtual void sortRelocs(const MCAssembler &Asm,
74                          std::vector<ELFRelocationEntry> &Relocs);
75
76  /// \name Accessors
77  /// @{
78  uint8_t getOSABI() const { return OSABI; }
79  uint16_t getEMachine() const { return EMachine; }
80  bool hasRelocationAddend() const { return HasRelocationAddend; }
81  bool is64Bit() const { return Is64Bit; }
82  bool isN64() const { return IsN64; }
83  /// @}
84
85  // Instead of changing everyone's API we pack the N64 Type fields
86  // into the existing 32 bit data unsigned.
87#define R_TYPE_SHIFT 0
88#define R_TYPE_MASK 0xffffff00
89#define R_TYPE2_SHIFT 8
90#define R_TYPE2_MASK 0xffff00ff
91#define R_TYPE3_SHIFT 16
92#define R_TYPE3_MASK 0xff00ffff
93#define R_SSYM_SHIFT 24
94#define R_SSYM_MASK 0x00ffffff
95
96  // N64 relocation type accessors
97  uint8_t getRType(uint32_t Type) const {
98    return (unsigned)((Type >> R_TYPE_SHIFT) & 0xff);
99  }
100  uint8_t getRType2(uint32_t Type) const {
101    return (unsigned)((Type >> R_TYPE2_SHIFT) & 0xff);
102  }
103  uint8_t getRType3(uint32_t Type) const {
104    return (unsigned)((Type >> R_TYPE3_SHIFT) & 0xff);
105  }
106  uint8_t getRSsym(uint32_t Type) const {
107    return (unsigned)((Type >> R_SSYM_SHIFT) & 0xff);
108  }
109
110  // N64 relocation type setting
111  unsigned setRType(unsigned Value, unsigned Type) const {
112    return ((Type & R_TYPE_MASK) | ((Value & 0xff) << R_TYPE_SHIFT));
113  }
114  unsigned setRType2(unsigned Value, unsigned Type) const {
115    return (Type & R_TYPE2_MASK) | ((Value & 0xff) << R_TYPE2_SHIFT);
116  }
117  unsigned setRType3(unsigned Value, unsigned Type) const {
118    return (Type & R_TYPE3_MASK) | ((Value & 0xff) << R_TYPE3_SHIFT);
119  }
120  unsigned setRSsym(unsigned Value, unsigned Type) const {
121    return (Type & R_SSYM_MASK) | ((Value & 0xff) << R_SSYM_SHIFT);
122  }
123};
124
125/// \brief Construct a new ELF writer instance.
126///
127/// \param MOTW - The target specific ELF writer subclass.
128/// \param OS - The stream to write to.
129/// \returns The constructed object writer.
130MCObjectWriter *createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
131                                      raw_pwrite_stream &OS,
132                                      bool IsLittleEndian);
133} // End llvm namespace
134
135#endif
136