mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 20:51:50 +00:00
bc21edaf17
ARM64 Mac has 16k pages, so we need snapshot parts to be 16k aligned for our ELF loader to load them via mmap. TEST=ci Bug: https://github.com/dart-lang/sdk/issues/42773 Change-Id: Ifa3d70e453ea72883d821e48cfc76b0d983391f2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193821 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Siva Annamalai <asiva@google.com>
155 lines
5.5 KiB
C++
155 lines
5.5 KiB
C++
// 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 "vm/allocation.h"
|
|
#include "vm/compiler/runtime_api.h"
|
|
#include "vm/datastream.h"
|
|
#include "vm/growable_array.h"
|
|
#include "vm/zone.h"
|
|
|
|
namespace dart {
|
|
|
|
class Dwarf;
|
|
class ElfWriteStream;
|
|
class Section;
|
|
class Segment;
|
|
class StringTable;
|
|
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 = 16 * KB;
|
|
static constexpr uword kNoSectionStart = 0;
|
|
|
|
bool IsStripped() const { return dwarf_ == nullptr; }
|
|
|
|
Zone* zone() { return zone_; }
|
|
const Dwarf* dwarf() const { return dwarf_; }
|
|
Dwarf* dwarf() { return dwarf_; }
|
|
|
|
// Returns the relocated address for the symbol with the given name or
|
|
// kNoSectionStart if the symbol was not found.
|
|
uword SymbolAddress(const char* name) const;
|
|
|
|
// What the next memory offset for an appropriately aligned section would be.
|
|
//
|
|
// Only used by AssemblyImageWriter and BlobImageWriter methods.
|
|
intptr_t NextMemoryOffset(intptr_t alignment) const;
|
|
intptr_t AddText(const char* name, const uint8_t* bytes, intptr_t size);
|
|
intptr_t AddROData(const char* name, const uint8_t* bytes, intptr_t size);
|
|
void AddDebug(const char* name, const uint8_t* bytes, intptr_t size);
|
|
|
|
// Adds a local symbol for the given offset and size in the "current" section,
|
|
// that is, the section index for the symbol is for the next added section.
|
|
void AddLocalSymbol(const char* name,
|
|
intptr_t type,
|
|
intptr_t offset,
|
|
intptr_t size);
|
|
|
|
void Finalize();
|
|
|
|
private:
|
|
static constexpr const char* kBuildIdNoteName = ".note.gnu.build-id";
|
|
|
|
static Section* CreateBSS(Zone* zone, Type type, intptr_t size);
|
|
|
|
// Adds the section and also creates a PT_LOAD segment for the section if it
|
|
// is an allocated section.
|
|
//
|
|
// For allocated sections, if symbol_name is provided, a symbol for the
|
|
// section will be added to the dynamic table (if allocated) and static
|
|
// table (if not stripped) during finalization.
|
|
//
|
|
// Returns the memory offset if the section is allocated.
|
|
intptr_t AddSection(Section* section,
|
|
const char* name,
|
|
const char* symbol_name = nullptr);
|
|
// Replaces [old_section] with [new_section] in all appropriate places. If the
|
|
// section is allocated, the memory size of the section must be the same as
|
|
// the original to ensure any already-calculated memory offsets are unchanged.
|
|
void ReplaceSection(Section* old_section, Section* new_section);
|
|
|
|
void AddStaticSymbol(const char* name,
|
|
intptr_t binding,
|
|
intptr_t type,
|
|
intptr_t section_index,
|
|
intptr_t address,
|
|
intptr_t size);
|
|
void AddDynamicSymbol(const char* name,
|
|
intptr_t binding,
|
|
intptr_t type,
|
|
intptr_t section_index,
|
|
intptr_t address,
|
|
intptr_t size);
|
|
|
|
Segment* LastLoadSegment() const;
|
|
const Section* FindSectionForAddress(intptr_t address) const;
|
|
Section* CreateBuildIdNote(const void* description_bytes,
|
|
intptr_t description_length);
|
|
Section* GenerateFinalBuildId();
|
|
|
|
void AddSectionSymbols();
|
|
void FinalizeDwarfSections();
|
|
void FinalizeProgramTable();
|
|
void ComputeFileOffsets();
|
|
|
|
void WriteHeader(ElfWriteStream* stream);
|
|
void WriteSectionTable(ElfWriteStream* stream);
|
|
void WriteProgramTable(ElfWriteStream* stream);
|
|
void WriteSections(ElfWriteStream* stream);
|
|
|
|
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_;
|
|
|
|
// We always create a BSS section for all Elf files, though it may be NOBITS
|
|
// if this is separate debugging information.
|
|
Section* const bss_;
|
|
|
|
// All our strings would fit in a single page. However, we use separate
|
|
// .shstrtab and .dynstr to work around a bug in Android's strip utility.
|
|
StringTable* const shstrtab_;
|
|
StringTable* const dynstrtab_;
|
|
SymbolTable* const dynsym_;
|
|
|
|
// The static tables are lazily created when static symbols are added.
|
|
StringTable* strtab_ = nullptr;
|
|
SymbolTable* symtab_ = nullptr;
|
|
|
|
// We always create a GNU build ID for all Elf files. In order to create
|
|
// the appropriate offset to it in an InstructionsSection object, we create an
|
|
// initial build ID section as a placeholder and then replace that section
|
|
// during finalization once we have the information to calculate the real one.
|
|
Section* build_id_;
|
|
|
|
GrowableArray<Section*> sections_;
|
|
GrowableArray<Segment*> segments_;
|
|
intptr_t memory_offset_;
|
|
intptr_t section_table_file_offset_ = -1;
|
|
intptr_t section_table_file_size_ = -1;
|
|
intptr_t program_table_file_offset_ = -1;
|
|
intptr_t program_table_file_size_ = -1;
|
|
};
|
|
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_ELF_H_
|