Newer
Older
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
//===- lib/ReaderWriter/ELF/ELFHeaderChunks.h -----------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_ELF_HEADER_CHUNKS_H_
#define LLD_READER_WRITER_ELF_HEADER_CHUNKS_H_
#include "llvm/Object/ELF.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "ELFSegmentChunks.h"
/// \brief An ELFHeader represents the Elf[32/64]_Ehdr structure at the
/// start of an ELF executable file.
namespace lld {
namespace elf {
template<class ELFT>
class ELFHeader : public Chunk<ELFT> {
public:
typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
ELFHeader();
void e_ident(int I, unsigned char C) { _eh.e_ident[I] = C; }
void e_type(uint16_t type) { _eh.e_type = type; }
void e_machine(uint16_t machine) { _eh.e_machine = machine; }
void e_version(uint32_t version) { _eh.e_version = version; }
void e_entry(int64_t entry) { _eh.e_entry = entry; }
void e_phoff(int64_t phoff) { _eh.e_phoff = phoff; }
void e_shoff(int64_t shoff) { _eh.e_shoff = shoff; }
void e_flags(uint32_t flags) { _eh.e_flags = flags; }
void e_ehsize(uint16_t ehsize) { _eh.e_ehsize = ehsize; }
void e_phentsize(uint16_t phentsize) { _eh.e_phentsize = phentsize; }
void e_phnum(uint16_t phnum) { _eh.e_phnum = phnum; }
void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
void e_shnum(uint16_t shnum) { _eh.e_shnum = shnum; }
void e_shstrndx(uint16_t shstrndx) { _eh.e_shstrndx = shstrndx; }
uint64_t fileSize() { return sizeof (Elf_Ehdr); }
static inline bool classof(const Chunk<ELFT> *c) {
return c->Kind() == Chunk<ELFT>::K_ELFHeader;
}
void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer);
void finalize() { }
private:
Elf_Ehdr _eh;
};
template<class ELFT>
ELFHeader<ELFT>::ELFHeader()
: Chunk<ELFT>("elfhdr", Chunk<ELFT>::K_ELFHeader) {
this->_align2 = ELFT::Is64Bits ? 8 : 4;
this->_fsize = sizeof(Elf_Ehdr);
this->_msize = sizeof(Elf_Ehdr);
memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT);
e_ident(llvm::ELF::EI_MAG0, 0x7f);
e_ident(llvm::ELF::EI_MAG1, 'E');
e_ident(llvm::ELF::EI_MAG2, 'L');
e_ident(llvm::ELF::EI_MAG3, 'F');
e_ehsize(sizeof(Elf_Ehdr));
e_flags(2);
}
template <class ELFT>
void ELFHeader<ELFT>::write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) {
uint8_t *chunkBuffer = buffer.getBufferStart();
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
uint8_t *atomContent = chunkBuffer + this->fileOffset();
memcpy(atomContent, &_eh, fileSize());
}
/// \brief An ELFProgramHeader represents the Elf[32/64]_Phdr structure at the
/// start of an ELF executable file.
template<class ELFT>
class ELFProgramHeader : public Chunk<ELFT> {
public:
typedef llvm::object::Elf_Phdr_Impl<ELFT> Elf_Phdr;
typedef typename std::vector<Elf_Phdr *>::iterator PhIterT;
/// \brief Find a program header entry, given the type of entry that
/// we are looking for
class FindPhdr {
public:
FindPhdr(uint64_t type, uint64_t flags, uint64_t flagsClear)
: _type(type)
, _flags(flags)
, _flagsClear(flagsClear)
{}
bool operator()(const Elf_Phdr *j) const {
return ((j->p_type == _type) &&
((j->p_flags & _flags) == _flags) &&
(!(j->p_flags & _flagsClear)));
}
private:
uint64_t _type;
uint64_t _flags;
uint64_t _flagsClear;
};
ELFProgramHeader()
: Chunk<ELFT>("elfphdr", Chunk<ELFT>::K_ELFProgramHeader) {
this->_align2 = ELFT::Is64Bits ? 8 : 4;
resetProgramHeaders();
}
bool addSegment(Segment<ELFT> *segment);
void resetProgramHeaders() {
_phi = _ph.begin();
}
uint64_t fileSize() {
return sizeof(Elf_Phdr) * _ph.size();
}
static inline bool classof(const Chunk<ELFT> *c) {
return c->Kind() == Chunk<ELFT>::K_ELFProgramHeader;
}
void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer);
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
/// \brief find a program header entry in the list of program headers
PhIterT findProgramHeader(uint64_t type, uint64_t flags, uint64_t flagClear) {
return std::find_if(_ph.begin(), _ph.end(),
FindPhdr(type, flags, flagClear));
}
PhIterT begin() {
return _ph.begin();
}
PhIterT end() {
return _ph.end();
}
void finalize() { }
int64_t entsize() {
return sizeof(Elf_Phdr);
}
int64_t numHeaders() {
return _ph.size();
}
private:
std::vector<Elf_Phdr *> _ph;
PhIterT _phi;
llvm::BumpPtrAllocator _allocator;
};
template<class ELFT>
bool
ELFProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) {
Elf_Phdr *phdr = nullptr;
bool ret = false;
for (auto slice : segment->slices()) {
if (_phi == _ph.end()) {
phdr = new(_allocator.Allocate<Elf_Phdr>()) Elf_Phdr;
_ph.push_back(phdr);
_phi = _ph.end();
ret = true;
} else {
phdr = (*_phi);
++_phi;
}
phdr->p_type = segment->segmentType();
phdr->p_offset = slice->fileOffset();
phdr->p_vaddr = slice->virtualAddr();
phdr->p_paddr = slice->virtualAddr();
phdr->p_filesz = slice->fileSize();
phdr->p_memsz = slice->memSize();
phdr->p_flags = segment->flags();
phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ?
segment->pageSize() : slice->align2();
}
this->_fsize = fileSize();
this->_msize = this->_fsize;
return ret;
}
template <class ELFT>
void ELFProgramHeader<ELFT>::write(ELFWriter *writer,
llvm::FileOutputBuffer &buffer) {
uint8_t *chunkBuffer = buffer.getBufferStart();
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
uint8_t *dest = chunkBuffer + this->fileOffset();
for (auto phi : _ph) {
memcpy(dest, phi, sizeof(Elf_Phdr));
dest += sizeof(Elf_Phdr);
}
}
/// \brief An ELFSectionHeader represents the Elf[32/64]_Shdr structure
/// at the end of the file
template<class ELFT>
class ELFSectionHeader : public Chunk<ELFT> {
public:
typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
ELFSectionHeader(int32_t order);
void appendSection(MergedSections<ELFT> *section);
void updateSection(Section<ELFT> *section);
static inline bool classof(const Chunk<ELFT> *c) {
return c->getChunkKind() == Chunk<ELFT>::K_ELFSectionHeader;
}
void setStringSection(ELFStringTable<ELFT> *s) {
_stringSection = s;
}
void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer);
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
void finalize() { }
inline uint16_t fileSize() {
return sizeof(Elf_Shdr) * _sectionInfo.size();
}
inline int64_t entsize() {
return sizeof(Elf_Shdr);
}
inline int64_t numHeaders() {
return _sectionInfo.size();
}
private:
ELFStringTable<ELFT> *_stringSection;
std::vector<Elf_Shdr*> _sectionInfo;
llvm::BumpPtrAllocator _sectionAllocate;
};
template<class ELFT>
ELFSectionHeader<ELFT>::ELFSectionHeader(int32_t order)
: Chunk<ELFT>("shdr", Chunk<ELFT>::K_ELFSectionHeader) {
this->_fsize = 0;
this->_align2 = 8;
this->setOrder(order);
// The first element in the list is always NULL
Elf_Shdr *nullshdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
::memset(nullshdr, 0, sizeof (Elf_Shdr));
_sectionInfo.push_back(nullshdr);
this->_fsize += sizeof (Elf_Shdr);
}
template<class ELFT>
void
ELFSectionHeader<ELFT>::appendSection(MergedSections<ELFT> *section) {
Elf_Shdr *shdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
shdr->sh_name = _stringSection->addString(section->name());
shdr->sh_type = section->type();
shdr->sh_flags = section->flags();
shdr->sh_offset = section->fileOffset();
shdr->sh_addr = section->virtualAddr();
shdr->sh_size = section->memSize();
shdr->sh_link = section->link();
shdr->sh_info = section->shinfo();
shdr->sh_addralign = section->align2();
shdr->sh_entsize = section->entsize();
_sectionInfo.push_back(shdr);
}
template<class ELFT>
void
ELFSectionHeader<ELFT>::updateSection(Section<ELFT> *section) {
Elf_Shdr *shdr = _sectionInfo[section->ordinal()];
shdr->sh_type = section->type();
shdr->sh_flags = section->flags();
shdr->sh_offset = section->fileOffset();
shdr->sh_addr = section->virtualAddr();
shdr->sh_size = section->fileSize();
shdr->sh_link = section->link();
shdr->sh_info = section->shinfo();
shdr->sh_addralign = section->align2();
shdr->sh_entsize = section->entsize();
}
template <class ELFT>
void ELFSectionHeader<ELFT>::write(ELFWriter *writer,
llvm::FileOutputBuffer &buffer) {
uint8_t *chunkBuffer = buffer.getBufferStart();
uint8_t *dest = chunkBuffer + this->fileOffset();
for (auto shi : _sectionInfo) {
memcpy(dest, shi, sizeof(Elf_Shdr));
dest += sizeof(Elf_Shdr);
}
_stringSection->write(writer, buffer);
}
} // elf
} // lld
#endif // LLD_READER_WRITER_ELF_HEADER_CHUNKS_H_