1 | // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #ifndef RUNTIME_VM_ELF_H_ |
6 | #define RUNTIME_VM_ELF_H_ |
7 | |
8 | #include "vm/allocation.h" |
9 | #include "vm/compiler/runtime_api.h" |
10 | #include "vm/datastream.h" |
11 | #include "vm/growable_array.h" |
12 | #include "vm/zone.h" |
13 | |
14 | namespace dart { |
15 | |
16 | class Dwarf; |
17 | class ElfWriteStream; |
18 | class Section; |
19 | class Segment; |
20 | class StringTable; |
21 | class SymbolTable; |
22 | |
23 | class Elf : public ZoneAllocated { |
24 | public: |
25 | enum class Type { |
26 | // A snapshot that should include segment contents. |
27 | Snapshot, |
28 | // Separately compiled debugging information that should not include |
29 | // most segment contents. |
30 | DebugInfo, |
31 | }; |
32 | |
33 | Elf(Zone* zone, |
34 | StreamingWriteStream* stream, |
35 | Type type, |
36 | Dwarf* dwarf = nullptr); |
37 | |
38 | static const intptr_t kPageSize = 4096; |
39 | |
40 | bool IsStripped() const { return dwarf_ == nullptr; } |
41 | |
42 | Zone* zone() { return zone_; } |
43 | const Dwarf* dwarf() const { return dwarf_; } |
44 | Dwarf* dwarf() { return dwarf_; } |
45 | |
46 | uword BssStart(bool vm) const; |
47 | |
48 | // What the next memory offset for a kPageSize-aligned section would be. |
49 | // |
50 | // Only used by BlobImageWriter::WriteText() to determine the memory offset |
51 | // for the text section before it is added. |
52 | intptr_t NextMemoryOffset() const; |
53 | intptr_t AddNoBits(const char* name, const uint8_t* bytes, intptr_t size); |
54 | intptr_t AddText(const char* name, const uint8_t* bytes, intptr_t size); |
55 | intptr_t AddROData(const char* name, const uint8_t* bytes, intptr_t size); |
56 | void AddDebug(const char* name, const uint8_t* bytes, intptr_t size); |
57 | |
58 | void Finalize(); |
59 | |
60 | private: |
61 | static Section* CreateBSS(Zone* zone, Type type, intptr_t size); |
62 | |
63 | // Adds the section and also creates a PT_LOAD segment for the section if it |
64 | // is an allocated section. |
65 | // |
66 | // For allocated sections, if symbol_name is provided, a symbol for the |
67 | // section will be added to the dynamic table (if allocated) and static |
68 | // table (if not stripped) during finalization. |
69 | // |
70 | // Returns the memory offset if the section is allocated. |
71 | intptr_t AddSection(Section* section, |
72 | const char* name, |
73 | const char* symbol_name = nullptr); |
74 | void AddStaticSymbol(const char* name, |
75 | intptr_t info, |
76 | intptr_t section_index, |
77 | intptr_t address, |
78 | intptr_t size); |
79 | void AddDynamicSymbol(const char* name, |
80 | intptr_t info, |
81 | intptr_t section_index, |
82 | intptr_t address, |
83 | intptr_t size); |
84 | |
85 | Segment* LastLoadSegment() const; |
86 | const Section* FindSectionForAddress(intptr_t address) const; |
87 | Section* GenerateBuildId(); |
88 | |
89 | void AddSectionSymbols(); |
90 | void FinalizeDwarfSections(); |
91 | void FinalizeProgramTable(); |
92 | void ComputeFileOffsets(); |
93 | |
94 | void (ElfWriteStream* stream); |
95 | void WriteSectionTable(ElfWriteStream* stream); |
96 | void WriteProgramTable(ElfWriteStream* stream); |
97 | void WriteSections(ElfWriteStream* stream); |
98 | |
99 | Zone* const zone_; |
100 | StreamingWriteStream* const unwrapped_stream_; |
101 | const Type type_; |
102 | |
103 | // If nullptr, then the ELF file should be stripped of static information like |
104 | // the static symbol table (and its corresponding string table). |
105 | Dwarf* const dwarf_; |
106 | |
107 | // We always create a BSS section for all Elf files, though it may be NOBITS |
108 | // if this is separate debugging information. |
109 | Section* const bss_; |
110 | |
111 | // All our strings would fit in a single page. However, we use separate |
112 | // .shstrtab and .dynstr to work around a bug in Android's strip utility. |
113 | StringTable* const shstrtab_; |
114 | StringTable* const dynstrtab_; |
115 | SymbolTable* const dynsym_; |
116 | |
117 | // The static tables are lazily created when static symbols are added. |
118 | StringTable* strtab_ = nullptr; |
119 | SymbolTable* symtab_ = nullptr; |
120 | |
121 | GrowableArray<Section*> sections_; |
122 | GrowableArray<Segment*> segments_; |
123 | intptr_t memory_offset_; |
124 | intptr_t section_table_file_offset_ = -1; |
125 | intptr_t section_table_file_size_ = -1; |
126 | intptr_t program_table_file_offset_ = -1; |
127 | intptr_t program_table_file_size_ = -1; |
128 | }; |
129 | |
130 | } // namespace dart |
131 | |
132 | #endif // RUNTIME_VM_ELF_H_ |
133 | |