summaryrefslogtreecommitdiff
path: root/lib/CodeGen/ELFWriter.h
blob: 6f7fbace8abaa83298a8bb805187dbc39da30a90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
//===-- ELFWriter.h - Target-independent ELF writer support -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the ELFWriter class.
//
//===----------------------------------------------------------------------===//

#ifndef ELFWRITER_H
#define ELFWRITER_H

#include "llvm/ADT/SetVector.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include <map>

namespace llvm {
  class BinaryObject;
  class Constant;
  class ConstantInt;
  class ConstantStruct;
  class ELFCodeEmitter;
  class ELFRelocation;
  class ELFSection;
  struct ELFSym;
  class GlobalVariable;
  class JITDebugRegisterer;
  class Mangler;
  class MachineCodeEmitter;
  class MachineConstantPoolEntry;
  class ObjectCodeEmitter;
  class MCAsmInfo;
  class TargetELFWriterInfo;
  class TargetLoweringObjectFile;
  class raw_ostream;
  class SectionKind;
  class MCContext;
  class TargetMachine;

  typedef std::vector<ELFSym*>::iterator ELFSymIter;
  typedef std::vector<ELFSection*>::iterator ELFSectionIter;
  typedef SetVector<const GlobalValue*>::const_iterator PendingGblsIter;
  typedef SetVector<const char *>::const_iterator PendingExtsIter;
  typedef std::pair<const Constant *, int64_t> CstExprResTy;

  /// ELFWriter - This class implements the common target-independent code for
  /// writing ELF files.  Targets should derive a class from this to
  /// parameterize the output format.
  ///
  class ELFWriter : public MachineFunctionPass {
    friend class ELFCodeEmitter;
    friend class JITDebugRegisterer;
  public:
    static char ID;

    /// Return the ELFCodeEmitter as an instance of ObjectCodeEmitter
    ObjectCodeEmitter *getObjectCodeEmitter() {
      return reinterpret_cast<ObjectCodeEmitter*>(ElfCE);
    }

    ELFWriter(raw_ostream &O, TargetMachine &TM);
    ~ELFWriter();

  protected:
    /// Output stream to send the resultant object file to.
    raw_ostream &O;

    /// Target machine description.
    TargetMachine &TM;

    /// Context object for machine code objects.
    MCContext &OutContext;
    
    /// Target Elf Writer description.
    const TargetELFWriterInfo *TEW;

    /// Mang - The object used to perform name mangling for this module.
    Mangler *Mang;

    /// MCE - The MachineCodeEmitter object that we are exposing to emit machine
    /// code for functions to the .o file.
    ELFCodeEmitter *ElfCE;

    /// TLOF - Target Lowering Object File, provide section names for globals 
    /// and other object file specific stuff
    const TargetLoweringObjectFile &TLOF;

    /// MAI - Target Asm Info, provide information about section names for
    /// globals and other target specific stuff.
    const MCAsmInfo *MAI;

    //===------------------------------------------------------------------===//
    // Properties inferred automatically from the target machine.
    //===------------------------------------------------------------------===//

    /// is64Bit/isLittleEndian - This information is inferred from the target
    /// machine directly, indicating whether to emit a 32- or 64-bit ELF file.
    bool is64Bit, isLittleEndian;

    /// doInitialization - Emit the file header and all of the global variables
    /// for the module to the ELF file.
    bool doInitialization(Module &M);
    bool runOnMachineFunction(MachineFunction &MF);

    /// doFinalization - Now that the module has been completely processed, emit
    /// the ELF file to 'O'.
    bool doFinalization(Module &M);

  private:
    /// Blob containing the Elf header
    BinaryObject ElfHdr;

    /// SectionList - This is the list of sections that we have emitted to the
    /// file. Once the file has been completely built, the section header table
    /// is constructed from this info.
    std::vector<ELFSection*> SectionList;
    unsigned NumSections;   // Always = SectionList.size()

    /// SectionLookup - This is a mapping from section name to section number in
    /// the SectionList. Used to quickly gather the Section Index from MAI names
    std::map<std::string, ELFSection*> SectionLookup;

    /// PendingGlobals - Globals not processed as symbols yet.
    SetVector<const GlobalValue*> PendingGlobals;

    /// GblSymLookup - This is a mapping from global value to a symbol index
    /// in the symbol table or private symbols list. This is useful since reloc
    /// symbol references must be quickly mapped to their indices on the lists.
    std::map<const GlobalValue*, uint32_t> GblSymLookup;

    /// PendingExternals - Externals not processed as symbols yet.
    SetVector<const char *> PendingExternals;

    /// ExtSymLookup - This is a mapping from externals to a symbol index
    /// in the symbol table list. This is useful since reloc symbol references
    /// must be quickly mapped to their symbol table indices.
    std::map<const char *, uint32_t> ExtSymLookup;

