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");
130 static_assert(kHeaderFields * compiler::target::kWordSize <= kHeaderSize,
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) {
273 AddString(zone,
this,
key, 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;
598 virtual intptr_t
WriteBytes(
const void* bytes, intptr_t size) = 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),
661 lib_(Library::Handle(zone)),
662 cls_(Class::Handle(zone)),
663 parent_(Function::Handle(zone)),
664 owner_(Object::Handle(zone)),
665 string_(String::Handle(zone)),
666 insns_(Instructions::Handle(zone)),
667 store_(IsolateGroup::Current()->object_store()),
668 for_assembly_(for_assembly),
669 usage_count_(zone) {}
680 const char* SnapshotNameFor(
const ObjectData& data);
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,
789 BaseWriteStream* stream,
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);
872 virtual intptr_t
WriteBytes(
const void* bytes, intptr_t size);
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)
virtual void FrameUnwindPrologue()
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)
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)
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 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 const uint8_t buffer[]
static constexpr intptr_t kObjectStartAlignment
constexpr intptr_t kWordSize
DirectChainedHashMap< ObjectOffsetTrait > ObjectOffsetMap
struct dart::ImageWriterCommand::@153::@155 insert_instruction_of_code
@ InsertInstructionOfCode
@ InsertBytesOfTrampoline
ImageWriterCommand(intptr_t expected_offset, uint8_t *trampoline_bytes, intptr_t trampoline_length)
struct dart::ImageWriterCommand::@153::@157 insert_padding
struct dart::ImageWriterCommand::@153::@156 insert_trampoline_bytes
ImageWriterCommand(intptr_t expected_offset, intptr_t padding_length)
ImageWriterCommand(intptr_t expected_offset, CodePtr code)
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::@162::@164 bytes
ObjectOffsetPair(ObjectPtr obj, int32_t off)