summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/ELFWriter.h
blob: bab118c6e356820c40763f37cd6abb2145e7e4b5 (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 <list>
#include <map>

namespace llvm {
  class BinaryObject;
  class Constant;
  class ConstantStruct;
  class ELFCodeEmitter;
  class GlobalVariable;
  class Mangler;
  class MachineCodeEmitter;
  class TargetAsmInfo;
  class TargetELFWriterInfo;
  class raw_ostream;
  class ELFSection;
  class ELFSym;
  class ELFRelocation;

  /// 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;
  public:
    static char ID;

    MachineCodeEmitter &getMachineCodeEmitter() const {
      return *(MachineCodeEmitter*)MCE;
    }

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

    typedef std::vector<unsigned char> DataBuffer;

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

    /// Target machine description.
    TargetMachine &TM;

    /// 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 *MCE;

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

    //===------------------------------------------------------------------===//
    // 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::list<ELFSection> SectionList;
    unsigned NumSections;   // Always = SectionList.size()

    /// SectionLookup - This is a mapping from section name to section number in
    /// the SectionList.
    std::map<std::string, ELFSection*> SectionLookup;

    /// GblSymLookup - This is a mapping from global value to a symbol index
    /// in the symbol table. This is useful since relocations symbol references
    /// must be quickly mapped to a symbol table index
    std::map<const GlobalValue*, uint32_t> GblSymLookup;

    /// SymbolList - This is the list of symbols emitted to the symbol table
    /// Local symbols go to the front and Globals to the back.
    std::list<ELFSym> SymbolList;

    /// PendingGlobals - List of externally defined symbols that we have been
    /// asked to emit, but have not seen a reference to.  When a reference
    /// is seen, the symbol will move from this list to the SymbolList.
    SetVector<GlobalValue*> PendingGlobals;

    // Remove tab from section name prefix. This is necessary becase TAI 
    // sometimes return a section name prefixed with a "\t" char. This is
    // a little bit dirty. FIXME: find a better approach, maybe add more
    // methods to TAI to get the clean name?
    void fixNameForSection(std::string &Name) {
      size_t Pos = Name.find("\t");
      if (Pos != std::string::npos)
        Name.erase(Pos, 1);

      Pos = Name.find(".section ");
      if (Pos != std::string::npos)
        Name.erase(Pos, 9);

      Pos = Name.find("\n");
      if (Pos != std::string::npos)
        Name.erase(Pos, 1);
    }

    /// 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) {
      std::string SectionName(Name);
      fixNameForSection(SectionName);

      ELFSection *&SN = SectionLookup[SectionName];
      if (SN) return *SN;

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

    /// TODO: support mangled names here to emit the right .text section
    /// for c++ object files.
    ELFSection &getTextSection() {
      return getSection(".text", ELFSection::SHT_PROGBITS,
                        ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC);
    }

    /// Get jump table section on the section name returned by TAI
    ELFSection &getJumpTableSection(std::string SName, unsigned Align) {
      return getSection(SName, ELFSection::SHT_PROGBITS,
                        ELFSection::SHF_ALLOC, Align);
    }

    /// Get a constant pool section based on the section name returned by TAI
    ELFSection &getConstantPoolSection(std::string SName, unsigned Align) {
      return getSection(SName, ELFSection::SHT_PROGBITS,
                        ELFSection::SHF_MERGE | ELFSection::SHF_ALLOC, Align);
    }

    /// Return the relocation section of section 'S'. 'RelA' is true
    /// if the relocation section contains entries with addends.
    ELFSection &getRelocSection(std::string SName, bool RelA, unsigned Align) {
      std::string RelSName(".rel");
      unsigned SHdrTy = RelA ? ELFSection::SHT_RELA : ELFSection::SHT_REL;

      if (RelA) RelSName.append("a");
      RelSName.append(SName);

      return getSection(RelSName, SHdrTy, 0, Align);
    }

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

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

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

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

    ELFSection &getDataSection() {
      return getSection(".data", ELFSection::SHT_PROGBITS,
                        ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC, 4);
    }

    ELFSection &getBSSSection() {
      return getSection(".bss", ELFSection::SHT_NOBITS,
                        ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC, 4);
    }

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

    // Helpers for obtaining ELF specific info.
    unsigned getGlobalELFLinkage(const GlobalValue *GV);
    unsigned getGlobalELFVisibility(const GlobalValue *GV);
    unsigned getElfSectionFlags(unsigned Flags);

    // 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 EmitFunctionDeclaration(const Function *F);
    void EmitGlobalVar(const GlobalVariable *GV);
    void EmitGlobalConstant(const Constant *C, ELFSection &GblS);
    void EmitGlobalConstantStruct(const ConstantStruct *CVS,
                                  ELFSection &GblS);
    ELFSection &getGlobalSymELFSection(const GlobalVariable *GV, ELFSym &Sym);
    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();
    void OutputSectionsAndSectionTable();
  };
}

#endif
OpenPOWER on IntegriCloud