5#ifndef RUNTIME_VM_IMAGE_SNAPSHOT_H_
6#define RUNTIME_VM_IMAGE_SNAPSHOT_H_
26#define SNAPSHOT_BACKTRACE
41 explicit Image(
const void* raw_memory)
42 :
Image(reinterpret_cast<
uword>(raw_memory)) {}
44 : raw_memory_(raw_memory),
45 snapshot_size_(FieldValue(raw_memory, HeaderField::ImageSize)),
46 extra_info_(ExtraInfo(raw_memory_, snapshot_size_)) {
54 return reinterpret_cast<void*
>(raw_memory_ + kHeaderSize);
88 enum class HeaderField : intptr_t {
94 InstructionsSectionOffset,
101 static constexpr intptr_t kHeaderFields =
102 static_cast<intptr_t
>(HeaderField::InstructionsSectionOffset) + 1;
104 static uword FieldValue(
uword raw_memory, HeaderField field) {
105 return reinterpret_cast<const uword*
>(
106 raw_memory)[
static_cast<intptr_t
>(field)];
111 static constexpr intptr_t kNoInstructionsSection = 0;
112 static constexpr intptr_t kNoBssSection = 0;
113 static constexpr intptr_t kNoRelocatedAddress = 0;
114 static constexpr intptr_t kNoBuildId = 0;
125 "Image page cannot be used as Page");
128 static_assert(kHeaderFields *
kWordSize <= kHeaderSize,
129 "Too many fields in Image header for host architecture");
131 "Too many fields in Image header for target architecture");
135 static const UntaggedInstructionsSection* ExtraInfo(
const uword raw_memory,
139 const uword raw_memory_;
140 const intptr_t snapshot_size_;
141 const UntaggedInstructionsSection*
const extra_info_;
154 ImageReader(
const uint8_t* data_image,
const uint8_t* instructions_image);
164 const uint8_t* data_image_;
165 const uint8_t* instructions_image_;
216 uint8_t* trampoline_bytes,
217 intptr_t trampoline_length)
247#if defined(DART_PRECOMPILER)
249class Trie :
public ZoneAllocated {
253 static bool IsValidKey(
const char*
key) {
254 for (intptr_t
i = 0;
key[
i] !=
'\0';
i++) {
255 if (ChildIndex(
key[
i]) < 0)
return false;
265 static Trie<T>* AddString(Zone* zone,
272 void AddString(Zone* zone,
const char*
key,
const T*
value) {
283 static const T* Lookup(
const Trie<T>* trie,
285 intptr_t* end =
nullptr);
294 const T* Lookup(
const char*
key, intptr_t* end =
nullptr)
const {
295 return Lookup(
this,
key, end);
301 static constexpr intptr_t kNumValidChars = 64;
304 for (intptr_t
i = 0;
i < kNumValidChars;
i++) {
305 children_[
i] =
nullptr;
309 static intptr_t ChildIndex(
char c) {
310 if (c ==
'_')
return 0;
311 if (c ==
'@')
return 1;
312 if (c >=
'0' && c <=
'9')
return (
'9' - c) + 2;
313 if (c >=
'a' && c <=
'z')
return (
'z' - c) + 12;
314 if (c >=
'A' && c <=
'Z')
return (
'Z' - c) + 38;
318 const T* value_ =
nullptr;
319 Trie<T>* children_[kNumValidChars];
323Trie<T>* Trie<T>::AddString(Zone* zone,
328 if (trie ==
nullptr) {
329 trie =
new (zone) Trie<T>();
332 ASSERT(trie->value_ ==
nullptr);
333 trie->value_ =
value;
335 auto const index = ChildIndex(*
key);
336 ASSERT(index >= 0 && index < kNumValidChars);
337 trie->children_[index] =
338 AddString(zone, trie->children_[index],
key + 1,
value);
345const T* Trie<T>::Lookup(
const Trie<T>* trie,
const char*
key, intptr_t* end) {
347 for (;
key[
i] !=
'\0';
i++) {
348 auto const index = ChildIndex(
key[
i]);
349 ASSERT(index < kNumValidChars);
351 if (end ==
nullptr)
return nullptr;
355 if (trie ==
nullptr)
continue;
356 trie = trie->children_[index];
358 if (end !=
nullptr) {
361 if (trie ==
nullptr)
return nullptr;
368#if defined(DART_PRECOMPILER)
370 bool generates_assembly,
371 const Trie<const char>* deobfuscation_trie =
nullptr);
390#if defined(DART_PRECOMPILER)
391 if (FLAG_precompiled_mode) {
413#if defined(SNAPSHOT_BACKTRACE)
457#if defined(DART_PRECOMPILER)
461 static constexpr intptr_t SectionLabel(
ProgramSection section,
bool vm) {
465 return 1 + 2 *
static_cast<int>(section) + ((shared || vm) ? 0 : 1);
468 static Trie<const char>* CreateReverseObfuscationTrie(
Thread* thread);
469 static const char* Deobfuscate(
Zone* zone,
470 const Trie<const char>* trie,
486 bool is_canonical =
false);
502 intptr_t text_offset)
524#if defined(SNAPSHOT_BACKTRACE)
527 raw_parent(raw_parent),
554#if defined(SNAPSHOT_BACKTRACE)
584 intptr_t* alignment_padding =
nullptr) = 0;
600 virtual intptr_t
Align(intptr_t alignment,
602 intptr_t position) = 0;
603#if defined(DART_PRECOMPILER)
609 virtual intptr_t Relocation(intptr_t section_offset,
610 intptr_t source_label,
611 intptr_t source_offset,
612 intptr_t target_label,
613 intptr_t target_offset) = 0;
616 virtual intptr_t RelocatedAddress(intptr_t section_offset,
619 virtual void AddCodeSymbol(
const Code&
code,
621 intptr_t section_offset) = 0;
623 virtual void AddDataSymbol(
const char* symbol,
624 intptr_t section_offset,
631 intptr_t Relocation(intptr_t section_offset,
632 intptr_t source_label,
633 intptr_t target_label) {
634 return Relocation(section_offset, source_label, 0, target_label, 0);
638 template <
typename T>
653#if defined(DART_PRECOMPILER)
656 explicit SnapshotTextObjectNamer(
Zone* zone,
657 const Trie<const char>* deobfuscation_trie,
660 deobfuscation_trie_(deobfuscation_trie),
668 for_assembly_(for_assembly),
669 usage_count_(zone) {}
686 const char* SnapshotNameFor(
const Object&
object);
693 const Trie<const char>*
const deobfuscation_trie_;
708 SnapshotTextObjectNamer namer_;
727 static intptr_t SizeInSnapshotForBytes(intptr_t
length);
732#if defined(DART_PRECOMPILER)
734 true) == Elf::kVmBssLabel,
735 "unexpected label for VM BSS section");
737 false) == Elf::kIsolateBssLabel,
738 "unexpected label for isolate BSS section");
740 true) == Elf::kBuildIdLabel,
741 "unexpected label for build id section");
743 false) == Elf::kBuildIdLabel,
744 "unexpected label for build id section");
746#define AutoTraceImage(object, section_offset, stream) \
747 TraceImageObjectScope<std::remove_pointer<decltype(stream)>::type> \
748 AutoTraceImageObjectScopeVar##__COUNTER__(this, section_offset, stream, \
755 intptr_t section_offset,
760 section_offset_(section_offset),
761 start_offset_(stream_->Position() - section_offset),
762 object_type_(writer->ObjectTypeForProfile(object)),
763 object_name_(object.IsString() ? object.ToCString() : nullptr) {}
765 ~TraceImageObjectScope() {
766 if (writer_->profile_writer_ ==
nullptr)
return;
767 ASSERT(writer_->IsROSpace());
768 writer_->profile_writer_->SetObjectTypeAndName(
769 {writer_->offset_space_, start_offset_}, object_type_, object_name_);
770 writer_->profile_writer_->AttributeBytesTo(
771 {writer_->offset_space_, start_offset_},
772 stream_->Position() - section_offset_ - start_offset_);
776 ImageWriter*
const writer_;
777 const T*
const stream_;
778 const intptr_t section_offset_;
779 const intptr_t start_offset_;
780 const char*
const object_type_;
781 const char*
const object_name_;
786class AssemblyImageWriter :
public ImageWriter {
788 AssemblyImageWriter(Thread* thread,
790 const Trie<const char>* deobfuscation_trie =
nullptr,
792 Elf* debug_elf =
nullptr);
796 virtual void WriteBss(
bool vm);
797 virtual void WriteROData(NonStreamingWriteStream* clustered_stream,
bool vm);
799 virtual bool EnterSection(ProgramSection section,
802 intptr_t* alignment_padding =
nullptr);
803 virtual void ExitSection(ProgramSection
name,
bool vm, intptr_t
size);
804 virtual intptr_t WriteTargetWord(
word value);
805 virtual intptr_t WriteBytes(
const void* bytes, intptr_t
size);
806 virtual intptr_t
Align(intptr_t alignment,
809 virtual intptr_t Relocation(intptr_t section_offset,
810 intptr_t source_label,
811 intptr_t source_offset,
812 intptr_t target_label,
813 intptr_t target_offset);
814 virtual intptr_t RelocatedAddress(intptr_t section_offset, intptr_t label) {
816 return WriteTargetWord(Image::kNoRelocatedAddress);
818 virtual void FrameUnwindPrologue();
819 virtual void FrameUnwindEpilogue();
820 virtual void AddCodeSymbol(
const Code&
code,
823 virtual void AddDataSymbol(
const char* symbol, intptr_t
offset,
size_t size);
825 BaseWriteStream*
const assembly_stream_;
826 Dwarf*
const assembly_dwarf_;
827 Elf*
const debug_elf_;
831 intptr_t current_section_label_ = 0;
835 ZoneGrowableArray<Elf::SymbolData>* current_symbols_ =
nullptr;
839 IntMap<const char*> label_to_symbol_name_;
847#if defined(DART_PRECOMPILER)
851 const Trie<const char>* deobfuscation_trie =
nullptr,
852 Elf* debug_elf =
nullptr,
858 Elf* debug_elf =
nullptr,
869 intptr_t* alignment_padding =
nullptr);
873 virtual intptr_t
Align(intptr_t alignment,
880#if defined(DART_PRECOMPILER)
881 virtual intptr_t Relocation(intptr_t section_offset,
882 intptr_t source_label,
883 intptr_t source_offset,
884 intptr_t target_label,
885 intptr_t target_offset);
886 virtual intptr_t RelocatedAddress(intptr_t section_offset, intptr_t label) {
887 return ImageWriter::Relocation(section_offset,
888 Elf::Relocation::kSnapshotRelative, label);
890 virtual void AddCodeSymbol(
const Code&
code,
893 virtual void AddDataSymbol(
const char* symbol, intptr_t
offset,
size_t size);
897 ZoneGrowableArray<Elf::Relocation>* current_relocations_ =
nullptr;
900 ZoneGrowableArray<Elf::SymbolData>* current_symbols_ =
nullptr;
903 NonStreamingWriteStream*
const vm_instructions_;
904 NonStreamingWriteStream*
const isolate_instructions_;
906 Elf*
const debug_elf_;
910 NonStreamingWriteStream* current_section_stream_ =
nullptr;
static void encode(uint8_t output[16], const uint32_t input[4])
#define ASSERT_NOTNULL(ptr)
static constexpr T decode(S value)
static constexpr S update(T value, S original)
static constexpr S encode(T value)
virtual void WriteBss(bool vm)
virtual bool EnterSection(ProgramSection section, bool vm, intptr_t alignment, intptr_t *alignment_padding=nullptr)
virtual void WriteROData(NonStreamingWriteStream *clustered_stream, bool vm)
virtual void ExitSection(ProgramSection name, bool vm, intptr_t size)
BlobImageWriter(Thread *thread, NonStreamingWriteStream *vm_instructions, NonStreamingWriteStream *isolate_instructions, Elf *debug_elf=nullptr, Elf *elf=nullptr)
virtual void FrameUnwindPrologue()
virtual intptr_t Align(intptr_t alignment, intptr_t offset, intptr_t position)
virtual void FrameUnwindEpilogue()
virtual intptr_t WriteBytes(const void *bytes, intptr_t size)
virtual intptr_t WriteTargetWord(word value)
ObjectPtr GetObjectAt(uint32_t offset) const
InstructionsPtr GetInstructionsAt(uint32_t offset) const
ONLY_IN_PRECOMPILED(uword GetBareInstructionsEnd() const)
ApiErrorPtr VerifyAlignment() const
ONLY_IN_PRECOMPILED(uword GetBareInstructionsAt(uint32_t offset) const)
ImageReader(const uint8_t *data_image, const uint8_t *instructions_image)
intptr_t GetTextObjectCount() const
intptr_t next_text_offset_
virtual void FrameUnwindEpilogue()=0
static intptr_t SizeInSnapshot(ObjectPtr object)
V8SnapshotProfileWriter * profile_writer_
const char *const instructions_type_
intptr_t WriteFixed(T value)
GrowableArray< ObjectData > objects_
static intptr_t SizeInSnapshot(const Object &object)
void TraceInstructions(const Instructions &instructions)
virtual intptr_t Align(intptr_t alignment, intptr_t offset, intptr_t position)=0
intptr_t next_data_offset_
void Write(NonStreamingWriteStream *clustered_stream, bool vm)
GrowableArray< InstructionsData > instructions_
void SetProfileWriter(V8SnapshotProfileWriter *profile_writer)
void DumpInstructionStats()
static constexpr intptr_t kRODataAlignment
virtual void FrameUnwindPrologue()=0
const char *const padding_type_
static const char * TagObjectTypeAsReadOnly(Zone *zone, const char *type)
void ClearProfileWriter()
intptr_t AlignWithBreakInstructions(intptr_t alignment, intptr_t offset)
intptr_t text_size() const
void DumpInstructionsSizes()
virtual void ExitSection(ProgramSection name, bool vm, intptr_t size)=0
const char *const image_type_
static constexpr intptr_t kTextAlignment
virtual void WriteROData(NonStreamingWriteStream *clustered_stream, bool vm)
ImageWriter(Thread *thread, bool generates_assembly)
const char *const instructions_section_type_
virtual intptr_t WriteBytes(const void *bytes, intptr_t size)=0
static constexpr intptr_t kBssAlignment
static constexpr intptr_t kNumProgramSections
void GetTrampolineInfo(intptr_t *count, intptr_t *size) const
virtual void WriteBss(bool vm)=0
int32_t GetTextOffsetFor(InstructionsPtr instructions, CodePtr code)
const char * ObjectTypeForProfile(const Object &object) const
virtual intptr_t WriteTargetWord(word value)=0
uint32_t GetDataOffsetFor(ObjectPtr raw_object)
intptr_t data_size() const
void PrepareForSerialization(GrowableArray< ImageWriterCommand > *commands)
virtual bool EnterSection(ProgramSection name, bool vm, intptr_t alignment, intptr_t *alignment_padding=nullptr)=0
const char *const trampoline_type_
uint32_t AddBytesToData(uint8_t *bytes, intptr_t length)
static const char * SectionSymbol(ProgramSection section, bool vm)
static uword GetMarkedTags(classid_t cid, intptr_t size, bool is_canonical=false)
friend class TraceImageObjectScope
uword object_size() const
bool contains(uword address) const
const uint8_t * build_id() const
friend class AssemblyImageWriter
Image(const uword raw_memory)
intptr_t build_id_length() const
friend class BitsContainer
void * object_start() const
bool compiled_to_elf() const
Image(const void *raw_memory)
uword instructions_relocated_address() const
static IsolateGroup * Current()
static bool IsKeyEqual(Pair pair, Key key)
static Key KeyOf(Pair kv)
static uword Hash(Key key)
static Value ValueOf(Pair kv)
static constexpr bool IsAligned(T x, uintptr_t alignment, uintptr_t offset=0)
static constexpr intptr_t kWordSize
static constexpr intptr_t kObjectStartAlignment
constexpr intptr_t kWordSize
DirectChainedHashMap< ObjectOffsetTrait > ObjectOffsetMap
static int8_t data[kExtLength]
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
@ InsertInstructionOfCode
@ InsertBytesOfTrampoline
ImageWriterCommand(intptr_t expected_offset, uint8_t *trampoline_bytes, intptr_t trampoline_length)
struct dart::ImageWriterCommand::@154::@158 insert_padding
ImageWriterCommand(intptr_t expected_offset, intptr_t padding_length)
ImageWriterCommand(intptr_t expected_offset, CodePtr code)
struct dart::ImageWriterCommand::@154::@156 insert_instruction_of_code
struct dart::ImageWriterCommand::@154::@157 insert_trampoline_bytes
const Instructions * insns_
InstructionsData(InstructionsPtr insns, CodePtr code, intptr_t text_offset)
intptr_t trampoline_length
InstructionsPtr raw_insns_
InstructionsData(uint8_t *trampoline_bytes, intptr_t trampoline_length, intptr_t text_offset)
uint8_t * trampoline_bytes
ObjectData(uint8_t *buf, intptr_t length)
bool is_original_object() const
ObjectData(ObjectPtr raw_obj)
void set_is_object(bool value)
struct dart::ImageWriter::ObjectData::@163::@165 bytes
ObjectOffsetPair(ObjectPtr obj, int32_t off)