Halide 21.0.0
Halide compiler and libraries
Loading...
Searching...
No Matches
Elf.h
Go to the documentation of this file.
1#ifndef HALIDE_ELF_H
2#define HALIDE_ELF_H
3
4#include <algorithm>
5#include <cstdint>
6#include <iterator>
7#include <list>
8#include <memory>
9#include <string>
10#include <utility>
11#include <vector>
12
13namespace Halide {
14namespace Internal {
15namespace Elf {
16
17// This ELF parser mostly deserializes the object into a graph
18// structure in memory. It replaces indices into tables (sections,
19// symbols, etc.) with a weakly referenced graph of pointers. The
20// Object datastructure owns all of the objects. This namespace exists
21// because it is very difficult to use LLVM's object parser to modify
22// an object (it's fine for parsing only). This was built using
23// http://www.skyfree.org/linux/references/ELF_Format.pdf as a reference
24// for the ELF structs and constants.
25
26class Object;
27class Symbol;
28class Section;
29class Relocation;
30
31// Helpful wrapper to allow range-based for loops.
32template<typename T>
34 T b, e;
35
36public:
38 : b(b), e(e) {
39 }
40
41 T begin() const {
42 return b;
43 }
44 T end() const {
45 return e;
46 }
47};
48
49/** Describes a symbol */
50class Symbol {
51public:
59
69
76
77private:
78 std::string name;
79 const Section *definition = nullptr;
80 uint64_t offset = 0;
81 uint32_t size = 0;
82 Binding binding = STB_LOCAL;
83 Type type = STT_NOTYPE;
84 Visibility visibility = STV_DEFAULT;
85
86public:
87 Symbol() = default;
88 Symbol(const std::string &name)
89 : name(name) {
90 }
91
92 /** Accesses the name of this symbol. */
93 ///@{
94 Symbol &set_name(const std::string &name) {
95 this->name = name;
96 return *this;
97 }
98 const std::string &get_name() const {
99 return name;
100 }
101 ///@}
102
103 /** Accesses the type of this symbol. */
104 ///@{
106 this->type = type;
107 return *this;
108 }
109 Type get_type() const {
110 return type;
111 }
112 ///@}
113
114 /** Accesses the properties that describe the definition of this symbol. */
115 ///@{
116 Symbol &define(const Section *section, uint64_t offset, uint32_t size) {
117 this->definition = section;
118 this->offset = offset;
119 this->size = size;
120 return *this;
121 }
122 bool is_defined() const {
123 return definition != nullptr;
124 }
125 const Section *get_section() const {
126 return definition;
127 }
129 return offset;
130 }
132 return size;
133 }
134 ///@}
135
136 /** Access the binding and visibility of this symbol. See the ELF
137 * spec for more information about these properties. */
138 ///@{
140 this->binding = binding;
141 return *this;
142 }
144 this->visibility = visibility;
145 return *this;
146 }
148 return binding;
149 }
151 return visibility;
152 }
153 ///@}
154};
155
156/** Describes a relocation to be applied to an offset of a section in
157 * an Object. */
159 uint32_t type = 0;
160 uint64_t offset = 0;
161 int64_t addend = 0;
162 const Symbol *symbol = nullptr;
163
164public:
165 Relocation() = default;
166 Relocation(uint32_t type, uint64_t offset, int64_t addend, const Symbol *symbol)
167 : type(type), offset(offset), addend(addend), symbol(symbol) {
168 }
169
170 /** The type of relocation to be applied. The meaning of this
171 * value depends on the machine of the object. */
172 ///@{
174 this->type = type;
175 return *this;
176 }
178 return type;
179 }
180 ///@}
181
182 /** Where to apply the relocation. This is relative to the section
183 * the relocation belongs to. */
184 ///@{
186 this->offset = offset;
187 return *this;
188 }
190 return offset;
191 }
192 ///@}
193
194 /** The value to replace with the relocation is the address of the symbol plus the addend. */
195 ///@{
196 Relocation &set_symbol(const Symbol *symbol) {
197 this->symbol = symbol;
198 return *this;
199 }
201 this->addend = addend;
202 return *this;
203 }
204 const Symbol *get_symbol() const {
205 return symbol;
206 }
208 return addend;
209 }
210 ///@}
211};
212
213/** Describes a section of an object file. */
214class Section {
215public:
216 enum Type : uint32_t {
229 SHT_LOPROC = 0x70000000u,
230 SHT_HIPROC = 0x7fffffffu,
231 SHT_LOUSER = 0x80000000u,
232 SHT_HIUSER = 0xffffffffu,
233 };
234
235 enum Flag : uint32_t {
239 SHF_MASKPROC = 0xf0000000u,
240 };
241
242 typedef std::vector<Relocation> RelocationList;
243 typedef RelocationList::iterator relocation_iterator;
244 typedef RelocationList::const_iterator const_relocation_iterator;
245
246 typedef std::vector<char>::iterator contents_iterator;
247 typedef std::vector<char>::const_iterator const_contents_iterator;
248
249private:
250 std::string name;
251 Type type = SHT_NULL;
252 uint32_t flags = 0;
253 std::vector<char> contents;
254 // Sections may have a size larger than the contents.
255 uint64_t size = 0;
256 uint64_t alignment = 1;
257 RelocationList relocs;
258
259public:
260 Section() = default;
261 Section(const std::string &name, Type type)
262 : name(name), type(type) {
263 }
264
265 Section &set_name(const std::string &name) {
266 this->name = name;
267 return *this;
268 }
269 const std::string &get_name() const {
270 return name;
271 }
272
274 this->type = type;
275 return *this;
276 }
277 Type get_type() const {
278 return type;
279 }
280
282 this->flags |= flag;
283 return *this;
284 }
286 this->flags &= ~flag;
287 return *this;
288 }
290 this->flags = flags;
291 return *this;
292 }
294 return flags;
295 }
296 bool is_alloc() const {
297 return (flags & SHF_ALLOC) != 0;
298 }
299 bool is_writable() const {
300 return (flags & SHF_WRITE) != 0;
301 }
302
303 /** Get or set the size of the section. The size may be larger
304 * than the content. */
305 ///@{
307 this->size = size;
308 return *this;
309 }
311 return std::max((uint64_t)size, (uint64_t)contents.size());
312 }
313 ///@}
314
316 this->alignment = alignment;
317 return *this;
318 }
320 return alignment;
321 }
322
323 Section &set_contents(std::vector<char> contents) {
324 this->contents = std::move(contents);
325 return *this;
326 }
327 template<typename It>
329 this->contents.assign(begin, end);
330 return *this;
331 }
332 template<typename It>
334 this->contents.insert(this->contents.end(), begin, end);
335 return *this;
336 }
337 template<typename It>
339 typedef typename std::iterator_traits<It>::value_type T;
340 uint64_t size_bytes = std::distance(begin, end) * sizeof(T);
341 this->contents.insert(this->contents.begin(), begin, end);
342
343 // When we add data to the start of the section, we need to fix up
344 // the offsets of the relocations linked to this section.
345 for (Relocation &r : relocations()) {
346 r.set_offset(r.get_offset() + size_bytes);
347 }
348
349 return *this;
350 }
351 /** Set, append or prepend an object to the contents, assuming T is a
352 * trivially copyable datatype. */
353 template<typename T>
354 Section &set_contents(const std::vector<T> &contents) {
355 this->contents.assign((const char *)contents.data(), (const char *)(contents.data() + contents.size()));
356 return *this;
357 }
358 template<typename T>
360 return append_contents((const char *)&x, (const char *)(&x + 1));
361 }
362 template<typename T>
364 return prepend_contents((const char *)&x, (const char *)(&x + 1));
365 }
366 const std::vector<char> &get_contents() const {
367 return contents;
368 }
370 return contents.begin();
371 }
373 return contents.end();
374 }
376 return contents.begin();
377 }
379 return contents.end();
380 }
381 const char *contents_data() const {
382 return contents.data();
383 }
384 size_t contents_size() const {
385 return contents.size();
386 }
387 bool contents_empty() const {
388 return contents.empty();
389 }
390
391 Section &set_relocations(std::vector<Relocation> relocs) {
392 this->relocs = std::move(relocs);
393 return *this;
394 }
395 template<typename It>
397 this->relocs.assign(begin, end);
398 return *this;
399 }
400 void add_relocation(const Relocation &reloc) {
401 relocs.push_back(reloc);
402 }
404 return relocs.begin();
405 }
407 return relocs.end();
408 }
410 return {relocs.begin(), relocs.end()};
411 }
413 return relocs.begin();
414 }
416 return relocs.end();
417 }
419 return {relocs.begin(), relocs.end()};
420 }
421 size_t relocations_size() const {
422 return relocs.size();
423 }
424};
425
426/** Base class for a target architecture to implement the target
427 * specific aspects of linking. */
428class Linker {
429public:
430 virtual ~Linker() = default;
431
432 virtual uint16_t get_machine() = 0;
433 virtual uint32_t get_flags() = 0;
434 virtual uint32_t get_version() = 0;
435 virtual void append_dynamic(Section &dynamic) = 0;
436
437 /** Add or get an entry to the global offset table (GOT) with a
438 * relocation pointing to sym. */
439 virtual uint64_t get_got_entry(Section &got, const Symbol &sym) = 0;
440
441 /** Check to see if this relocation should go through the PLT. */
442 virtual bool needs_plt_entry(const Relocation &reloc) = 0;
443
444 /** Add a PLT entry for a symbol sym defined externally. Returns a
445 * symbol representing the PLT entry. */
446 virtual Symbol add_plt_entry(const Symbol &sym, Section &plt, Section &got,
447 const Symbol &got_sym) = 0;
448
449 /** Perform a relocation. This function may opt to not apply the
450 * relocation, and return a new relocation to be performed at
451 * runtime. This requires that the section to apply the relocation
452 * to is writable at runtime. */
453 virtual Relocation relocate(uint64_t fixup_offset, char *fixup_addr, uint64_t type,
454 const Symbol *sym, uint64_t sym_offset, int64_t addend,
455 Section &got) = 0;
456};
457
458/** Holds all of the relevant sections and symbols for an object. */
459class Object {
460public:
461 enum Type : uint16_t {
467 ET_LOPROC = 0xff00u,
468 ET_HIPROC = 0xffffu,
469 };
470
471 // We use lists for sections and symbols to avoid iterator
472 // invalidation when we modify the containers.
473 typedef std::list<Section> SectionList;
474 typedef typename SectionList::iterator section_iterator;
475 typedef typename SectionList::const_iterator const_section_iterator;
476
477 typedef std::list<Symbol> SymbolList;
478 typedef typename SymbolList::iterator symbol_iterator;
479 typedef typename SymbolList::const_iterator const_symbol_iterator;
480
481private:
482 SectionList secs;
483 SymbolList syms;
484
485 Type type = ET_NONE;
486 uint16_t machine = 0;
487 uint32_t version = 0;
488 uint64_t entry = 0;
489 uint32_t flags = 0;
490
491 Object(const Object &);
492 void operator=(const Object &);
493
494public:
495 Object() = default;
496
497 Type get_type() const {
498 return type;
499 }
501 return machine;
502 }
504 return version;
505 }
507 return entry;
508 }
510 return flags;
511 }
512
513 Object &set_type(Type type) {
514 this->type = type;
515 return *this;
516 }
517 Object &set_machine(uint16_t machine) {
518 this->machine = machine;
519 return *this;
520 }
521 Object &set_version(uint32_t version) {
522 this->version = version;
523 return *this;
524 }
525 Object &set_entry(uint64_t entry) {
526 this->entry = entry;
527 return *this;
528 }
529 Object &set_flags(uint32_t flags) {
530 this->flags = flags;
531 return *this;
532 }
533
534 /** Parse an object in memory to an Object. */
535 static std::unique_ptr<Object> parse_object(const char *data, size_t size);
536
537 /** Write a shared object in memory. */
538 std::vector<char> write_shared_object(Linker *linker, const std::vector<std::string> &depedencies = {},
539 const std::string &soname = "");
540
542 return secs.begin();
543 }
545 return secs.end();
546 }
548 return {secs.begin(), secs.end()};
549 }
551 return secs.begin();
552 }
554 return secs.end();
555 }
557 return {secs.begin(), secs.end()};
558 }
559 size_t sections_size() const {
560 return secs.size();
561 }
562 section_iterator find_section(const std::string &name);
563
564 section_iterator add_section(const std::string &name, Section::Type type);
567 return secs.erase(i);
568 }
569
570 section_iterator merge_sections(const std::vector<section_iterator> &sections);
572
574 return syms.begin();
575 }
577 return syms.end();
578 }
580 return {syms.begin(), syms.end()};
581 }
583 return syms.begin();
584 }
586 return syms.end();
587 }
589 return {syms.begin(), syms.end()};
590 }
591 size_t symbols_size() const {
592 return syms.size();
593 }
594 symbol_iterator find_symbol(const std::string &name);
595 const_symbol_iterator find_symbol(const std::string &name) const;
596
597 symbol_iterator add_symbol(const std::string &name);
598};
599
600} // namespace Elf
601} // namespace Internal
602} // namespace Halide
603
604#endif
Base class for a target architecture to implement the target specific aspects of linking.
Definition Elf.h:428
virtual Symbol add_plt_entry(const Symbol &sym, Section &plt, Section &got, const Symbol &got_sym)=0
Add a PLT entry for a symbol sym defined externally.
virtual void append_dynamic(Section &dynamic)=0
virtual bool needs_plt_entry(const Relocation &reloc)=0
Check to see if this relocation should go through the PLT.
virtual uint32_t get_flags()=0
virtual uint32_t get_version()=0
virtual uint64_t get_got_entry(Section &got, const Symbol &sym)=0
Add or get an entry to the global offset table (GOT) with a relocation pointing to sym.
virtual uint16_t get_machine()=0
virtual Relocation relocate(uint64_t fixup_offset, char *fixup_addr, uint64_t type, const Symbol *sym, uint64_t sym_offset, int64_t addend, Section &got)=0
Perform a relocation.
Holds all of the relevant sections and symbols for an object.
Definition Elf.h:459
uint16_t get_machine() const
Definition Elf.h:500
symbol_iterator symbols_end()
Definition Elf.h:576
section_iterator erase_section(section_iterator i)
Definition Elf.h:566
Object & set_type(Type type)
Definition Elf.h:513
symbol_iterator find_symbol(const std::string &name)
Object & set_flags(uint32_t flags)
Definition Elf.h:529
const_section_iterator sections_begin() const
Definition Elf.h:550
section_iterator sections_end()
Definition Elf.h:544
static std::unique_ptr< Object > parse_object(const char *data, size_t size)
Parse an object in memory to an Object.
SymbolList::const_iterator const_symbol_iterator
Definition Elf.h:479
iterator_range< const_section_iterator > sections() const
Definition Elf.h:556
Object & set_entry(uint64_t entry)
Definition Elf.h:525
section_iterator find_section(const std::string &name)
std::vector< char > write_shared_object(Linker *linker, const std::vector< std::string > &depedencies={}, const std::string &soname="")
Write a shared object in memory.
iterator_range< section_iterator > sections()
Definition Elf.h:547
iterator_range< symbol_iterator > symbols()
Definition Elf.h:579
section_iterator add_section(const std::string &name, Section::Type type)
uint32_t get_flags() const
Definition Elf.h:509
Object & set_machine(uint16_t machine)
Definition Elf.h:517
SymbolList::iterator symbol_iterator
Definition Elf.h:478
Type get_type() const
Definition Elf.h:497
const_symbol_iterator find_symbol(const std::string &name) const
const_section_iterator sections_end() const
Definition Elf.h:553
SectionList::const_iterator const_section_iterator
Definition Elf.h:475
const_symbol_iterator symbols_begin() const
Definition Elf.h:582
Object & set_version(uint32_t version)
Definition Elf.h:521
section_iterator add_relocation_section(const Section &for_section)
size_t symbols_size() const
Definition Elf.h:591
section_iterator merge_text_sections()
uint64_t get_entry() const
Definition Elf.h:506
section_iterator merge_sections(const std::vector< section_iterator > &sections)
const_symbol_iterator symbols_end() const
Definition Elf.h:585
std::list< Symbol > SymbolList
Definition Elf.h:477
symbol_iterator add_symbol(const std::string &name)
symbol_iterator symbols_begin()
Definition Elf.h:573
size_t sections_size() const
Definition Elf.h:559
uint32_t get_version() const
Definition Elf.h:503
section_iterator sections_begin()
Definition Elf.h:541
SectionList::iterator section_iterator
Definition Elf.h:474
iterator_range< const_symbol_iterator > symbols() const
Definition Elf.h:588
std::list< Section > SectionList
Definition Elf.h:473
Describes a relocation to be applied to an offset of a section in an Object.
Definition Elf.h:158
int64_t get_addend() const
The value to replace with the relocation is the address of the symbol plus the addend.
Definition Elf.h:207
Relocation(uint32_t type, uint64_t offset, int64_t addend, const Symbol *symbol)
Definition Elf.h:166
Relocation & set_symbol(const Symbol *symbol)
The value to replace with the relocation is the address of the symbol plus the addend.
Definition Elf.h:196
Relocation & set_type(uint32_t type)
The type of relocation to be applied.
Definition Elf.h:173
Relocation & set_addend(int64_t addend)
The value to replace with the relocation is the address of the symbol plus the addend.
Definition Elf.h:200
uint64_t get_offset() const
Where to apply the relocation.
Definition Elf.h:189
Relocation & set_offset(uint64_t offset)
Where to apply the relocation.
Definition Elf.h:185
const Symbol * get_symbol() const
The value to replace with the relocation is the address of the symbol plus the addend.
Definition Elf.h:204
uint32_t get_type() const
The type of relocation to be applied.
Definition Elf.h:177
Describes a section of an object file.
Definition Elf.h:214
bool contents_empty() const
Definition Elf.h:387
Section & prepend_contents(It begin, It end)
Definition Elf.h:338
size_t relocations_size() const
Definition Elf.h:421
Section & append_contents(It begin, It end)
Definition Elf.h:333
uint64_t get_alignment() const
Definition Elf.h:319
size_t contents_size() const
Definition Elf.h:384
Section & set_contents(const std::vector< T > &contents)
Set, append or prepend an object to the contents, assuming T is a trivially copyable datatype.
Definition Elf.h:354
relocation_iterator relocations_end()
Definition Elf.h:406
uint32_t get_flags() const
Definition Elf.h:293
Section & set_relocations(std::vector< Relocation > relocs)
Definition Elf.h:391
Section & set_contents(std::vector< char > contents)
Definition Elf.h:323
uint64_t get_size() const
Get or set the size of the section.
Definition Elf.h:310
Section & set_flags(uint32_t flags)
Definition Elf.h:289
std::vector< char >::iterator contents_iterator
Definition Elf.h:246
relocation_iterator relocations_begin()
Definition Elf.h:403
void add_relocation(const Relocation &reloc)
Definition Elf.h:400
const std::vector< char > & get_contents() const
Definition Elf.h:366
RelocationList::iterator relocation_iterator
Definition Elf.h:243
RelocationList::const_iterator const_relocation_iterator
Definition Elf.h:244
Section & set_contents(It begin, It end)
Definition Elf.h:328
const_contents_iterator contents_begin() const
Definition Elf.h:375
Section & set_size(uint64_t size)
Get or set the size of the section.
Definition Elf.h:306
contents_iterator contents_begin()
Definition Elf.h:369
const std::string & get_name() const
Definition Elf.h:269
contents_iterator contents_end()
Definition Elf.h:372
const_relocation_iterator relocations_begin() const
Definition Elf.h:412
iterator_range< relocation_iterator > relocations()
Definition Elf.h:409
Section & set_type(Type type)
Definition Elf.h:273
std::vector< char >::const_iterator const_contents_iterator
Definition Elf.h:247
Section & remove_flag(Flag flag)
Definition Elf.h:285
Section & append_contents(const T &x)
Definition Elf.h:359
Section(const std::string &name, Type type)
Definition Elf.h:261
Section & set_flag(Flag flag)
Definition Elf.h:281
Section & set_name(const std::string &name)
Definition Elf.h:265
std::vector< Relocation > RelocationList
Definition Elf.h:242
bool is_writable() const
Definition Elf.h:299
Section & prepend_contents(const T &x)
Definition Elf.h:363
const_contents_iterator contents_end() const
Definition Elf.h:378
Section & set_relocations(It begin, It end)
Definition Elf.h:396
const_relocation_iterator relocations_end() const
Definition Elf.h:415
iterator_range< const_relocation_iterator > relocations() const
Definition Elf.h:418
const char * contents_data() const
Definition Elf.h:381
Section & set_alignment(uint64_t alignment)
Definition Elf.h:315
Describes a symbol.
Definition Elf.h:50
Symbol(const std::string &name)
Definition Elf.h:88
uint64_t get_offset() const
Accesses the properties that describe the definition of this symbol.
Definition Elf.h:128
const Section * get_section() const
Accesses the properties that describe the definition of this symbol.
Definition Elf.h:125
Visibility get_visibility() const
Access the binding and visibility of this symbol.
Definition Elf.h:150
Type get_type() const
Accesses the type of this symbol.
Definition Elf.h:109
Symbol & set_visibility(Visibility visibility)
Access the binding and visibility of this symbol.
Definition Elf.h:143
Symbol & define(const Section *section, uint64_t offset, uint32_t size)
Accesses the properties that describe the definition of this symbol.
Definition Elf.h:116
Symbol & set_type(Type type)
Accesses the type of this symbol.
Definition Elf.h:105
bool is_defined() const
Accesses the properties that describe the definition of this symbol.
Definition Elf.h:122
Symbol & set_name(const std::string &name)
Accesses the name of this symbol.
Definition Elf.h:94
Symbol & set_binding(Binding binding)
Access the binding and visibility of this symbol.
Definition Elf.h:139
const std::string & get_name() const
Accesses the name of this symbol.
Definition Elf.h:98
uint32_t get_size() const
Accesses the properties that describe the definition of this symbol.
Definition Elf.h:131
Binding get_binding() const
Access the binding and visibility of this symbol.
Definition Elf.h:147
auto begin(reverse_adaptor< T > i)
Definition Util.h:471
auto end(reverse_adaptor< T > i)
Definition Util.h:476
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
unsigned __INT64_TYPE__ uint64_t
signed __INT64_TYPE__ int64_t
unsigned __INT8_TYPE__ uint8_t
unsigned __INT16_TYPE__ uint16_t
unsigned __INT32_TYPE__ uint32_t