Add support for building/representing the symbol table, add some enum constants
[oota-llvm.git] / include / llvm / CodeGen / ELFWriter.h
1 //===-- ELFWriter.h - Target-independent ELF writer support -----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the ELFWriter class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_CODEGEN_ELFWRITER_H
15 #define LLVM_CODEGEN_ELFWRITER_H
16
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18
19 namespace llvm {
20   class GlobalVariable;
21
22   /// ELFWriter - This class implements the common target-independent code for
23   /// writing ELF files.  Targets should derive a class from this to
24   /// parameterize the output format.
25   ///
26   class ELFWriter : public MachineFunctionPass {
27   protected:
28     ELFWriter(std::ostream &O, TargetMachine &TM);
29
30     /// Output stream to send the resultant object file to.
31     ///
32     std::ostream &O;
33
34     /// Target machine description.
35     ///
36     TargetMachine &TM;
37
38     //===------------------------------------------------------------------===//
39     // Properties to be set by the derived class ctor, used to configure the
40     // ELFWriter.
41
42     // e_machine - This field is the target specific value to emit as the
43     // e_machine member of the ELF header.
44     unsigned short e_machine;
45
46     // e_flags - The machine flags for the target.  This defaults to zero.
47     unsigned e_flags;
48
49     //===------------------------------------------------------------------===//
50     // Properties inferred automatically from the target machine.
51     //
52
53     /// is64Bit/isLittleEndian - This information is inferred from the target
54     /// machine directly, indicating whether to emit a 32- or 64-bit ELF file.
55     bool is64Bit, isLittleEndian;
56
57     /// doInitialization - Emit the file header and all of the global variables
58     /// for the module to the ELF file.
59     bool doInitialization(Module &M);
60
61     bool runOnMachineFunction(MachineFunction &MF);
62
63
64     /// doFinalization - Now that the module has been completely processed, emit
65     /// the ELF file to 'O'.
66     bool doFinalization(Module &M);
67
68   private:
69     // The buffer we are accumulating the file into.  Note that this should be
70     // changed into something much more efficient later (and the bytecode writer
71     // as well!).
72     std::vector<unsigned char> OutputBuffer;
73
74     /// ELFSection - This struct contains information about each section that is
75     /// emitted to the OutputBuffer.  This is eventually turned into the section
76     /// header table at the end of the file.
77     struct ELFSection {
78       std::string Name;       // Name of the section.
79       unsigned NameIdx;       // Index in .shstrtab of name, once emitted.
80       unsigned Type;
81       unsigned Flags;
82       uint64_t Addr;
83       unsigned Offset;
84       unsigned Size;
85       unsigned Link;
86       unsigned Info;
87       unsigned Align;
88       unsigned EntSize;
89
90       enum { SHT_NULL = 0, SHT_PROGBITS = 1, SHT_SYMTAB = 2, SHT_STRTAB = 3,
91              SHT_RELA = 4, SHT_HASH = 5, SHT_DYNAMIC = 6, SHT_NOTE = 7,
92              SHT_NOBITS = 8, SHT_REL = 9, SHT_SHLIB = 10, SHT_DYNSYM = 11 };
93       enum { SHN_UNDEF = 0, SHN_ABS = 0xFFF1, SHN_COMMON = 0xFFF2 };
94       enum { SHF_WRITE = 1, SHF_ALLOC = 2, SHF_EXECINSTR = 4 };
95
96       ELFSection(const char *name = "", unsigned offset = 0)
97         : Name(name), Type(0), Flags(0), Addr(0), Offset(offset), Size(0),
98           Link(0), Info(0), Align(0), EntSize(0) {
99       }
100     };
101
102     /// SectionList - This is the list of sections that we have emitted to the
103     /// file.  Once the file has been completely built, the section header table
104     /// is constructed from this info.
105     std::vector<ELFSection> SectionList;
106
107     /// ELFSym - This struct contains information about each symbol that is
108     /// added to logical symbol table for the module.  This is eventually
109     /// turned into a real symbol table in the file.
110     struct ELFSym {
111       GlobalValue *GV;        // The global value this corresponds to.
112       //std::string Name;       // Name of the symbol.
113       unsigned NameIdx;       // Index in .strtab of name, once emitted.
114       uint64_t Value;
115       unsigned Size;
116       unsigned char Info;
117       unsigned char Other;
118       unsigned short SectionIdx;
119
120       enum { STB_LOCAL = 0, STB_GLOBAL = 1, STB_WEAK = 2 };
121       enum { STT_NOTYPE = 0, STT_OBJECT = 1, STT_FUNC = 2, STT_SECTION = 3,
122              STT_FILE = 4 };
123       ELFSym(GlobalValue *gv) : GV(gv), Value(0), Size(0), Info(0),
124                                 Other(0), SectionIdx(0) {}
125
126       void SetBind(unsigned X) {
127         assert(X == (X & 0xF) && "Bind value out of range!");
128         Info = (Info & 0x0F) | (X << 4);
129       }
130       void SetType(unsigned X) {
131         assert(X == (X & 0xF) && "Type value out of range!");
132         Info = (Info & 0xF0) | X;
133       }
134     };
135
136     /// SymbolTable - This is the list of symbols we have emitted to the file.
137     /// This actually gets rearranged before emission to OutputBuffer (to put
138     /// the local symbols first in the list).
139     std::vector<ELFSym> SymbolTable;
140
141
142     // As we accumulate the ELF file into OutputBuffer, we occasionally need to
143     // keep track of locations to update later (e.g. the location of the section
144     // table in the ELF header.  These members keep track of the offset in
145     // OffsetBuffer of these various pieces to update and other locations in the
146     // file.
147     unsigned ELFHeader_e_shoff_Offset;     // e_shoff    in ELF header.
148     unsigned ELFHeader_e_shstrndx_Offset;  // e_shstrndx in ELF header.
149     unsigned ELFHeader_e_shnum_Offset;     // e_shnum    in ELF header.
150
151     // align - Emit padding into the file until the current output position is
152     // aligned to the specified power of two boundary.
153     void align(unsigned Boundary) {
154       assert(Boundary && (Boundary & (Boundary-1)) == 0 &&
155              "Must align to 2^k boundary");
156       while (OutputBuffer.size() & (Boundary-1))
157         outbyte(0xAB);
158     }
159
160     void outbyte(unsigned char X) { OutputBuffer.push_back(X); }
161     void outhalf(unsigned short X) {
162       if (isLittleEndian) {
163         OutputBuffer.push_back(X&255);
164         OutputBuffer.push_back(X >> 8);
165       } else {
166         OutputBuffer.push_back(X >> 8);
167         OutputBuffer.push_back(X&255);
168       }
169     }
170     void outword(unsigned X) {
171       if (isLittleEndian) {
172         OutputBuffer.push_back((X >>  0) & 255);
173         OutputBuffer.push_back((X >>  8) & 255);
174         OutputBuffer.push_back((X >> 16) & 255);
175         OutputBuffer.push_back((X >> 24) & 255);
176       } else {
177         OutputBuffer.push_back((X >> 24) & 255);
178         OutputBuffer.push_back((X >> 16) & 255);
179         OutputBuffer.push_back((X >>  8) & 255);
180         OutputBuffer.push_back((X >>  0) & 255);
181       }
182     }
183     void outaddr(uint64_t X) {
184       if (!is64Bit)
185         outword((unsigned)X);
186       else
187         assert(0 && "Emission of 64-bit data not implemented yet!");
188     }
189
190     // fix functions - Replace an existing entry at an offset.
191     void fixhalf(unsigned short X, unsigned Offset) {
192       unsigned char *P = &OutputBuffer[Offset];
193       P[0] = (X >> (isLittleEndian ?  0 : 8)) & 255;
194       P[1] = (X >> (isLittleEndian ?  8 : 0)) & 255;
195     }
196
197     void fixword(unsigned X, unsigned Offset) {
198       unsigned char *P = &OutputBuffer[Offset];
199       P[0] = (X >> (isLittleEndian ?  0 : 24)) & 255;
200       P[1] = (X >> (isLittleEndian ?  8 : 16)) & 255;
201       P[2] = (X >> (isLittleEndian ? 16 :  8)) & 255;
202       P[3] = (X >> (isLittleEndian ? 24 :  0)) & 255;
203     }
204
205     void fixaddr(uint64_t X, unsigned Offset) {
206       if (!is64Bit)
207         fixword((unsigned)X, Offset);
208       else
209         assert(0 && "Emission of 64-bit data not implemented yet!");
210     }
211
212   private:
213     void EmitGlobal(GlobalVariable *GV, ELFSection &DataSection,
214                     ELFSection &BSSSection);
215
216     void EmitSymbolTable();
217
218     void EmitSectionTableStringTable();
219     void EmitSectionTable();
220   };
221 }
222
223 #endif