| // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #ifndef RUNTIME_VM_ELF_H_ |
| #define RUNTIME_VM_ELF_H_ |
| |
| #include "platform/globals.h" |
| |
| #if defined(DART_PRECOMPILER) |
| #include "vm/allocation.h" |
| #include "vm/compiler/runtime_api.h" |
| #include "vm/datastream.h" |
| #include "vm/growable_array.h" |
| #include "vm/so_writer.h" |
| #include "vm/zone.h" |
| #endif |
| |
| namespace dart { |
| |
| // The max page size on all supported architectures. Used to determine |
| // the alignment of load segments, so that they are guaranteed page-aligned, |
| // and no shared object section or segment should have a larger alignment. |
| #if defined(DART_TARGET_OS_LINUX) && defined(TARGET_ARCH_ARM64) |
| // Some Linux distributions on ARM64 select 64 KB page size. |
| // Follow LLVM (https://reviews.llvm.org/D25079) and set maximum page size |
| // to 64 KB for ARM64 Linux builds. |
| static constexpr intptr_t kElfPageSize = 64 * KB; |
| #elif defined(DART_TARGET_OS_ANDROID) && defined(TARGET_ARCH_IS_64_BIT) |
| static constexpr intptr_t kElfPageSize = 64 * KB; |
| #else |
| static constexpr intptr_t kElfPageSize = 16 * KB; |
| #endif |
| |
| #if defined(DART_PRECOMPILER) |
| |
| class ProgramTable; |
| class SectionTable; |
| class ElfSymbolTable; |
| |
| class ElfWriter : public SharedObjectWriter { |
| public: |
| ElfWriter(Zone* zone, |
| BaseWriteStream* stream, |
| Type type, |
| Dwarf* dwarf = nullptr); |
| |
| static constexpr intptr_t kPageSize = kElfPageSize; |
| intptr_t page_size() const override { return kPageSize; } |
| |
| Output output() const override { return Output::Elf; } |
| |
| const ElfSymbolTable& symtab() const { |
| ASSERT(symtab_ != nullptr); |
| return *symtab_; |
| } |
| const SectionTable& section_table() const { return *section_table_; } |
| |
| void AddText(const char* name, |
| intptr_t label, |
| const uint8_t* bytes, |
| intptr_t size, |
| const SharedObjectWriter::RelocationArray* relocations, |
| const SharedObjectWriter::SymbolDataArray* symbol) override; |
| void AddROData(const char* name, |
| intptr_t label, |
| const uint8_t* bytes, |
| intptr_t size, |
| const SharedObjectWriter::RelocationArray* relocations, |
| const SharedObjectWriter::SymbolDataArray* symbols) override; |
| |
| void Finalize() override; |
| |
| void AssertConsistency(const SharedObjectWriter* debug) const override { |
| if (auto* const debug_elf = debug->AsElfWriter()) { |
| AssertConsistency(this, debug_elf); |
| } else { |
| FATAL("Expected both snapshot and debug to be ELF"); |
| } |
| } |
| |
| const ElfWriter* AsElfWriter() const override { return this; } |
| |
| private: |
| static void AssertConsistency(const ElfWriter* snapshot, |
| const ElfWriter* debug_info); |
| |
| static constexpr const char kBuildIdNoteName[] = ".note.gnu.build-id"; |
| static constexpr const char kTextName[] = ".text"; |
| static constexpr const char kDataName[] = ".rodata"; |
| static constexpr const char kBssName[] = ".bss"; |
| static constexpr const char kDynamicTableName[] = ".dynamic"; |
| |
| void CreateBSS(); |
| void GenerateBuildId(); |
| void InitializeSymbolTables(); |
| void FinalizeDwarfSections(); |
| void FinalizeEhFrame(); |
| void ComputeOffsets(); |
| |
| // Contains all sections that will have entries in the section header table. |
| SectionTable* const section_table_; |
| |
| // Contains all segments in the program header table. Set after finalizing |
| // the section table. |
| ProgramTable* program_table_ = nullptr; |
| |
| // The static tables are always created for use in relocation calculations, |
| // even though they may not end up in the final ELF file. |
| ElfSymbolTable* symtab_ = nullptr; |
| |
| friend class SectionTable; // For section name static fields. |
| }; |
| |
| #endif // DART_PRECOMPILER |
| |
| } // namespace dart |
| |
| #endif // RUNTIME_VM_ELF_H_ |