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 "platform/globals.h"
9
10#if defined(DART_PRECOMPILER)
11#include "vm/allocation.h"
12#include "vm/compiler/runtime_api.h"
13#include "vm/datastream.h"
14#include "vm/growable_array.h"
15#include "vm/zone.h"
16#endif
17
18namespace dart {
19
20// The max page size on all supported architectures. Used to determine
21// the alignment of load segments, so that they are guaranteed page-aligned,
22// and no ELF section or segment should have a larger alignment.
23#if defined(DART_TARGET_OS_LINUX) && defined(TARGET_ARCH_ARM64)
24// Some Linux distributions on ARM64 select 64 KB page size.
25// Follow LLVM (https://reviews.llvm.org/D25079) and set maximum page size
26// to 64 KB for ARM64 Linux builds.
27static constexpr intptr_t kElfPageSize = 64 * KB;
28#else
29static constexpr intptr_t kElfPageSize = 16 * KB;
30#endif
31
32#if defined(DART_PRECOMPILER)
33
34class Dwarf;
35class ProgramTable;
36class Section;
37class SectionTable;
38class SymbolTable;
39
40class Elf : public ZoneAllocated {
41 public:
42 enum class Type {
43 // A snapshot that should include segment contents.
44 Snapshot,
45 // Separately compiled debugging information that should not include
46 // most segment contents.
47 DebugInfo,
48 };
49
50 Elf(Zone* zone, BaseWriteStream* stream, Type type, Dwarf* dwarf = nullptr);
51
52 static constexpr intptr_t kPageSize = kElfPageSize;
53
54 bool IsStripped() const { return dwarf_ == nullptr; }
55
56 Zone* zone() const { return zone_; }
57 const Dwarf* dwarf() const { return dwarf_; }
58 Dwarf* dwarf() { return dwarf_; }
59 const SymbolTable& symtab() const {
60 ASSERT(symtab_ != nullptr);
61 return *symtab_;
62 }
63 const SectionTable& section_table() const { return *section_table_; }
64
65 // Stores the information needed to appropriately generate a
66 // relocation from the target to the source at the given section offset.
67 struct Relocation {
68 size_t size_in_bytes;
69 intptr_t section_offset;
70 intptr_t source_label;
71 intptr_t source_offset;
72 intptr_t target_label;
73 intptr_t target_offset;
74
75 // Used when the corresponding offset is relative from the location of the
76 // relocation itself.
77 static constexpr intptr_t kSelfRelative = -1;
78 // Used when the corresponding offset is relative to the start of the
79 // snapshot.
80 static constexpr intptr_t kSnapshotRelative = -2;
81
82 Relocation(size_t size_in_bytes,
83 intptr_t section_offset,
84 intptr_t source_label,
85 intptr_t source_offset,
86 intptr_t target_label,
87 intptr_t target_offset)
88 : size_in_bytes(size_in_bytes),
89 section_offset(section_offset),
90 source_label(source_label),
91 source_offset(source_offset),
92 target_label(target_label),
93 target_offset(target_offset) {
94 // Other than special values, all labels should be positive.
95 ASSERT(source_label > 0 || source_label == kSelfRelative ||
96 source_label == kSnapshotRelative);
97 ASSERT(target_label > 0 || target_label == kSelfRelative ||
98 target_label == kSnapshotRelative);
99 }
100 };
101
102 // Stores the information needed to appropriately generate a symbol
103 // during finalization.
104 struct SymbolData {
105 const char* name;
106 intptr_t type;
107 intptr_t offset;
108 size_t size;
109 // A positive unique ID only used internally in the Dart VM, not part of
110 // the Elf output.
111 intptr_t label;
112
113 SymbolData(const char* name,
114 intptr_t type,
115 intptr_t offset,
116 size_t size,
117 intptr_t label)
118 : name(name), type(type), offset(offset), size(size), label(label) {
119 ASSERT(label > 0);
120 }
121 };
122
123 // Must be the same value as the values returned by ImageWriter::SectionLabel
124 // for the appropriate section and vm values.
125 static constexpr intptr_t kVmBssLabel = 5;
126 static constexpr intptr_t kIsolateBssLabel = 6;
127 static constexpr intptr_t kBuildIdLabel = 7;
128
129 void AddText(const char* name,
130 intptr_t label,
131 const uint8_t* bytes,
132 intptr_t size,
133 const ZoneGrowableArray<Relocation>* relocations,
134 const ZoneGrowableArray<SymbolData>* symbol);
135 void AddROData(const char* name,
136 intptr_t label,
137 const uint8_t* bytes,
138 intptr_t size,
139 const ZoneGrowableArray<Relocation>* relocations,
140 const ZoneGrowableArray<SymbolData>* symbols);
141
142 void Finalize();
143
144 private:
145 static constexpr const char kBuildIdNoteName[] = ".note.gnu.build-id";
146 static constexpr const char kTextName[] = ".text";
147 static constexpr const char kDataName[] = ".rodata";
148 static constexpr const char kBssName[] = ".bss";
149 static constexpr const char kDynamicTableName[] = ".dynamic";
150
151 void CreateBSS();
152 void GenerateBuildId();
153 void InitializeSymbolTables();
154 void FinalizeDwarfSections();
155 void FinalizeEhFrame();
156 void ComputeOffsets();
157
158 Zone* const zone_;
159 BaseWriteStream* const unwrapped_stream_;
160 const Type type_;
161
162 // If nullptr, then the ELF file should be stripped of static information like
163 // the static symbol table (and its corresponding string table).
164 Dwarf* const dwarf_;
165
166 // Contains all sections that will have entries in the section header table.
167 SectionTable* const section_table_;
168
169 // Contains all segments in the program header table. Set after finalizing
170 // the section table.
171 ProgramTable* program_table_ = nullptr;
172
173 // The static tables are always created for use in relocation calculations,
174 // even though they may not end up in the final ELF file.
175 SymbolTable* symtab_ = nullptr;
176
177 friend class SectionTable; // For section name static fields.
178};
179
180#endif // DART_PRECOMPILER
181
182} // namespace dart
183
184#endif // RUNTIME_VM_ELF_H_
185

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com

source code of flutter_engine/third_party/dart/runtime/vm/elf.h