Flutter Engine
The Flutter Engine
image_snapshot.h
Go to the documentation of this file.
1// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_IMAGE_SNAPSHOT_H_
6#define RUNTIME_VM_IMAGE_SNAPSHOT_H_
7
8#include <memory>
9#include <utility>
10
11#include "platform/assert.h"
12#include "platform/utils.h"
13#include "vm/allocation.h"
15#include "vm/datastream.h"
16#include "vm/elf.h"
17#include "vm/globals.h"
18#include "vm/growable_array.h"
19#include "vm/hash_map.h"
20#include "vm/object.h"
21#include "vm/reusable_handles.h"
24
25#if defined(DEBUG)
26#define SNAPSHOT_BACKTRACE
27#endif
28
29namespace dart {
30
31// Forward declarations.
32class BitsContainer;
33class Code;
34class Dwarf;
35class Elf;
36class Instructions;
37class Object;
38
40 public:
41 explicit Image(const void* raw_memory)
42 : Image(reinterpret_cast<uword>(raw_memory)) {}
43 explicit Image(const uword raw_memory)
44 : raw_memory_(raw_memory),
45 snapshot_size_(FieldValue(raw_memory, HeaderField::ImageSize)),
46 extra_info_(ExtraInfo(raw_memory_, snapshot_size_)) {
48 }
49
50 // Even though an Image is read-only memory, we must return a void* here.
51 // All objects in an Image are pre-marked, though, so the GC will not attempt
52 // to change the returned memory.
53 void* object_start() const {
54 return reinterpret_cast<void*>(raw_memory_ + kHeaderSize);
55 }
56
57 uword object_size() const { return snapshot_size_ - kHeaderSize; }
58
59 bool contains(uword address) const {
60 uword start = reinterpret_cast<uword>(object_start());
61 return address >= start && (address - start < object_size());
62 }
63
64 // Returns the address of the BSS section, or nullptr if one is not available.
65 // Only has meaning for instructions images from precompiled snapshots.
66 uword* bss() const;
67
68 // Returns the relocated address of the isolate's instructions, or 0 if
69 // one is not available. Only has meaning for instructions images from
70 // precompiled snapshots.
72
73 // Returns the GNU build ID, or nullptr if not available. See
74 // build_id_length() for the length of the returned buffer. Only has meaning
75 // for instructions images from precompiled snapshots.
76 const uint8_t* build_id() const;
77
78 // Returns the length of the GNU build ID returned by build_id(). Only has
79 // meaning for instructions images from precompiled snapshots.
80 intptr_t build_id_length() const;
81
82 // Returns whether this instructions section was compiled to ELF. Only has
83 // meaning for instructions images from precompiled snapshots.
84 bool compiled_to_elf() const;
85
86 private:
87 // Word-sized fields in an Image object header.
88 enum class HeaderField : intptr_t {
89 // The size of the image (total of header and payload).
90 ImageSize,
91 // The offset of the InstructionsSection object in the image. Note this
92 // offset is from the start of the _image_, _not_ from its payload start,
93 // so we can detect images without an InstructionsSection by a 0 value here.
94 InstructionsSectionOffset,
95 // If adding more fields, updating kHeaderFields below. (However, more
96 // fields _can't_ be added on 64-bit architectures, see the restrictions
97 // on kHeaderSize below.)
98 };
99
100 // Number of fields described by the HeaderField enum.
101 static constexpr intptr_t kHeaderFields =
102 static_cast<intptr_t>(HeaderField::InstructionsSectionOffset) + 1;
103
104 static uword FieldValue(uword raw_memory, HeaderField field) {
105 return reinterpret_cast<const uword*>(
106 raw_memory)[static_cast<intptr_t>(field)];
107 }
108
109 // Constants used to denote special values for the offsets in the Image
110 // object header and the fields of the InstructionsSection object.
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;
115
116 // The size of the Image object header.
117 //
118 // Note: Image::kHeaderSize is _not_ an architecture-dependent constant,
119 // and so there is no compiler::target::Image::kHeaderSize.
120 static constexpr intptr_t kHeaderSize = kObjectStartAlignment;
121 // Explicitly double-checking kHeaderSize is never changed. Increasing the
122 // Image header size would mean objects would not start at a place expected
123 // by parts of the VM (like the GC) that use Image pages as Pages.
124 static_assert(kHeaderSize == kObjectStartAlignment,
125 "Image page cannot be used as Page");
126 // Make sure that the number of fields in the Image header fit both on the
127 // host and target architectures.
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");
132
133 // We don't use a handle or the tagged pointer because this object cannot be
134 // moved in memory by the GC.
135 static const UntaggedInstructionsSection* ExtraInfo(const uword raw_memory,
136 const uword size);
137
138 // Most internal uses would cast this to uword, so just store it as such.
139 const uword raw_memory_;
140 const intptr_t snapshot_size_;
141 const UntaggedInstructionsSection* const extra_info_;
142
143 // For access to private constants.
145 friend class BitsContainer;
146 friend class BlobImageWriter;
147 friend class ImageWriter;
148
150};
151
153 public:
154 ImageReader(const uint8_t* data_image, const uint8_t* instructions_image);
155
156 ApiErrorPtr VerifyAlignment() const;
157
158 ONLY_IN_PRECOMPILED(uword GetBareInstructionsAt(uint32_t offset) const);
159 ONLY_IN_PRECOMPILED(uword GetBareInstructionsEnd() const);
160 InstructionsPtr GetInstructionsAt(uint32_t offset) const;
161 ObjectPtr GetObjectAt(uint32_t offset) const;
162
163 private:
164 const uint8_t* data_image_;
165 const uint8_t* instructions_image_;
166
167 DISALLOW_COPY_AND_ASSIGN(ImageReader);
168};
169
171 public:
173 ObjectOffsetPair(ObjectPtr obj, int32_t off) : object(obj), offset(off) {}
174
176 int32_t offset;
177};
178
180 public:
181 // Typedefs needed for the DirectChainedHashMap template.
182 typedef ObjectPtr Key;
183 typedef int32_t Value;
185
186 static Key KeyOf(Pair kv) { return kv.object; }
187 static Value ValueOf(Pair kv) { return kv.offset; }
188 static uword Hash(Key key);
189 static inline bool IsKeyEqual(Pair pair, Key key);
190};
191
193
194// A command which instructs the image writer to emit something into the ".text"
195// segment.
196//
197// For now this supports
198//
199// * emitting the instructions of a [Code] object
200// * emitting a trampoline of a certain size
201// * emitting a padding of a certain size
202//
204 enum Opcode {
208 };
209
214
216 uint8_t* trampoline_bytes,
217 intptr_t trampoline_length)
220 insert_trampoline_bytes({trampoline_bytes, trampoline_length}) {}
221
226
227 // The offset (relative to the very first [ImageWriterCommand]) we expect
228 // this [ImageWriterCommand] to have.
230
232 union {
233 struct {
234 CodePtr code;
236 struct {
237 uint8_t* buffer;
240
241 struct {
244 };
245};
246
247#if defined(DART_PRECOMPILER)
248template <typename T>
249class Trie : public ZoneAllocated {
250 public:
251 // Returns whether [key] is a valid trie key (that is, a C string that
252 // contains only characters for which charIndex returns a non-negative value).
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;
256 }
257 return true;
258 }
259
260 // Adds a binding of [key] to [value] in [trie]. Assumes that the string in
261 // [key] is a valid trie key and does not already have a value in [trie].
262 //
263 // If [trie] is nullptr, then a new trie is created and a pointer to the new
264 // trie is returned. Otherwise, [trie] will be returned.
265 static Trie<T>* AddString(Zone* zone,
266 Trie<T>* trie,
267 const char* key,
268 const T* value);
269
270 // Adds a binding of [key] to [value]. Assumes that the string in [key] is a
271 // valid trie key and does not already have a value in this trie.
272 void AddString(Zone* zone, const char* key, const T* value) {
273 AddString(zone, this, key, value);
274 }
275
276 // Looks up the value stored for [key] in [trie]. If one is not found, then
277 // nullptr is returned.
278 //
279 // If [end] is not nullptr, then the longest prefix of [key] that is a valid
280 // trie key prefix will be used for the lookup and the value pointed to by
281 // [end] is set to the index after that prefix. Otherwise, the whole [key]
282 // is used.
283 static const T* Lookup(const Trie<T>* trie,
284 const char* key,
285 intptr_t* end = nullptr);
286
287 // Looks up the value stored for [key]. If one is not found, then nullptr is
288 // returned.
289 //
290 // If [end] is not nullptr, then the longest prefix of [key] that is a valid
291 // trie key prefix will be used for the lookup and the value pointed to by
292 // [end] is set to the index after that prefix. Otherwise, the whole [key]
293 // is used.
294 const T* Lookup(const char* key, intptr_t* end = nullptr) const {
295 return Lookup(this, key, end);
296 }
297
298 private:
299 // Currently, only the following characters can appear in obfuscated names:
300 // '_', '@', '0-9', 'a-z', 'A-Z'
301 static constexpr intptr_t kNumValidChars = 64;
302
303 Trie() {
304 for (intptr_t i = 0; i < kNumValidChars; i++) {
305 children_[i] = nullptr;
306 }
307 }
308
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;
315 return -1;
316 }
317
318 const T* value_ = nullptr;
319 Trie<T>* children_[kNumValidChars];
320};
321
322template <typename T>
323Trie<T>* Trie<T>::AddString(Zone* zone,
324 Trie<T>* trie,
325 const char* key,
326 const T* value) {
327 ASSERT(key != nullptr);
328 if (trie == nullptr) {
329 trie = new (zone) Trie<T>();
330 }
331 if (*key == '\0') {
332 ASSERT(trie->value_ == nullptr);
333 trie->value_ = value;
334 } else {
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);
339 }
340
341 return trie;
342}
343
344template <typename T>
345const T* Trie<T>::Lookup(const Trie<T>* trie, const char* key, intptr_t* end) {
346 intptr_t i = 0;
347 for (; key[i] != '\0'; i++) {
348 auto const index = ChildIndex(key[i]);
349 ASSERT(index < kNumValidChars);
350 if (index < 0) {
351 if (end == nullptr) return nullptr;
352 break;
353 }
354 // Still find the longest valid trie prefix when no stored value.
355 if (trie == nullptr) continue;
356 trie = trie->children_[index];
357 }
358 if (end != nullptr) {
359 *end = i;
360 }
361 if (trie == nullptr) return nullptr;
362 return trie->value_;
363}
364#endif
365
366class ImageWriter : public ValueObject {
367 public:
368#if defined(DART_PRECOMPILER)
369 ImageWriter(Thread* thread,
370 bool generates_assembly,
371 const Trie<const char>* deobfuscation_trie = nullptr);
372#else
373 ImageWriter(Thread* thread, bool generates_assembly);
374#endif
375 virtual ~ImageWriter() {}
376
377 // Alignment constants used in writing ELF or assembly snapshots.
378
379 // BSS sections contain word-sized data.
380 static constexpr intptr_t kBssAlignment = compiler::target::kWordSize;
381 // ROData sections contain objects wrapped in an Image object.
382 static constexpr intptr_t kRODataAlignment = kObjectStartAlignment;
383 // Text sections contain objects (even in bare instructions mode) wrapped
384 // in an Image object.
385 static constexpr intptr_t kTextAlignment = kObjectStartAlignment;
386
388 next_data_offset_ = Image::kHeaderSize;
389 next_text_offset_ = Image::kHeaderSize;
390#if defined(DART_PRECOMPILER)
391 if (FLAG_precompiled_mode) {
392 // We reserve space for the initial InstructionsSection object. It is
393 // manually serialized since it includes offsets to other snapshot parts.
394 // It contains all the payloads which start directly after the header.
396 }
397#endif
398 objects_.Clear();
399 instructions_.Clear();
400 }
401
402 // Will start preparing the ".text" segment by interpreting the provided
403 // [ImageWriterCommand]s.
405
406 bool IsROSpace() const {
411 }
412 int32_t GetTextOffsetFor(InstructionsPtr instructions, CodePtr code);
413#if defined(SNAPSHOT_BACKTRACE)
414 uint32_t GetDataOffsetFor(ObjectPtr raw_object, ObjectPtr raw_parent);
415#else
416 uint32_t GetDataOffsetFor(ObjectPtr raw_object);
417#endif
418
419 uint32_t AddBytesToData(uint8_t* bytes, intptr_t length);
420
421 void Write(NonStreamingWriteStream* clustered_stream, bool vm);
422 intptr_t data_size() const { return next_data_offset_; }
423 intptr_t text_size() const { return next_text_offset_; }
424 intptr_t GetTextObjectCount() const;
425 void GetTrampolineInfo(intptr_t* count, intptr_t* size) const;
426
428
430 profile_writer_ = profile_writer;
431 }
432
434
435 void TraceInstructions(const Instructions& instructions);
436
437 static intptr_t SizeInSnapshot(ObjectPtr object);
438 static intptr_t SizeInSnapshot(const Object& object) {
439 return SizeInSnapshot(object.ptr());
440 }
441
442 // Returns nullptr if there is no profile writer.
443 const char* ObjectTypeForProfile(const Object& object) const;
444 static const char* TagObjectTypeAsReadOnly(Zone* zone, const char* type);
445
446 enum class ProgramSection {
447 Text, // Instructions.
448 Data, // Read-only data.
449 Bss, // Statically allocated variables initialized at load.
450 BuildId, // GNU build ID (when applicable)
451 // Adjust kNumProgramSections below to use last enum value added.
452 };
453
454 static constexpr intptr_t kNumProgramSections =
455 static_cast<int>(ProgramSection::BuildId) + 1;
456
457#if defined(DART_PRECOMPILER)
458 // Returns a predetermined label for the given section in the VM isolate
459 // (if vm is true) or application isolate (otherwise) section. Some sections
460 // are shared by both.
461 static constexpr intptr_t SectionLabel(ProgramSection section, bool vm) {
462 // Both vm and isolate share the build id section.
463 const bool shared = section == ProgramSection::BuildId;
464 // The initial 1 is to ensure the result is positive.
465 return 1 + 2 * static_cast<int>(section) + ((shared || vm) ? 0 : 1);
466 }
467
468 static Trie<const char>* CreateReverseObfuscationTrie(Thread* thread);
469 static const char* Deobfuscate(Zone* zone,
470 const Trie<const char>* trie,
471 const char* str);
472#endif
473
474 protected:
475 virtual void WriteBss(bool vm) = 0;
476 virtual void WriteROData(NonStreamingWriteStream* clustered_stream, bool vm);
477 void WriteText(bool vm);
478
479 // Returns the standard Dart dynamic symbol name for the given VM isolate (if
480 // vm is true) or application isolate (otherwise) section. Some sections are
481 // shared by both.
482 static const char* SectionSymbol(ProgramSection section, bool vm);
483
485 intptr_t size,
486 bool is_canonical = false);
487 static uword GetMarkedTags(const Object& obj);
488
491
493 InstructionsData(InstructionsPtr insns, CodePtr code, intptr_t text_offset)
494 : raw_insns_(insns),
496 text_offset_(text_offset),
497 trampoline_bytes(nullptr),
499
501 intptr_t trampoline_length,
502 intptr_t text_offset)
503 : raw_insns_(nullptr),
504 raw_code_(nullptr),
505 text_offset_(text_offset),
508
509 union {
510 InstructionsPtr raw_insns_;
512 };
513 union {
514 CodePtr raw_code_;
515 const Code* code_;
516 };
517 intptr_t text_offset_;
518
521 };
522
523 struct ObjectData {
524#if defined(SNAPSHOT_BACKTRACE)
525 explicit ObjectData(ObjectPtr raw_obj, ObjectPtr raw_parent)
526 : raw_obj(raw_obj),
527 raw_parent(raw_parent),
530 ObjectData(uint8_t* buf, intptr_t length)
531 : bytes({buf, length}),
532 raw_parent(Object::null()),
535#else
537 : raw_obj(raw_obj),
540 ObjectData(uint8_t* buf, intptr_t length)
541 : bytes({buf, length}),
544#endif
545
546 union {
547 struct {
548 uint8_t* buf;
549 intptr_t length;
552 const Object* obj;
553 };
554#if defined(SNAPSHOT_BACKTRACE)
555 union {
556 ObjectPtr raw_parent;
557 const Object* parent;
558 };
559#endif
560 uint8_t flags;
561
562 bool is_object() const { return IsObjectField::decode(flags); }
563 bool is_original_object() const {
565 }
566
567 void set_is_object(bool value) {
569 }
570
574 };
575
576 // Methods abstracting out the particulars of the underlying concrete writer.
577
578 // Marks the entrance into a particular ProgramSection for either the VM
579 // isolate (if vm is true) or application isolate (if not). Returns false if
580 // this section should not be written.
582 bool vm,
583 intptr_t alignment,
584 intptr_t* alignment_padding = nullptr) = 0;
585 // Marks the exit from a particular ProgramSection, allowing subclasses to
586 // do any post-writing work.
587 virtual void ExitSection(ProgramSection name, bool vm, intptr_t size) = 0;
588 // Writes a prologue to the text section that describes how to interpret
589 // Dart stack frames using DWARF's Call Frame Information (CFI).
590 virtual void FrameUnwindPrologue() = 0;
591 // Writes an epilogue to the text section that marks the end of instructions
592 // covered by the CFI information in the prologue.
593 virtual void FrameUnwindEpilogue() = 0;
594 // Writes a target uword-sized value to the section contents.
595 virtual intptr_t WriteTargetWord(word value) = 0;
596 // Writes a sequence of bytes of length [size] from address [bytes] to the
597 // section contents.
598 virtual intptr_t WriteBytes(const void* bytes, intptr_t size) = 0;
599 // Pads the section contents to a given alignment with zeroes.
600 virtual intptr_t Align(intptr_t alignment,
601 intptr_t offset,
602 intptr_t position) = 0;
603#if defined(DART_PRECOMPILER)
604 // Writes a target word-sized value that depends on the final relocated
605 // addresses of the sections named by the two symbols. If T is the final
606 // relocated address of the target section and S is the final relocated
607 // address of the source, the final value is:
608 // (T + target_offset + target_addend) - (S + source_offset)
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;
614 // Writes a target word-sized value that contains the relocated address
615 // pointed to by the given symbol.
616 virtual intptr_t RelocatedAddress(intptr_t section_offset,
617 intptr_t label) = 0;
618 // Creates a static symbol for the given Code object when appropriate.
619 virtual void AddCodeSymbol(const Code& code,
620 const char* symbol,
621 intptr_t section_offset) = 0;
622 // Creates a static symbol for a read-only data object when appropriate.
623 virtual void AddDataSymbol(const char* symbol,
624 intptr_t section_offset,
625 size_t size) = 0;
626
627 // Overloaded convenience versions of the above virtual methods.
628
629 // An overload of Relocation where the target and source offsets and
630 // target addend are 0.
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);
635 }
636#endif
637 // Writes a fixed-sized value of type T to the section contents.
638 template <typename T>
639 intptr_t WriteFixed(T value) {
640 return WriteBytes(&value, sizeof(value));
641 }
642 // Like Align, but instead of padding with zeroes, the appropriate break
643 // instruction for the target architecture is used.
644 intptr_t AlignWithBreakInstructions(intptr_t alignment, intptr_t offset);
645
647 Zone* const zone_;
652
653#if defined(DART_PRECOMPILER)
654 class SnapshotTextObjectNamer : ValueObject {
655 public:
656 explicit SnapshotTextObjectNamer(Zone* zone,
657 const Trie<const char>* deobfuscation_trie,
658 bool for_assembly)
659 : zone_(ASSERT_NOTNULL(zone)),
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) {}
670
671 const char* StubNameForType(const AbstractType& type) const;
672
673 // Returns a unique name for text data to use in symbols. The name is
674 // not assembly-safe and must be appropriately quoted in assembly output.
675 // Assumes that code in the InstructionsData has been allocated a handle.
676 const char* SnapshotNameFor(const InstructionsData& data);
677 // Returns a unique name for read-only data to use in symbols. The name is
678 // not assembly-safe and must be appropriately quoted in assembly output.
679 // Assumes that the ObjectData has already been converted to object handles.
680 const char* SnapshotNameFor(const ObjectData& data);
681
682 private:
683 // Returns a unique name for the given code or read-only data object for use
684 // in symbols. The name is not assembly-safe and must be appropriately
685 // quoted in assembly output.
686 const char* SnapshotNameFor(const Object& object);
687 // Adds a non-unique name for the given object to the given buffer.
688 void AddNonUniqueNameFor(BaseTextBuffer* buffer, const Object& object);
689 // Modifies the symbol name in the buffer as needed for assembly use.
690 void ModifyForAssembly(BaseTextBuffer* buffer);
691
692 Zone* const zone_;
693 const Trie<const char>* const deobfuscation_trie_;
694 Library& lib_;
695 Class& cls_;
696 Function& parent_;
697 Object& owner_;
698 String& string_;
699 Instructions& insns_;
700 ObjectStore* const store_;
701 // Used to decide whether we need to add a uniqueness suffix.
702 bool for_assembly_;
703 CStringIntMap usage_count_;
704
705 DISALLOW_COPY_AND_ASSIGN(SnapshotTextObjectNamer);
706 };
707
708 SnapshotTextObjectNamer namer_;
709
710 // Reserve two positive labels for each of the ProgramSection values (one for
711 // vm, one for isolate).
712 intptr_t next_label_ = 1 + 2 * kNumProgramSections;
713#endif
714
717 const char* const image_type_;
718 const char* const instructions_section_type_;
719 const char* const instructions_type_;
720 const char* const trampoline_type_;
721 const char* const padding_type_;
722
723 template <class T>
725
726 private:
727 static intptr_t SizeInSnapshotForBytes(intptr_t length);
728
730};
731
732#if defined(DART_PRECOMPILER)
733static_assert(ImageWriter::SectionLabel(ImageWriter::ProgramSection::Bss,
734 /*vm=*/true) == Elf::kVmBssLabel,
735 "unexpected label for VM BSS section");
736static_assert(ImageWriter::SectionLabel(ImageWriter::ProgramSection::Bss,
737 /*vm=*/false) == Elf::kIsolateBssLabel,
738 "unexpected label for isolate BSS section");
739static_assert(ImageWriter::SectionLabel(ImageWriter::ProgramSection::BuildId,
740 /*vm=*/true) == Elf::kBuildIdLabel,
741 "unexpected label for build id section");
742static_assert(ImageWriter::SectionLabel(ImageWriter::ProgramSection::BuildId,
743 /*vm=*/false) == Elf::kBuildIdLabel,
744 "unexpected label for build id section");
745
746#define AutoTraceImage(object, section_offset, stream) \
747 TraceImageObjectScope<std::remove_pointer<decltype(stream)>::type> \
748 AutoTraceImageObjectScopeVar##__COUNTER__(this, section_offset, stream, \
749 object);
750
751template <typename T>
752class TraceImageObjectScope : ValueObject {
753 public:
754 TraceImageObjectScope(ImageWriter* writer,
755 intptr_t section_offset,
756 const T* stream,
757 const Object& object)
758 : writer_(ASSERT_NOTNULL(writer)),
759 stream_(ASSERT_NOTNULL(stream)),
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) {}
764
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_);
773 }
774
775 private:
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_;
782
783 DISALLOW_COPY_AND_ASSIGN(TraceImageObjectScope);
784};
785
786class AssemblyImageWriter : public ImageWriter {
787 public:
788 AssemblyImageWriter(Thread* thread,
789 BaseWriteStream* stream,
790 const Trie<const char>* deobfuscation_trie = nullptr,
791 bool strip = false,
792 Elf* debug_elf = nullptr);
793 void Finalize();
794
795 private:
796 virtual void WriteBss(bool vm);
797 virtual void WriteROData(NonStreamingWriteStream* clustered_stream, bool vm);
798
799 virtual bool EnterSection(ProgramSection section,
800 bool vm,
801 intptr_t alignment,
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,
807 intptr_t offset,
808 intptr_t position);
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) {
815 // Cannot calculate snapshot-relative addresses in assembly snapshots.
816 return WriteTargetWord(Image::kNoRelocatedAddress);
817 }
818 virtual void FrameUnwindPrologue();
819 virtual void FrameUnwindEpilogue();
820 virtual void AddCodeSymbol(const Code& code,
821 const char* symbol,
822 intptr_t offset);
823 virtual void AddDataSymbol(const char* symbol, intptr_t offset, size_t size);
824
825 BaseWriteStream* const assembly_stream_;
826 Dwarf* const assembly_dwarf_;
827 Elf* const debug_elf_;
828
829 // Used in Relocation to output "(.)" for relocations involving the current
830 // section position.
831 intptr_t current_section_label_ = 0;
832
833 // Used for creating local symbols for code and data objects in the
834 // debugging info, if separately written.
835 ZoneGrowableArray<Elf::SymbolData>* current_symbols_ = nullptr;
836
837 // Maps labels to the appropriate symbol names for relocations and DWARF
838 // output.
839 IntMap<const char*> label_to_symbol_name_;
840
841 DISALLOW_COPY_AND_ASSIGN(AssemblyImageWriter);
842};
843#endif
844
846 public:
847#if defined(DART_PRECOMPILER)
848 BlobImageWriter(Thread* thread,
849 NonStreamingWriteStream* vm_instructions,
850 NonStreamingWriteStream* isolate_instructions,
851 const Trie<const char>* deobfuscation_trie = nullptr,
852 Elf* debug_elf = nullptr,
853 Elf* elf = nullptr);
854#else
855 BlobImageWriter(Thread* thread,
856 NonStreamingWriteStream* vm_instructions,
857 NonStreamingWriteStream* isolate_instructions,
858 Elf* debug_elf = nullptr,
859 Elf* elf = nullptr);
860#endif
861
862 private:
863 virtual void WriteBss(bool vm);
864 virtual void WriteROData(NonStreamingWriteStream* clustered_stream, bool vm);
865
866 virtual bool EnterSection(ProgramSection section,
867 bool vm,
868 intptr_t alignment,
869 intptr_t* alignment_padding = nullptr);
870 virtual void ExitSection(ProgramSection name, bool vm, intptr_t size);
871 virtual intptr_t WriteTargetWord(word value);
872 virtual intptr_t WriteBytes(const void* bytes, intptr_t size);
873 virtual intptr_t Align(intptr_t alignment,
874 intptr_t offset,
875 intptr_t position);
876 // TODO(rmacnak): Generate .debug_frame / .eh_frame / .arm.exidx to
877 // provide unwinding information.
878 virtual void FrameUnwindPrologue() {}
879 virtual void FrameUnwindEpilogue() {}
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);
889 }
890 virtual void AddCodeSymbol(const Code& code,
891 const char* symbol,
892 intptr_t offset);
893 virtual void AddDataSymbol(const char* symbol, intptr_t offset, size_t size);
894
895 // Set on section entrance to a new array containing the relocations for the
896 // current section.
897 ZoneGrowableArray<Elf::Relocation>* current_relocations_ = nullptr;
898 // Set on section entrance to a new array containing the local symbol data
899 // for the current section.
900 ZoneGrowableArray<Elf::SymbolData>* current_symbols_ = nullptr;
901#endif
902
903 NonStreamingWriteStream* const vm_instructions_;
904 NonStreamingWriteStream* const isolate_instructions_;
905 Elf* const elf_;
906 Elf* const debug_elf_;
907
908 // Set on section entrance to the stream that should be used by the writing
909 // methods.
910 NonStreamingWriteStream* current_section_stream_ = nullptr;
911
912 DISALLOW_COPY_AND_ASSIGN(BlobImageWriter);
913};
914
915} // namespace dart
916
917#endif // RUNTIME_VM_IMAGE_SNAPSHOT_H_
Align
int count
Definition: FontMgrTest.cpp:50
TArray< uint32_t > Key
static void encode(uint8_t output[16], const uint32_t input[4])
Definition: SkMD5.cpp:240
#define ASSERT_NOTNULL(ptr)
Definition: assert.h:323
GLenum type
static constexpr T decode(S value)
Definition: bitfield.h:171
static constexpr S update(T value, S original)
Definition: bitfield.h:188
static constexpr S encode(T value)
Definition: bitfield.h:165
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)
bool IsROSpace() const
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)
intptr_t AlignWithBreakInstructions(intptr_t alignment, intptr_t offset)
virtual ~ImageWriter()
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)
Thread *const thread_
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
void WriteText(bool vm)
uword object_size() const
uword * bss() 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()
Definition: isolate.h:539
ObjectOffsetPair Pair
static bool IsKeyEqual(Pair pair, Key key)
static Key KeyOf(Pair kv)
static uword Hash(Key key)
static Value ValueOf(Pair kv)
static ObjectPtr null()
Definition: object.h:433
static Object & Handle()
Definition: object.h:407
static constexpr bool IsAligned(T x, uintptr_t alignment, uintptr_t offset=0)
Definition: utils.h:92
#define ASSERT(E)
glong glong end
uint8_t value
size_t length
static constexpr intptr_t kWordSize
Definition: runtime_api.h:274
Definition: dart_vm.cc:33
static constexpr intptr_t kObjectStartAlignment
const char *const name
int32_t classid_t
Definition: globals.h:524
uintptr_t uword
Definition: globals.h:501
intptr_t word
Definition: globals.h:500
const intptr_t cid
constexpr intptr_t kWordSize
Definition: globals.h:509
DirectChainedHashMap< ObjectOffsetTrait > ObjectOffsetMap
static int8_t data[kExtLength]
dictionary commands
Definition: dom.py:171
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
Definition: switches.h:126
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
Definition: switches.h:259
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:581
#define T
Definition: precompiler.cc:65
SeparatedVector2 offset
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
InstructionsData(InstructionsPtr insns, CodePtr code, intptr_t text_offset)
InstructionsData(uint8_t *trampoline_bytes, intptr_t trampoline_length, intptr_t text_offset)
ObjectData(uint8_t *buf, intptr_t length)
ObjectData(ObjectPtr raw_obj)
struct dart::ImageWriter::ObjectData::@163::@165 bytes
ObjectOffsetPair(ObjectPtr obj, int32_t off)