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