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
|
//===-- 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/CodeGen/MachineFunctionPass.h"
#include <list>
#include <map>
namespace llvm {
class GlobalVariable;
class Mangler;
class MachineCodeEmitter;
class ELFCodeEmitter;
/// 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(std::ostream &O, TargetMachine &TM);
~ELFWriter();
typedef std::vector<unsigned char> DataBuffer;
protected:
/// Output stream to send the resultant object file to.
///
std::ostream &O;
/// Target machine description.
///
TargetMachine &TM;
/// 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;
//===------------------------------------------------------------------===//
// Properties to be set by the derived class ctor, used to configure the
// ELFWriter.
// e_machine - This field is the target specific value to emit as the
// e_machine member of the ELF header.
unsigned short e_machine;
// e_flags - The machine flags for the target. This defaults to zero.
unsigned e_flags;
//===------------------------------------------------------------------===//
// 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:
// The buffer we accumulate the file header into. Note that this should be
// changed into something much more efficient later (and the bitcode writer
// as well!).
DataBuffer FileHeader;
/// ELFSection - This struct contains information about each section that is
/// emitted to the file. This is eventually turned into the section header
/// table at the end of the file.
struct ELFSection {
std::string Name; // Name of the section.
unsigned NameIdx; // Index in .shstrtab of name, once emitted.
unsigned Type;
unsigned Flags;
uint64_t Addr;
unsigned Offset;
unsigned Size;
unsigned Link;
unsigned Info;
unsigned Align;
unsigned EntSize;
/// SectionIdx - The number of the section in the Section Table.
///
unsigned short SectionIdx;
/// SectionData - The actual data for this section which we are building
/// up for emission to the file.
DataBuffer SectionData;
enum { SHT_NULL = 0, SHT_PROGBITS = 1, SHT_SYMTAB = 2, SHT_STRTAB = 3,
SHT_RELA = 4, SHT_HASH = 5, SHT_DYNAMIC = 6, SHT_NOTE = 7,
SHT_NOBITS = 8, SHT_REL = 9, SHT_SHLIB = 10, SHT_DYNSYM = 11 };
enum { SHN_UNDEF = 0, SHN_ABS = 0xFFF1, SHN_COMMON = 0xFFF2 };
enum { // SHF - ELF Section Header Flags
SHF_WRITE = 1 << 0, // Writable
SHF_ALLOC = 1 << 1, // Mapped into the process addr space
SHF_EXECINSTR = 1 << 2, // Executable
SHF_MERGE = 1 << 4, // Might be merged if equal
SHF_STRINGS = 1 << 5, // Contains null-terminated strings
SHF_INFO_LINK = 1 << 6, // 'sh_info' contains SHT index
SHF_LINK_ORDER = 1 << 7, // Preserve order after combining
SHF_OS_NONCONFORMING = 1 << 8, // nonstandard OS support required
SHF_GROUP = 1 << 9, // Section is a member of a group
SHF_TLS = 1 << 10 // Section holds thread-local data
};
ELFSection(const std::string &name)
: Name(name), Type(0), Flags(0), Addr(0), Offset(0), Size(0),
Link(0), Info(0), Align(0), EntSize(0) {
}
};
/// 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;
/// 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) {
ELFSection *&SN = SectionLookup[Name];
if (SN) return *SN;
SectionList.push_back(Name);
SN = &SectionList.back();
SN->SectionIdx = NumSections++;
SN->Type = Type;
SN->Flags = Flags;
return *SN;
}
ELFSection &getDataSection() {
return getSection(".data", ELFSection::SHT_PROGBITS,
ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC);
}
ELFSection &getBSSSection() {
return getSection(".bss", ELFSection::SHT_NOBITS,
ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC);
}
/// ELFSym - This struct contains information about each symbol that is
/// added to logical symbol table for the module. This is eventually
/// turned into a real symbol table in the file.
struct ELFSym {
const GlobalValue *GV; // The global value this corresponds to.
unsigned NameIdx; // Index in .strtab of name, once emitted.
uint64_t Value;
unsigned Size;
unsigned char Info;
unsigned char Other;
unsigned short SectionIdx;
enum { STB_LOCAL = 0, STB_GLOBAL = 1, STB_WEAK = 2 };
enum { STT_NOTYPE = 0, STT_OBJECT = 1, STT_FUNC = 2, STT_SECTION = 3,
STT_FILE = 4 };
ELFSym(const GlobalValue *gv) : GV(gv), Value(0), Size(0), Info(0),
Other(0), SectionIdx(0) {}
void SetBind(unsigned X) {
assert(X == (X & 0xF) && "Bind value out of range!");
Info = (Info & 0x0F) | (X << 4);
}
void SetType(unsigned X) {
assert(X == (X & 0xF) && "Type value out of range!");
Info = (Info & 0xF0) | X;
}
};
/// SymbolTable - This is the list of symbols we have emitted to the file.
/// This actually gets rearranged before emission to the file (to put the
/// local symbols first in the list).
std::vector<ELFSym> SymbolTable;
// 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 ELFHeader_e_shoff_Offset; // e_shoff in ELF header.
unsigned ELFHeader_e_shstrndx_Offset; // e_shstrndx in ELF header.
unsigned ELFHeader_e_shnum_Offset; // e_shnum in ELF header.
private:
void EmitGlobal(GlobalVariable *GV);
void EmitSymbolTable();
void EmitSectionTableStringTable();
void OutputSectionsAndSectionTable();
};
}
#endif
|