~pali/+junk/llvm-toolchain-3.7

« back to all changes in this revision

Viewing changes to include/llvm/MC/MCMachObjectWriter.h

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2015-07-15 17:51:08 UTC
  • Revision ID: package-import@ubuntu.com-20150715175108-l8mynwovkx4zx697
Tags: upstream-3.7~+rc2
ImportĀ upstreamĀ versionĀ 3.7~+rc2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===-- llvm/MC/MCMachObjectWriter.h - Mach 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_MCMACHOBJECTWRITER_H
 
11
#define LLVM_MC_MCMACHOBJECTWRITER_H
 
12
 
 
13
#include "llvm/ADT/DenseMap.h"
 
14
#include "llvm/ADT/SmallString.h"
 
15
#include "llvm/MC/MCExpr.h"
 
16
#include "llvm/MC/MCObjectWriter.h"
 
17
#include "llvm/MC/StringTableBuilder.h"
 
18
#include "llvm/Support/DataTypes.h"
 
19
#include "llvm/Support/MachO.h"
 
20
#include <vector>
 
21
 
 
22
namespace llvm {
 
23
 
 
24
class MachObjectWriter;
 
25
 
 
26
class MCMachObjectTargetWriter {
 
27
  const unsigned Is64Bit : 1;
 
28
  const uint32_t CPUType;
 
29
  const uint32_t CPUSubtype;
 
30
  unsigned LocalDifference_RIT;
 
31
 
 
32
protected:
 
33
  MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_,
 
34
                           uint32_t CPUSubtype_);
 
35
 
 
36
  void setLocalDifferenceRelocationType(unsigned Type) {
 
37
    LocalDifference_RIT = Type;
 
38
  }
 
39
 
 
40
public:
 
41
  virtual ~MCMachObjectTargetWriter();
 
42
 
 
43
  /// \name Lifetime Management
 
44
  /// @{
 
45
 
 
46
  virtual void reset() {}
 
47
 
 
48
  /// @}
 
49
 
 
50
  /// \name Accessors
 
51
  /// @{
 
52
 
 
53
  bool is64Bit() const { return Is64Bit; }
 
54
  uint32_t getCPUType() const { return CPUType; }
 
55
  uint32_t getCPUSubtype() const { return CPUSubtype; }
 
56
  unsigned getLocalDifferenceRelocationType() const {
 
57
    return LocalDifference_RIT;
 
58
  }
 
59
 
 
60
  /// @}
 
61
 
 
62
  /// \name API
 
63
  /// @{
 
64
 
 
65
  virtual void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
 
66
                                const MCAsmLayout &Layout,
 
67
                                const MCFragment *Fragment,
 
68
                                const MCFixup &Fixup, MCValue Target,
 
69
                                uint64_t &FixedValue) = 0;
 
70
 
 
71
  /// @}
 
72
};
 
73
 
 
74
class MachObjectWriter : public MCObjectWriter {
 
75
  /// Helper struct for containing some precomputed information on symbols.
 
76
  struct MachSymbolData {
 
77
    const MCSymbol *Symbol;
 
78
    uint64_t StringIndex;
 
79
    uint8_t SectionIndex;
 
80
 
 
81
    // Support lexicographic sorting.
 
82
    bool operator<(const MachSymbolData &RHS) const;
 
83
  };
 
84
 
 
85
  /// The target specific Mach-O writer instance.
 
86
  std::unique_ptr<MCMachObjectTargetWriter> TargetObjectWriter;
 
87
 
 
88
  /// \name Relocation Data
 
89
  /// @{
 
90
 
 
91
  struct RelAndSymbol {
 
92
    const MCSymbol *Sym;
 
93
    MachO::any_relocation_info MRE;
 
94
    RelAndSymbol(const MCSymbol *Sym, const MachO::any_relocation_info &MRE)
 
95
        : Sym(Sym), MRE(MRE) {}
 
96
  };
 
97
 
 
98
  llvm::DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations;
 
99
  llvm::DenseMap<const MCSection *, unsigned> IndirectSymBase;
 
100
 
 
101
  SectionAddrMap SectionAddress;
 
102
 
 
103
  /// @}
 
104
  /// \name Symbol Table Data
 
105
  /// @{
 
106
 
 
107
  StringTableBuilder StringTable;
 
108
  std::vector<MachSymbolData> LocalSymbolData;
 
109
  std::vector<MachSymbolData> ExternalSymbolData;
 
110
  std::vector<MachSymbolData> UndefinedSymbolData;
 
111
 
 
112
  /// @}
 
113
 
 
114
  MachSymbolData *findSymbolData(const MCSymbol &Sym);
 
115
 
 
116
public:
 
117
  MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_pwrite_stream &OS,
 
118
                   bool IsLittleEndian)
 
119
      : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {}
 
120
 
 
121
  const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const;
 
122
 
 
123
  /// \name Lifetime management Methods
 
124
  /// @{
 
125
 
 
126
  void reset() override;
 
127
 
 
128
  /// @}
 
129
 
 
130
  /// \name Utility Methods
 
131
  /// @{
 
132
 
 
133
  bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
 
134
 
 
135
  SectionAddrMap &getSectionAddressMap() { return SectionAddress; }
 
136
 
 
137
  uint64_t getSectionAddress(const MCSection *Sec) const {
 
138
    return SectionAddress.lookup(Sec);
 
139
  }
 
140
  uint64_t getSymbolAddress(const MCSymbol &S, const MCAsmLayout &Layout) const;
 
141
 
 
142
  uint64_t getFragmentAddress(const MCFragment *Fragment,
 
143
                              const MCAsmLayout &Layout) const;
 
