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
14namespace dart {
15
16class Dwarf;
17class ElfWriteStream;
18class Section;
19class Segment;
20class StringTable;
21class SymbolTable;
22
23class 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 WriteHeader(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