1218885Sdim//===-- llvm/MC/MCELFObjectWriter.h - ELF Object Writer ---------*- C++ -*-===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim
10218885Sdim#ifndef LLVM_MC_MCELFOBJECTWRITER_H
11218885Sdim#define LLVM_MC_MCELFOBJECTWRITER_H
12218885Sdim
13234353Sdim#include "llvm/ADT/Triple.h"
14218885Sdim#include "llvm/Support/DataTypes.h"
15234353Sdim#include "llvm/Support/ELF.h"
16234353Sdim#include <vector>
17218885Sdim
18218885Sdimnamespace llvm {
19234353Sdimclass MCAssembler;
20234353Sdimclass MCFixup;
21234353Sdimclass MCFragment;
22234353Sdimclass MCObjectWriter;
23234353Sdimclass MCSymbol;
24234353Sdimclass MCValue;
25234353Sdim
26234353Sdim/// @name Relocation Data
27234353Sdim/// @{
28234353Sdim
29234353Sdimstruct ELFRelocationEntry {
30234353Sdim  // Make these big enough for both 32-bit and 64-bit
31234353Sdim  uint64_t r_offset;
32234353Sdim  int Index;
33234353Sdim  unsigned Type;
34234353Sdim  const MCSymbol *Symbol;
35234353Sdim  uint64_t r_addend;
36234353Sdim  const MCFixup *Fixup;
37234353Sdim
38234353Sdim  ELFRelocationEntry()
39234353Sdim    : r_offset(0), Index(0), Type(0), Symbol(0), r_addend(0), Fixup(0) {}
40234353Sdim
41234353Sdim  ELFRelocationEntry(uint64_t RelocOffset, int Idx, unsigned RelType,
42234353Sdim                     const MCSymbol *Sym, uint64_t Addend, const MCFixup &Fixup)
43234353Sdim    : r_offset(RelocOffset), Index(Idx), Type(RelType), Symbol(Sym),
44234353Sdim      r_addend(Addend), Fixup(&Fixup) {}
45234353Sdim};
46234353Sdim
47218885Sdimclass MCELFObjectTargetWriter {
48234353Sdim  const uint8_t OSABI;
49218885Sdim  const uint16_t EMachine;
50218885Sdim  const unsigned HasRelocationAddend : 1;
51218885Sdim  const unsigned Is64Bit : 1;
52239462Sdim  const unsigned IsN64 : 1;
53234353Sdim
54218885Sdimprotected:
55234353Sdim
56234353Sdim  MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_,
57239462Sdim                          uint16_t EMachine_,  bool HasRelocationAddend,
58239462Sdim                          bool IsN64=false);
59218885Sdim
60218885Sdimpublic:
61234353Sdim  static uint8_t getOSABI(Triple::OSType OSType) {
62234353Sdim    switch (OSType) {
63234353Sdim      case Triple::FreeBSD:
64234353Sdim        return ELF::ELFOSABI_FREEBSD;
65234353Sdim      case Triple::Linux:
66234353Sdim        return ELF::ELFOSABI_LINUX;
67234353Sdim      default:
68234353Sdim        return ELF::ELFOSABI_NONE;
69234353Sdim    }
70234353Sdim  }
71218885Sdim
72234353Sdim  virtual ~MCELFObjectTargetWriter() {}
73234353Sdim
74234353Sdim  virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
75234353Sdim                                bool IsPCRel, bool IsRelocWithSymbol,
76234353Sdim                                int64_t Addend) const = 0;
77234353Sdim  virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
78234353Sdim                                         const MCValue &Target,
79234353Sdim                                         const MCFragment &F,
80234353Sdim                                         const MCFixup &Fixup,
81234353Sdim                                         bool IsPCRel) const;
82243830Sdim  virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target,
83243830Sdim                                                  const MCFixup &Fixup,
84243830Sdim                                                  bool IsPCRel) const;
85234353Sdim
86234353Sdim  virtual void sortRelocs(const MCAssembler &Asm,
87234353Sdim                          std::vector<ELFRelocationEntry> &Relocs);
88234353Sdim
89218885Sdim  /// @name Accessors
90218885Sdim  /// @{
91243830Sdim  uint8_t getOSABI() const { return OSABI; }
92243830Sdim  uint16_t getEMachine() const { return EMachine; }
93243830Sdim  bool hasRelocationAddend() const { return HasRelocationAddend; }
94234353Sdim  bool is64Bit() const { return Is64Bit; }
95239462Sdim  bool isN64() const { return IsN64; }
96218885Sdim  /// @}
97239462Sdim
98239462Sdim  // Instead of changing everyone's API we pack the N64 Type fields
99239462Sdim  // into the existing 32 bit data unsigned.
100239462Sdim#define R_TYPE_SHIFT 0
101239462Sdim#define R_TYPE_MASK 0xffffff00
102239462Sdim#define R_TYPE2_SHIFT 8
103239462Sdim#define R_TYPE2_MASK 0xffff00ff
104239462Sdim#define R_TYPE3_SHIFT 16
105239462Sdim#define R_TYPE3_MASK 0xff00ffff
106239462Sdim#define R_SSYM_SHIFT 24
107239462Sdim#define R_SSYM_MASK 0x00ffffff
108239462Sdim
109239462Sdim  // N64 relocation type accessors
110239462Sdim  unsigned getRType(uint32_t Type) const {
111239462Sdim    return (unsigned)((Type >> R_TYPE_SHIFT) & 0xff);
112239462Sdim  }
113239462Sdim  unsigned getRType2(uint32_t Type) const {
114239462Sdim    return (unsigned)((Type >> R_TYPE2_SHIFT) & 0xff);
115239462Sdim  }
116239462Sdim  unsigned getRType3(uint32_t Type) const {
117239462Sdim    return (unsigned)((Type >> R_TYPE3_SHIFT) & 0xff);
118239462Sdim  }
119239462Sdim  unsigned getRSsym(uint32_t Type) const {
120239462Sdim    return (unsigned)((Type >> R_SSYM_SHIFT) & 0xff);
121239462Sdim  }
122239462Sdim
123239462Sdim  // N64 relocation type setting
124239462Sdim  unsigned setRType(unsigned Value, unsigned Type) const {
125239462Sdim    return ((Type & R_TYPE_MASK) | ((Value & 0xff) << R_TYPE_SHIFT));
126239462Sdim  }
127239462Sdim  unsigned setRType2(unsigned Value, unsigned Type) const {
128239462Sdim    return (Type & R_TYPE2_MASK) | ((Value & 0xff) << R_TYPE2_SHIFT);
129239462Sdim  }
130239462Sdim  unsigned setRType3(unsigned Value, unsigned Type) const {
131239462Sdim    return (Type & R_TYPE3_MASK) | ((Value & 0xff) << R_TYPE3_SHIFT);
132239462Sdim  }
133239462Sdim  unsigned setRSsym(unsigned Value, unsigned Type) const {
134239462Sdim    return (Type & R_SSYM_MASK) | ((Value & 0xff) << R_SSYM_SHIFT);
135239462Sdim  }
136218885Sdim};
137218885Sdim
138218885Sdim/// \brief Construct a new ELF writer instance.
139218885Sdim///
140218885Sdim/// \param MOTW - The target specific ELF writer subclass.
141218885Sdim/// \param OS - The stream to write to.
142218885Sdim/// \returns The constructed object writer.
143218885SdimMCObjectWriter *createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
144218885Sdim                                      raw_ostream &OS, bool IsLittleEndian);
145218885Sdim} // End llvm namespace
146218885Sdim
147218885Sdim#endif
148