    /// SymbolList - This is the list of symbols emitted to the symbol table.
    /// When the SymbolList is finally built, local symbols must be placed in
    /// the beginning while non-locals at the end.
    std::vector<ELFSym*> SymbolList;

    /// PrivateSyms - Record private symbols, every symbol here must never be
    /// present in the SymbolList.
    std::vector<ELFSym*> PrivateSyms;

    /// getSection - Return the section with the specified name, creating a new
    /// section if one does not already exist.
    ELFSection &getSection(const std::string &Name, unsigned Type,
                           unsigned Flags = 0, unsigned Align = 0) {
      ELFSection *&SN = SectionLookup[Name];
      if (SN) return *SN;

      SectionList.push_back(new ELFSection(Name, isLittleEndian, is64Bit));
      SN = SectionList.back();
      SN->SectionIdx = NumSections++;
      SN->Type = Type;
      SN->Flags = Flags;
      SN->Link = ELF::SHN_UNDEF;
      SN->Align = Align;
      return *SN;
    }

    ELFSection &getNonExecStackSection() {
      return getSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0, 1);
    }

    ELFSection &getSymbolTableSection() {
      return getSection(".symtab", ELF::SHT_SYMTAB, 0);
    }

    ELFSection &getStringTableSection() {
      return getSection(".strtab", ELF::SHT_STRTAB, 0, 1);
    }

    ELFSection &getSectionHeaderStringTableSection() {
      return getSection(".shstrtab", ELF::SHT_STRTAB, 0, 1);
    }

    ELFSection &getNullSection() {
      return getSection("", ELF::SHT_NULL, 0);
    }

    ELFSection &getDataSection();
    ELFSection &getBSSSection();
    ELFSection &getCtorSection();
    ELFSection &getDtorSection();
    ELFSection &getJumpTableSection();
    ELFSection &getConstantPoolSection(MachineConstantPoolEntry &CPE);
    ELFSection &getTextSection(const Function *F);
    ELFSection &getRelocSection(ELFSection &S);

    // Helpers for obtaining ELF specific info.
    unsigned getGlobalELFBinding(const GlobalValue *GV);
    unsigned getGlobalELFType(const GlobalValue *GV);
    unsigned getGlobalELFVisibility(const GlobalValue *GV);

    // AddPendingGlobalSymbol - Add a global to be processed and to
    // the global symbol lookup, use a zero index because the table
    // index will be determined later.
    void AddPendingGlobalSymbol(const GlobalValue *GV, 
                                bool AddToLookup = false);
    
    // AddPendingExternalSymbol - Add the external to be processed
    // and to the external symbol lookup, use a zero index because
    // the symbol table index will be determined later.
    void AddPendingExternalSymbol(const char *External);

    // AddToSymbolList - Update the symbol lookup and If the symbol is 
    // private add it to PrivateSyms list, otherwise to SymbolList. 
    void AddToSymbolList(ELFSym *GblSym);

    // As we complete the ELF file, we need to update fields in the ELF header
    // (e.g. the location of the section table).  These members keep track of
    // the offset in ELFHeader of these various pieces to update and other
    // locations in the file.
    unsigned ELFHdr_e_shoff_Offset;     // e_shoff    in ELF header.
    unsigned ELFHdr_e_shstrndx_Offset;  // e_shstrndx in ELF header.
    unsigned ELFHdr_e_shnum_Offset;     // e_shnum    in ELF header.

  private:
    void EmitGlobal(const GlobalValue *GV);
    void EmitGlobalConstant(const Constant *C, ELFSection &GblS);
    void EmitGlobalConstantStruct(const ConstantStruct *CVS,
                                  ELFSection &GblS);
    void EmitGlobalConstantLargeInt(const ConstantInt *CI, ELFSection &S);
    void EmitGlobalDataRelocation(const GlobalValue *GV, unsigned Size, 
                                  ELFSection &GblS, int64_t Offset = 0);
    bool EmitSpecialLLVMGlobal(const GlobalVariable *GV);
    void EmitXXStructorList(const Constant *List, ELFSection &Xtor);
    void EmitRelocations();
    void EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel, bool HasRelA);
    void EmitSectionHeader(BinaryObject &SHdrTab, const ELFSection &SHdr);
    void EmitSectionTableStringTable();
    void EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym);
    void EmitSymbolTable();
    void EmitStringTable(const std::string &ModuleName);
    void OutputSectionsAndSectionTable();
    void RelocateField(BinaryObject &BO, uint32_t Offset, int64_t Value,
                       unsigned Size);
    unsigned SortSymbols();
    CstExprResTy ResolveConstantExpr(const Constant *CV);
  };
}

#endif