| // 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/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 ELF 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 Dwarf; |
| class ProgramTable; |
| class Section; |
| class SectionTable; |
| class SymbolTable; |
| |
| class Elf : public ZoneAllocated { |
| public: |
| enum class Type { |
| // A snapshot that should include segment contents. |
| Snapshot, |
| // Separately compiled debugging information that should not include |
| // most segment contents. |
| DebugInfo, |
| }; |
| |
| Elf(Zone* zone, BaseWriteStream* stream, Type type, Dwarf* dwarf = nullptr); |
| |
| static constexpr intptr_t kPageSize = kElfPageSize; |
| |
| bool IsStripped() const { return dwarf_ == nullptr; } |
| |
| Zone* zone() const { return zone_; } |
| const Dwarf* dwarf() const { return dwarf_; } |
| Dwarf* dwarf() { return dwarf_; } |
| const SymbolTable& symtab() const { |
| ASSERT(symtab_ != nullptr); |
| return *symtab_; |
| } |
| const SectionTable& section_table() const { return *section_table_; } |
| |
| // Stores the information needed to appropriately generate a |
| // relocation from the target to the source at the given section offset. |
| struct Relocation { |
| size_t size_in_bytes; |
| intptr_t section_offset; |
| intptr_t source_label; |
| intptr_t source_offset; |
| intptr_t target_label; |
| intptr_t target_offset; |
| |
| // Used when the corresponding offset is relative from the location of the |
| // relocation itself. |
| static constexpr intptr_t kSelfRelative = -1; |
| // Used when the corresponding offset is relative to the start of the |
| // snapshot. |
| static constexpr intptr_t kSnapshotRelative = -2; |
| |
| Relocation(size_t size_in_bytes, |
| intptr_t section_offset, |
| intptr_t source_label, |
| intptr_t source_offset, |
| intptr_t target_label, |
| intptr_t target_offset) |
| : size_in_bytes(size_in_bytes), |
| section_offset(section_offset), |
| source_label(source_label), |
| source_offset(source_offset), |
| target_label(target_label), |
| target_offset(target_offset) { |
| // Other than special values, all labels should be positive. |
| ASSERT(source_label > 0 || source_label == kSelfRelative || |
| source_label == kSnapshotRelative); |
| ASSERT(target_label > 0 || target_label == kSelfRelative || |
| target_label == kSnapshotRelative); |
| } |
| }; |
| |
| // Stores the information needed to appropriately generate a symbol |
| // during finalization. |
| struct SymbolData { |
| const char* name; |
| intptr_t type; |
| intptr_t offset; |
| size_t size; |
| // A positive unique ID only used internally in the Dart VM, not part of |
| // the Elf output. |
| intptr_t label; |
| |
| SymbolData(const char* name, |
| intptr_t type, |
| intptr_t offset, |
| size_t size, |
| intptr_t label) |
| : name(name), type(type), offset(offset), size(size), label(label) { |
| ASSERT(label > 0); |
| } |
| }; |
| |
| // Must be the same value as the values returned by ImageWriter::SectionLabel |
| // for the appropriate section and vm values. |
| static constexpr intptr_t kVmBssLabel = 5; |
| static constexpr intptr_t kIsolateBssLabel = 6; |
| static constexpr intptr_t kBuildIdLabel = 7; |
| |
| void AddText(const char* name, |
| intptr_t label, |
| const uint8_t* bytes, |
| intptr_t size, |
| const ZoneGrowableArray<Relocation>* relocations, |
| const ZoneGrowableArray<SymbolData>* symbol); |
| void AddROData(const char* name, |
| intptr_t label, |
| const uint8_t* bytes, |
| intptr_t size, |
| const ZoneGrowableArray<Relocation>* relocations, |
| const ZoneGrowableArray<SymbolData>* symbols); |
| |
| void Finalize(); |
| |
| private: |
| 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(); |
| |
| Zone* const zone_; |
| BaseWriteStream* const unwrapped_stream_; |
| const Type type_; |
| |
| // If nullptr, then the ELF file should be stripped of static information like |
| // the static symbol table (and its corresponding string table). |
| Dwarf* const dwarf_; |
| |
| // 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. |
| SymbolTable* symtab_ = nullptr; |
| |
| friend class SectionTable; // For section name static fields. |
| }; |
| |
| #endif // DART_PRECOMPILER |
| |
| } // namespace dart |
| |
| #endif // RUNTIME_VM_ELF_H_ |