144
 
 
145
  uint64_t getPaddingSize(const MCSection *SD, const MCAsmLayout &Layout) const;
 
146
 
 
147
  bool doesSymbolRequireExternRelocation(const MCSymbol &S);
 
148
 
 
149
  /// @}
 
150
 
 
151
  /// \name Target Writer Proxy Accessors
 
152
  /// @{
 
153
 
 
154
  bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
 
155
  bool isX86_64() const {
 
156
    uint32_t CPUType = TargetObjectWriter->getCPUType();
 
157
    return CPUType == MachO::CPU_TYPE_X86_64;
 
158
  }
 
159
 
 
160
  /// @}
 
161
 
 
162
  void writeHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
 
163
                   bool SubsectionsViaSymbols);
 
164
 
 
165
  /// Write a segment load command.
 
166
  ///
 
167
  /// \param NumSections The number of sections in this segment.
 
168
  /// \param SectionDataSize The total size of the sections.
 
169
  void writeSegmentLoadCommand(unsigned NumSections, uint64_t VMSize,
 
170
                               uint64_t SectionDataStartOffset,
 
171
                               uint64_t SectionDataSize);
 
172
 
 
173
  void writeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
 
174
                    const MCSection &Sec, uint64_t FileOffset,
 
175
                    uint64_t RelocationsStart, unsigned NumRelocations);
 
176
 
 
177
  void writeSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
 
178
                              uint32_t StringTableOffset,
 
179
                              uint32_t StringTableSize);
 
180
 
 
181
  void writeDysymtabLoadCommand(
 
182
      uint32_t FirstLocalSymbol, uint32_t NumLocalSymbols,
 
183
      uint32_t FirstExternalSymbol, uint32_t NumExternalSymbols,
 
184
      uint32_t FirstUndefinedSymbol, uint32_t NumUndefinedSymbols,
 
185
      uint32_t IndirectSymbolOffset, uint32_t NumIndirectSymbols);
 
186
 
 
187
  void writeNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
 
188
 
 
189
  void writeLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset,
 
190
                                uint32_t DataSize);
 
191
 
 
192
  void writeLinkerOptionsLoadCommand(const std::vector<std::string> &Options);
 
193
 
 
194
  // FIXME: We really need to improve the relocation validation. Basically, we
 
195
  // want to implement a separate computation which evaluates the relocation
 
196
  // entry as the linker would, and verifies that the resultant fixup value is
 
197
  // exactly what the encoder wanted. This will catch several classes of
 
198
  // problems:
 
199
  //
 
200
  //  - Relocation entry bugs, the two algorithms are unlikely to have the same
 
201
  //    exact bug.
 
202
  //
 
203
  //  - Relaxation issues, where we forget to relax something.
 
204
  //
 
205
  //  - Input errors, where something cannot be correctly encoded. 'as' allows
 
206
  //    these through in many cases.
 
207
 
 
208
  // Add a relocation to be output in the object file. At the time this is
 
209
  // called, the symbol indexes are not know, so if the relocation refers
 
210
  // to a symbol it should be passed as \p RelSymbol so that it can be updated
 
211
  // afterwards. If the relocation doesn't refer to a symbol, nullptr should be
 
212
  // used.
 
213
  void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec,
 
214
                     MachO::any_relocation_info &MRE) {
 
215
    RelAndSymbol P(RelSymbol, MRE);
 
216
    Relocations[Sec].push_back(P);
 
217
  }
 
218
 
 
219
  void recordScatteredRelocation(const MCAssembler &Asm,
 
220
                                 const MCAsmLayout &Layout,
 
221
                                 const MCFragment *Fragment,
 
222
                                 const MCFixup &Fixup, MCValue Target,
 
223
                                 unsigned Log2Size, uint64_t &FixedValue);
 
224
 
 
225
  void recordTLVPRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
 
226
                            const MCFragment *Fragment, const MCFixup &Fixup,
 
227
                            MCValue Target, uint64_t &FixedValue);
 
228
 
 
229
  void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
 
230
                        const MCFragment *Fragment, const MCFixup &Fixup,
 
231
                        MCValue Target, bool &IsPCRel,
 
232
                        uint64_t &FixedValue) override;
 
233
 
 
234
  void bindIndirectSymbols(MCAssembler &Asm);
 
235
 
 
236
  /// Compute the symbol table data.
 
237
  void computeSymbolTable(MCAssembler &Asm,
 
238
                          std::vector<MachSymbolData> &LocalSymbolData,
 
239
                          std::vector<MachSymbolData> &ExternalSymbolData,
 
240
                          std::vector<MachSymbolData> &UndefinedSymbolData);
 
241
 
 
242
  void computeSectionAddresses(const MCAssembler &Asm,
 
243
                               const MCAsmLayout &Layout);
 
244
 
 
245
  void executePostLayoutBinding(MCAssembler &Asm,
 
246
                                const MCAsmLayout &Layout) override;
 
247
 
 
248
  bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
 
249
                                              const MCSymbol &SymA,
 
250
                                              const MCFragment &FB, bool InSet,
 
251
                                              bool IsPCRel) const override;
 
252
 
 
253
  void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
 
254
};
 
255
 
 
256
/// Construct a new Mach-O writer instance.
 
257
///
 
258
/// This routine takes ownership of the target writer subclass.
 
259
///
 
260
/// \param MOTW - The target specific Mach-O writer subclass.
 
261
/// \param OS - The stream to write to.
 
262
/// \returns The constructed object writer.
 
263
MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW,
 
264
                                       raw_pwrite_stream &OS,
 
265
                                       bool IsLittleEndian);
 
266
 
 
267
} // End llvm namespace
 
268
 
 
269
#endif