28#if !defined(DART_PRECOMPILED_RUNTIME)
34#if defined(DART_PRECOMPILER)
36 print_instruction_stats,
38 "Print instruction statistics");
41 print_instructions_sizes_to,
43 "Print sizes of all instruction objects to the given file");
46const UntaggedInstructionsSection* Image::ExtraInfo(
const uword raw_memory,
48#if defined(DART_PRECOMPILED_RUNTIME)
49 auto const raw_value =
50 FieldValue(raw_memory, HeaderField::InstructionsSectionOffset);
51 if (raw_value != kNoInstructionsSection) {
52 ASSERT(raw_value >= kHeaderSize);
54 auto const layout =
reinterpret_cast<const UntaggedInstructionsSection*
>(
55 raw_memory + raw_value);
69#if defined(DART_PRECOMPILED_RUNTIME)
70 ASSERT(extra_info_ !=
nullptr);
72 ASSERT(extra_info_->bss_offset_ != 0);
76 return reinterpret_cast<uword*
>(raw_memory_ + extra_info_->bss_offset_);
83#if defined(DART_PRECOMPILED_RUNTIME)
84 ASSERT(extra_info_ !=
nullptr);
85 return extra_info_->instructions_relocated_address_;
87 return kNoRelocatedAddress;
92#if defined(DART_PRECOMPILED_RUNTIME)
93 ASSERT(extra_info_ !=
nullptr);
94 if (extra_info_->build_id_offset_ != kNoBuildId) {
95 auto const note =
reinterpret_cast<elf::Note*
>(
96 raw_memory_ + extra_info_->build_id_offset_);
97 return note->
data + note->name_size;
104#if defined(DART_PRECOMPILED_RUNTIME)
105 ASSERT(extra_info_ !=
nullptr);
106 if (extra_info_->build_id_offset_ != kNoBuildId) {
107 auto const note =
reinterpret_cast<elf::Note*
>(
108 raw_memory_ + extra_info_->build_id_offset_);
116#if defined(DART_PRECOMPILED_RUNTIME)
117 ASSERT(extra_info_ !=
nullptr);
121 return extra_info_->instructions_relocated_address_ != kNoRelocatedAddress;
137 for (
uword cursor = body; cursor <
end; cursor +=
sizeof(uint32_t)) {
150 if (
a->GetClassId() !=
b->GetClassId()) {
154 intptr_t heap_size =
a->untag()->HeapSize();
155 if (
b->untag()->HeapSize() != heap_size) {
164 return 0 == memcmp(
reinterpret_cast<const void*
>(body_a),
165 reinterpret_cast<const void*
>(body_b), body_size);
168#if !defined(DART_PRECOMPILED_RUNTIME)
169#if defined(DART_PRECOMPILER)
171 bool generates_assembly,
172 const Trie<const char>* deobfuscation_trie)
178 next_data_offset_(0),
179 next_text_offset_(0),
182#if defined(DART_PRECOMPILER)
187 image_type_(TagObjectTypeAsReadOnly(zone_,
"Image")),
188 instructions_section_type_(
189 TagObjectTypeAsReadOnly(zone_,
"InstructionsSection")),
190 instructions_type_(TagObjectTypeAsReadOnly(zone_,
"Instructions")),
191 trampoline_type_(TagObjectTypeAsReadOnly(zone_,
"Trampoline")),
192 padding_type_(TagObjectTypeAsReadOnly(zone_,
"Padding")) {
205 CodePtr
code =
inst.insert_instruction_of_code.code;
215 auto trampoline_bytes =
inst.insert_trampoline_bytes.buffer;
216 auto trampoline_length =
inst.insert_trampoline_bytes.buffer_length;
224 auto padding_length =
inst.insert_padding.padding_length;
254intptr_t ImageWriter::SizeInSnapshotForBytes(intptr_t
length) {
264 case kCompressedStackMapsCid: {
269 case kCodeSourceMapCid: {
272 raw_map->untag()->length_);
274 case kPcDescriptorsCid: {
277 raw_desc->untag()->length_);
279 case kInstructionsCid: {
284 case kOneByteStringCid: {
289 case kTwoByteStringCid: {
296 FATAL(
"Unsupported class %s in rodata section.\n", clazz.
ToCString());
302#if defined(SNAPSHOT_BACKTRACE)
311#if defined(SNAPSHOT_BACKTRACE)
320 const intptr_t snap_size = SizeInSnapshotForBytes(
length);
336 if (
data.trampoline_length != 0) {
351 klass =
object.
clazz();
353 auto const name_str =
name.ToCString();
362#if defined(DART_PRECOMPILER)
364 std::unique_ptr<CombinedCodeStatistics> instruction_stats(
369 if (
stats !=
nullptr) {
370 stats->AppendTo(instruction_stats.get());
373 instruction_stats->DumpStatistics();
382 intptr_t trampolines_total_size = 0;
389 const bool is_trampoline =
data.trampoline_length != 0;
391 trampolines_total_size +=
data.trampoline_length;
396 if (owner.IsFunction()) {
397 cls = Function::Cast(owner).Owner();
398 name = cls.ScrubbedName();
401 js.PrintPropertyStr(
"l", url);
402 js.PrintPropertyStr(
"c",
name);
403 }
else if (owner.IsClass()) {
405 name = cls.ScrubbedName();
408 js.PrintPropertyStr(
"l", url);
409 js.PrintPropertyStr(
"c",
name);
411 js.PrintProperty(
"n",
412 data.code_->QualifiedName(
418 if (trampolines_total_size != 0) {
420 js.PrintProperty(
"n",
"[Stub] Trampoline");
421 js.PrintProperty(
"s", trampolines_total_size);
429 if ((file_open ==
nullptr) || (file_write ==
nullptr) ||
430 (file_close ==
nullptr)) {
431 OS::PrintErr(
"warning: Could not access file callbacks.");
435 const char* filename = FLAG_print_instructions_sizes_to;
436 void*
file = file_open(filename,
true);
437 if (
file ==
nullptr) {
438 OS::PrintErr(
"warning: Failed to write instruction sizes: %s\n", filename);
443 intptr_t output_length = 0;
451 if (FLAG_print_instruction_stats) {
455 if (FLAG_print_instructions_sizes_to !=
nullptr) {
469 if (
data.trampoline_length != 0)
continue;
480 if (
data.is_object()) {
482#if defined(SNAPSHOT_BACKTRACE)
492 if (!
data.is_object()) {
493 const auto bytes =
data.bytes;
496#if defined(SNAPSHOT_BACKTRACE)
497 data.parent = &Object::null_object();
499 data.set_is_object(
true);
500 String::Cast(*
data.obj).Hash();
522 intptr_t section_start =
stream->Position();
525 stream->WriteWord(Image::kNoInstructionsSection);
527 stream->Align(Image::kHeaderSize);
529#if defined(DART_PRECOMPILER)
540 ASSERT(entry.is_object());
541 const Object& obj = *entry.obj;
542#if defined(DART_PRECOMPILER)
543 AutoTraceImage(obj, section_start,
stream);
544 const char* object_name = namer_.SnapshotNameFor(entry);
546 auto const object_start =
stream->Position();
552 if (obj.IsCompressedStackMaps()) {
554 const intptr_t payload_size =
map.payload_size();
555 stream->WriteFixed<uint32_t>(
556 map.ptr()->untag()->payload()->flags_and_size());
557 stream->WriteBytes(
map.ptr()->untag()->payload()->data(), payload_size);
558 }
else if (obj.IsCodeSourceMap()) {
564 }
else if (obj.IsPcDescriptors()) {
570 }
else if (obj.IsString()) {
571 const String& str = String::Cast(obj);
575#if !defined(HASH_IN_OBJECT_HEADER)
583 ?
static_cast<const void*
>(OneByteString::DataStart(str))
584 :
static_cast<const void*
>(TwoByteString::DataStart(str)),
590 FATAL(
"Unsupported class %s in rodata section.\n", clazz.
ToCString());
594#if defined(DART_PRECOMPILER)
595 AddDataSymbol(object_name, object_start,
stream->Position() - object_start);
608 bool is_canonical ) {
622 const intptr_t adjusted_size =
634#if defined(HASH_IN_OBJECT_HEADER)
635 tags = UntaggedObject::HashTag::update(obj.
ptr()->
untag()->GetHeaderHash(),
657#if (defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)) && \
658 defined(TARGET_ARCH_ARM64)
692#define EMIT_UNWIND_DIRECTIVES_PER_FUNCTION 1
696 const bool bare_instruction_payloads = FLAG_precompiled_mode;
699 intptr_t alignment_padding = 0;
701 &alignment_padding)) {
705 intptr_t text_offset = 0;
706#if defined(DART_PRECOMPILER)
722 : Image::kNoInstructionsSection);
724 text_offset +=
Align(Image::kHeaderSize, 0, text_offset);
727#if defined(DART_PRECOMPILER)
729 ASSERT(instructions_symbol !=
nullptr);
731 ASSERT(instructions_label > 0);
733 ASSERT(bss_symbol !=
nullptr);
739 instructions_symbol);
745 if (FLAG_precompiled_mode) {
746 const intptr_t section_header_length =
751 const intptr_t section_payload_length =
752 bare_instruction_payloads
755 const intptr_t section_size =
757 section_payload_length);
762 instructions_symbol);
764 section_size - section_payload_length);
765 const intptr_t element_offset =
id.nonce() - parent_id.
nonce();
771 if (bare_instruction_payloads) {
783 text_offset += Relocation(text_offset, instructions_label, bss_label);
785 text_offset += RelocatedAddress(text_offset, instructions_label);
787 text_offset += Relocation(text_offset, instructions_label,
790 const intptr_t section_contents_alignment =
791 bare_instruction_payloads
794 const intptr_t alignment_offset =
796 const intptr_t expected_size =
797 bare_instruction_payloads
801 Align(section_contents_alignment, alignment_offset, text_offset);
806#if !defined(EMIT_UNWIND_DIRECTIVES_PER_FUNCTION)
810#if defined(DART_PRECOMPILER)
815 uint8_t padding_bytes[64];
816 memset(&padding_bytes[0], 0,
sizeof(padding_bytes));
821 const bool is_trampoline =
data.trampoline_bytes !=
nullptr;
822 const bool is_padding =
823 data.trampoline_bytes ==
nullptr &&
data.trampoline_length != 0;
826#if defined(DART_PRECOMPILER)
827 const char* object_name = namer_.SnapshotNameFor(
data);
834 const intptr_t
size = (is_trampoline || is_padding)
835 ?
data.trampoline_length
839 const intptr_t element_offset =
id.nonce() - parent_id.
nonce();
848 delete[]
data.trampoline_bytes;
849 data.trampoline_bytes =
nullptr;
858 const intptr_t instr_start = text_offset;
859 const auto& insns = *
data.insns_;
864 if (!bare_instruction_payloads) {
869 text_offset +=
WriteFixed(insns.untag()->size_and_flags_);
879#if defined(DART_PRECOMPILER)
883 AddCodeSymbol(
code, object_name, text_offset);
886#if defined(EMIT_UNWIND_DIRECTIVES_PER_FUNCTION)
896 auto const payload_start =
897 reinterpret_cast<const uint8_t*
>(insns.PayloadStart());
901 const uword payload_size = insns.Size();
902 auto const payload_end = payload_start + payload_size;
903 auto cursor = payload_start;
904#if defined(DART_PRECOMPILER)
905 descriptors =
code.pc_descriptors();
907 descriptors, UntaggedPcDescriptors::kBSSRelocation);
910 ASSERT(FLAG_precompiled_mode);
911 auto const next_reloc_offset = iterator.
PcOffset();
912 auto const next_reloc_address = payload_start + next_reloc_offset;
917 text_offset +=
WriteBytes(cursor, next_reloc_address - cursor);
921 const auto target_offset =
924 text_offset += Relocation(text_offset, instructions_label, text_offset,
925 bss_label, target_offset);
929 text_offset +=
WriteBytes(cursor, payload_end - cursor);
935 const intptr_t alignment =
936 bare_instruction_payloads
942#if defined(EMIT_UNWIND_DIRECTIVES_PER_FUNCTION)
950 ASSERT(bare_instruction_payloads ||
958#if !defined(EMIT_UNWIND_DIRECTIVES_PER_FUNCTION)
967 intptr_t bytes_written = 0;
975#if defined(TARGET_ARCH_ARM)
979#elif defined(TARGET_ARCH_ARM64)
982 if (remaining != 0) {
986#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32) || \
987 defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
991#error Unexpected architecture.
995 return bytes_written;
998#if defined(DART_PRECOMPILER)
1001static constexpr const char* kSizeDirectives[] = {
".byte",
".2byte",
".long",
1004static constexpr const char* kWordDirective =
1007class DwarfAssemblyStream :
public DwarfWriteStream {
1009 explicit DwarfAssemblyStream(Zone* zone,
1011 const IntMap<const char*>& label_to_name)
1014 label_to_name_(label_to_name) {}
1016 void sleb128(intptr_t
value) { stream_->Printf(
".sleb128 %" Pd "\n",
value); }
1017 void uleb128(uintptr_t
value) {
1018 stream_->Printf(
".uleb128 %" Pd "\n",
value);
1020 void u1(uint8_t
value) {
1023 void u2(uint16_t
value) {
1026 void u4(uint32_t
value) {
1029 void u8(uint64_t
value) {
1032 void string(
const char* cstr) {
1033 stream_->Printf(
".string \"%s\"\n", cstr);
1037 const char*
const length_prefix_symbol =
1040 stream_->Printf(
"L%s_size = .L%s_end - .L%s_start\n",
prefix,
prefix,
1043 stream_->Printf(
"%s: %s L%s_size\n", length_prefix_symbol,
1047 stream_->Printf(
".L%s_start:\n",
prefix);
1049 stream_->Printf(
".L%s_end:\n",
prefix);
1051 void OffsetFromSymbol(intptr_t label, intptr_t
offset) {
1052 const char* symbol = label_to_name_.Lookup(label);
1053 ASSERT(symbol !=
nullptr);
1055 PrintNamedAddress(symbol);
1057 PrintNamedAddressWithOffset(symbol,
offset);
1062 void InitializeAbstractOrigins(intptr_t
size) {}
1063 void RegisterAbstractOrigin(intptr_t index) {
1065 stream_->Printf(
".Lfunc%" Pd ":\n", index);
1067 void AbstractOrigin(intptr_t index) {
1069 stream_->Printf(
"Ltemp%" Pd " = .Lfunc%" Pd " - %s\n", temp_, index,
1077 void AbbreviationsPrologue() {
1078#if defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
1079 stream_->WriteString(
".section __DWARF,__debug_abbrev,regular,debug\n");
1080#elif defined(DART_TARGET_OS_LINUX) || defined(DART_TARGET_OS_ANDROID) || \
1081 defined(DART_TARGET_OS_FUCHSIA)
1082 stream_->WriteString(
".section .debug_abbrev,\"\"\n");
1087 void DebugInfoPrologue() {
1088#if defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
1089 stream_->WriteString(
".section __DWARF,__debug_info,regular,debug\n");
1090#elif defined(DART_TARGET_OS_LINUX) || defined(DART_TARGET_OS_ANDROID) || \
1091 defined(DART_TARGET_OS_FUCHSIA)
1092 stream_->WriteString(
".section .debug_info,\"\"\n");
1097 stream_->Printf(
"%s:\n", kDebugInfoLabel);
1099 void LineNumberProgramPrologue() {
1100#if defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
1101 stream_->WriteString(
".section __DWARF,__debug_line,regular,debug\n");
1102#elif defined(DART_TARGET_OS_LINUX) || defined(DART_TARGET_OS_ANDROID) || \
1103 defined(DART_TARGET_OS_FUCHSIA)
1104 stream_->WriteString(
".section .debug_line,\"\"\n");
1111 static constexpr const char* kDebugInfoLabel =
".Ldebug_info";
1113 void PrintNamedAddress(
const char*
name) {
1114 stream_->Printf(
"%s \"%s\"\n", kWordDirective,
name);
1116 void PrintNamedAddressWithOffset(
const char*
name, intptr_t
offset) {
1117 stream_->Printf(
"%s \"%s\" + %" Pd "\n", kWordDirective,
name,
offset);
1121 BaseWriteStream*
const stream_;
1122 const IntMap<const char*>& label_to_name_;
1128static inline Dwarf* AddDwarfIfUnstripped(
1132 const Trie<const char>* deobfuscation_trie) {
1134 if (elf !=
nullptr) {
1136 ASSERT(elf->dwarf() !=
nullptr);
1137 return elf->dwarf();
1139 return new (zone) Dwarf(zone, deobfuscation_trie);
1144AssemblyImageWriter::AssemblyImageWriter(
1147 const Trie<const char>* deobfuscation_trie,
1151 assembly_stream_(
stream),
1153 AddDwarfIfUnstripped(
zone_, strip, debug_elf, deobfuscation_trie)),
1154 debug_elf_(debug_elf),
1155 label_to_symbol_name_(
zone_) {
1161 auto const vm_label = SectionLabel(section,
true);
1162 label_to_symbol_name_.Insert(vm_label,
vm_name);
1165 auto const isolate_label = SectionLabel(section,
false);
1166 if (vm_label != isolate_label) {
1167 label_to_symbol_name_.Insert(isolate_label, isolate_name);
1175void AssemblyImageWriter::Finalize() {
1176 if (assembly_dwarf_ !=
nullptr) {
1177 DwarfAssemblyStream dwarf_stream(zone_, assembly_stream_,
1178 label_to_symbol_name_);
1179 dwarf_stream.AbbreviationsPrologue();
1180 assembly_dwarf_->WriteAbbreviations(&dwarf_stream);
1181 dwarf_stream.DebugInfoPrologue();
1182 assembly_dwarf_->WriteDebugInfo(&dwarf_stream);
1183 dwarf_stream.LineNumberProgramPrologue();
1184 assembly_dwarf_->WriteLineNumberProgram(&dwarf_stream);
1186 if (debug_elf_ !=
nullptr) {
1187 debug_elf_->Finalize();
1190#if defined(DART_TARGET_OS_LINUX) || defined(DART_TARGET_OS_ANDROID) || \
1191 defined(DART_TARGET_OS_FUCHSIA)
1193#if defined(TARGET_ARCH_ARM)
1194 assembly_stream_->WriteString(
".section .note.GNU-stack,\"\",%progbits\n");
1196 assembly_stream_->WriteString(
".section .note.GNU-stack,\"\",@progbits\n");
1201void ImageWriter::SnapshotTextObjectNamer::AddNonUniqueNameFor(
1203 const Object&
object) {
1204 if (
object.IsCode()) {
1205 const Code&
code = Code::Cast(
object);
1206 if (
code.IsStubCode()) {
1207 buffer->AddString(
"stub ");
1208 insns_ =
code.instructions();
1213 if (
code.IsAllocationStubCode()) {
1214 buffer->AddString(
"new ");
1215 }
else if (
code.IsTypeTestStubCode()) {
1216 buffer->AddString(
"assert type is ");
1220 owner_ =
code.owner();
1221 AddNonUniqueNameFor(
buffer, owner_);
1223 }
else if (
object.IsClass()) {
1224 const char*
name = Class::Cast(
object).UserVisibleNameCString();
1225 const char* deobfuscated_name =
1226 ImageWriter::Deobfuscate(zone_, deobfuscation_trie_,
name);
1227 buffer->AddString(deobfuscated_name);
1228 }
else if (
object.IsAbstractType()) {
1229 const AbstractType&
type = AbstractType::Cast(
object);
1230 if (deobfuscation_trie_ ==
nullptr) {
1235 ZoneTextBuffer temp_buffer(zone_);
1237 const char* deobfuscated_name = ImageWriter::Deobfuscate(
1238 zone_, deobfuscation_trie_, temp_buffer.buffer());
1239 buffer->AddString(deobfuscated_name);
1241 }
else if (
object.IsFunction()) {
1242 const Function& func = Function::Cast(
object);
1243 NameFormattingParams
params(
1245 if (deobfuscation_trie_ ==
nullptr) {
1250 ZoneTextBuffer temp_buffer(zone_);
1251 func.PrintName(
params, &temp_buffer);
1252 const char* deobfuscated_name = ImageWriter::Deobfuscate(
1253 zone_, deobfuscation_trie_, temp_buffer.buffer());
1254 buffer->AddString(deobfuscated_name);
1256 }
else if (
object.IsCompressedStackMaps()) {
1257 buffer->AddString(
"CompressedStackMaps");
1258 }
else if (
object.IsPcDescriptors()) {
1259 buffer->AddString(
"PcDescriptors");
1260 }
else if (
object.IsCodeSourceMap()) {
1261 buffer->AddString(
"CodeSourceMap");
1262 }
else if (
object.IsString()) {
1263 const String& str = String::Cast(
object);
1264 if (str.IsOneByteString()) {
1265 buffer->AddString(
"OneByteString");
1266 }
else if (str.IsTwoByteString()) {
1267 buffer->AddString(
"TwoByteString");
1274void ImageWriter::SnapshotTextObjectNamer::ModifyForAssembly(
1275 BaseTextBuffer*
buffer) {
1276 if (
buffer->buffer()[0] ==
'L') {
1287 auto*
const pair = usage_count_.Lookup(
buffer->buffer());
1288 if (pair ==
nullptr) {
1289 usage_count_.Insert({
buffer->buffer(), 1});
1291 buffer->Printf(
" (#%" Pd ")", ++pair->value);
1295const char* ImageWriter::SnapshotTextObjectNamer::SnapshotNameFor(
1296 const InstructionsData&
data) {
1297 ZoneTextBuffer printer(zone_);
1298 if (
data.trampoline_bytes !=
nullptr) {
1299 printer.AddString(
"Trampoline");
1300 }
else if (
data.trampoline_length != 0) {
1301 printer.AddString(
"Padding");
1303 AddNonUniqueNameFor(&printer, *
data.code_);
1305 if (for_assembly_) {
1306 ModifyForAssembly(&printer);
1308 return printer.buffer();
1311const char* ImageWriter::SnapshotTextObjectNamer::SnapshotNameFor(
1312 const ObjectData&
data) {
1314 ZoneTextBuffer printer(zone_);
1315 if (
data.is_original_object()) {
1316 const Object& obj = *
data.obj;
1317 AddNonUniqueNameFor(&printer, obj);
1318#if defined(SNAPSHOT_BACKTRACE)
1322 if (!obj.IsString()) {
1323 const Object& parent = *
data.parent;
1324 if (!parent.IsNull()) {
1325 printer.AddString(
" (");
1326 AddNonUniqueNameFor(&printer, parent);
1327 printer.AddString(
")");
1332 printer.AddString(
"RawBytes");
1334 if (for_assembly_) {
1335 ModifyForAssembly(&printer);
1337 return printer.buffer();
1340Trie<const char>* ImageWriter::CreateReverseObfuscationTrie(Thread* thread) {
1341 auto*
const zone = thread->zone();
1342 auto*
const map_array = thread->isolate_group()->obfuscation_map();
1343 if (map_array ==
nullptr)
return nullptr;
1345 Trie<const char>* trie =
nullptr;
1346 for (intptr_t
i = 0; map_array[
i] !=
nullptr;
i += 2) {
1347 auto const key = map_array[
i];
1348 auto const value = map_array[
i + 1];
1351 if (strcmp(
key,
value) == 0)
continue;
1354 trie = Trie<const char>::AddString(zone, trie,
value,
key);
1359const char* ImageWriter::Deobfuscate(Zone* zone,
1360 const Trie<const char>* trie,
1362 if (trie ==
nullptr)
return cstr;
1365 bool changed =
false;
1367 while (cstr[
i] !=
'\0') {
1374 }
else if (
value !=
nullptr) {
1378 buffer.AddRaw(
reinterpret_cast<const uint8_t*
>(cstr +
i),
offset);
1382 if (!changed)
return cstr;
1386void AssemblyImageWriter::WriteBss(
bool vm) {
1388 auto const entry_count =
1390 for (intptr_t
i = 0;
i < entry_count;
i++) {
1394 ExitSection(ProgramSection::Bss, vm,
1398void AssemblyImageWriter::WriteROData(NonStreamingWriteStream* clustered_stream,
1407 const intptr_t start_position = clustered_stream->Position();
1409 if (profile_writer_ !=
nullptr) {
1411 const intptr_t padding = clustered_stream->Position() - start_position;
1412 profile_writer_->AttributeBytesTo(
1419 const uint8_t* bytes = clustered_stream->buffer();
1420 const intptr_t
len = clustered_stream->bytes_written();
1421 intptr_t last_position = 0;
1422 for (
const auto& symbol : *current_symbols_) {
1423 WriteBytes(bytes + last_position, symbol.offset - last_position);
1424 assembly_stream_->Printf(
"\"%s\":\n", symbol.name);
1425#if defined(DART_TARGET_OS_LINUX) || defined(DART_TARGET_OS_ANDROID) || \
1426 defined(DART_TARGET_OS_FUCHSIA)
1428 assembly_stream_->Printf(
".size \"%s\", %zu\n", symbol.name, symbol.size);
1429 assembly_stream_->Printf(
".type \"%s\", %%object\n", symbol.name);
1430#elif defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
1436 last_position = symbol.offset;
1438 WriteBytes(bytes + last_position,
len - last_position);
1442bool AssemblyImageWriter::EnterSection(ProgramSection section,
1445 intptr_t* alignment_padding) {
1446 ASSERT(FLAG_precompiled_mode);
1447 ASSERT(current_symbols_ ==
nullptr);
1448 bool global_symbol =
false;
1450 case ProgramSection::Text:
1451 if (debug_elf_ !=
nullptr) {
1453 new (zone_) ZoneGrowableArray<Elf::SymbolData>(zone_, 0);
1455 assembly_stream_->WriteString(
".text\n");
1456 global_symbol =
true;
1466 new (zone_) ZoneGrowableArray<Elf::SymbolData>(zone_, 0);
1467#if defined(DART_TARGET_OS_LINUX) || defined(DART_TARGET_OS_ANDROID) || \
1468 defined(DART_TARGET_OS_FUCHSIA)
1469 assembly_stream_->WriteString(
".section .rodata\n");
1470#elif defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
1471 assembly_stream_->WriteString(
".const\n");
1475 global_symbol =
true;
1477 case ProgramSection::Bss:
1478 assembly_stream_->WriteString(
".bss\n");
1480 case ProgramSection::BuildId:
1483 current_section_label_ = SectionLabel(section, vm);
1484 ASSERT(current_section_label_ > 0);
1485 if (global_symbol) {
1486 assembly_stream_->Printf(
".globl %s\n", SectionSymbol(section, vm));
1488 intptr_t padding =
Align(alignment, 0, 0);
1489 if (alignment_padding !=
nullptr) {
1490 *alignment_padding = padding;
1492 assembly_stream_->Printf(
"%s:\n", SectionSymbol(section, vm));
1496static void ElfAddSection(
1503 ZoneGrowableArray<Elf::SymbolData>*
symbols,
1504 ZoneGrowableArray<Elf::Relocation>* relocations =
nullptr) {
1505 if (elf ==
nullptr)
return;
1508 elf->AddText(symbol, label, bytes,
size, relocations,
symbols);
1511 elf->AddROData(symbol, label, bytes,
size, relocations,
symbols);
1519void AssemblyImageWriter::ExitSection(ProgramSection
name,
1524#if defined(DART_TARGET_OS_LINUX) || defined(DART_TARGET_OS_ANDROID) || \
1525 defined(DART_TARGET_OS_FUCHSIA)
1527 assembly_stream_->Printf(
".size %s, %zu\n", SectionSymbol(
name, vm),
size);
1528 assembly_stream_->Printf(
".type %s, %%object\n", SectionSymbol(
name, vm));
1529#elif defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
1550 ElfAddSection(debug_elf_,
name, SectionSymbol(
name, vm),
1551 current_section_label_,
nullptr,
size,
1553 current_section_label_ = 0;
1554 current_symbols_ =
nullptr;
1557intptr_t AssemblyImageWriter::WriteTargetWord(
word value) {
1560 assembly_stream_->Printf(
"%s 0x%.*" Px "\n", kWordDirective,
1566intptr_t AssemblyImageWriter::Relocation(intptr_t section_offset,
1567 intptr_t source_label,
1568 intptr_t source_offset,
1569 intptr_t target_label,
1570 intptr_t target_offset) {
1573 if (target_label == SectionLabel(ProgramSection::BuildId,
false)) {
1574 return WriteTargetWord(Image::kNoBuildId);
1578 assembly_stream_->Printf(
"%s ", kWordDirective);
1579 if (target_label == current_section_label_) {
1580 assembly_stream_->WriteString(
"(.)");
1581 target_offset -= section_offset;
1583 const char* target_symbol = label_to_symbol_name_.Lookup(target_label);
1584 ASSERT(target_symbol !=
nullptr);
1585 assembly_stream_->Printf(
"%s", target_symbol);
1587 if (target_offset != 0) {
1588 assembly_stream_->Printf(
" + %" Pd "", target_offset);
1591 if (source_label == current_section_label_) {
1592 assembly_stream_->WriteString(
" - (.)");
1593 source_offset -= section_offset;
1595 const char* source_symbol = label_to_symbol_name_.Lookup(source_label);
1596 ASSERT(source_symbol !=
nullptr);
1597 assembly_stream_->Printf(
" - %s", source_symbol);
1599 if (source_offset != 0) {
1600 assembly_stream_->Printf(
" - %" Pd "", source_offset);
1602 assembly_stream_->WriteString(
"\n");
1606void AssemblyImageWriter::AddCodeSymbol(
const Code&
code,
1609 auto const label = next_label_++;
1610 label_to_symbol_name_.Insert(label, symbol);
1611 if (assembly_dwarf_ !=
nullptr) {
1612 assembly_dwarf_->AddCode(
code, label);
1614 if (debug_elf_ !=
nullptr) {
1616 debug_elf_->dwarf()->AddCode(
code, label);
1618 assembly_stream_->Printf(
"\"%s\":\n", symbol);
1619#if defined(DART_TARGET_OS_LINUX) || defined(DART_TARGET_OS_ANDROID) || \
1620 defined(DART_TARGET_OS_FUCHSIA)
1622 assembly_stream_->Printf(
".size \"%s\", %zu\n", symbol,
code.Size());
1623 assembly_stream_->Printf(
".type \"%s\", %%function\n", symbol);
1624#elif defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
1632void AssemblyImageWriter::AddDataSymbol(
const char* symbol,
1635 if (!FLAG_add_readonly_data_symbols)
return;
1636 auto const label = next_label_++;
1637 label_to_symbol_name_.Insert(label, symbol);
1641void AssemblyImageWriter::FrameUnwindPrologue() {
1645 assembly_stream_->WriteString(
".cfi_startproc\n");
1660#if defined(TARGET_ARCH_IA32)
1662#elif defined(TARGET_ARCH_X64)
1663 assembly_stream_->WriteString(
".cfi_def_cfa rbp, 16\n");
1664 assembly_stream_->WriteString(
".cfi_offset rip, -8\n");
1665 assembly_stream_->WriteString(
".cfi_offset rbp, -16\n");
1666#elif defined(TARGET_ARCH_ARM64)
1669 assembly_stream_->WriteString(
".cfi_def_cfa x29, 16\n");
1670 assembly_stream_->WriteString(
".cfi_offset x30, -8\n");
1671 assembly_stream_->WriteString(
".cfi_offset x29, -16\n");
1672#elif defined(TARGET_ARCH_ARM)
1673#if defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
1675 assembly_stream_->WriteString(
".cfi_def_cfa r7, 8\n");
1678 assembly_stream_->WriteString(
".cfi_def_cfa r11, 8\n");
1680 assembly_stream_->WriteString(
".cfi_offset lr, -4\n");
1681#if defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
1683 assembly_stream_->WriteString(
".cfi_offset r7, -8\n");
1686 assembly_stream_->WriteString(
".cfi_offset r11, -8\n");
1689#if !defined(DART_TARGET_OS_MACOS) && !defined(DART_TARGET_OS_MACOS_IOS)
1691 assembly_stream_->WriteString(
".fnstart\n");
1692 assembly_stream_->WriteString(
".save {r11, lr}\n");
1693 assembly_stream_->WriteString(
".setfp r11, sp, #0\n");
1695#elif defined(TARGET_ARCH_RISCV32)
1696 assembly_stream_->WriteString(
".cfi_def_cfa fp, 0\n");
1697 assembly_stream_->WriteString(
".cfi_offset ra, -4\n");
1698 assembly_stream_->WriteString(
".cfi_offset fp, -8\n");
1699#elif defined(TARGET_ARCH_RISCV64)
1700 assembly_stream_->WriteString(
".cfi_def_cfa fp, 0\n");
1701 assembly_stream_->WriteString(
".cfi_offset ra, -8\n");
1702 assembly_stream_->WriteString(
".cfi_offset fp, -16\n");
1704#error Unexpected architecture.
1708void AssemblyImageWriter::FrameUnwindEpilogue() {
1709#if defined(TARGET_ARCH_ARM)
1710#if !defined(DART_TARGET_OS_MACOS) && !defined(DART_TARGET_OS_MACOS_IOS)
1711 assembly_stream_->WriteString(
".fnend\n");
1714 assembly_stream_->WriteString(
".cfi_endproc\n");
1717intptr_t AssemblyImageWriter::WriteBytes(
const void* bytes, intptr_t
size) {
1719 auto const start =
reinterpret_cast<const uint8_t*
>(bytes);
1720 auto const end_of_words =
1723 cursor < reinterpret_cast<const compiler::target::word*>(end_of_words);
1725 WriteTargetWord(*cursor);
1728 if (end != end_of_words) {
1729 assembly_stream_->WriteString(kSizeDirectives[
kInt8SizeLog2]);
1730 for (
auto cursor = end_of_words; cursor <
end; cursor++) {
1731 assembly_stream_->Printf(
"%s 0x%.2x", cursor != end_of_words ?
"," :
"",
1734 assembly_stream_->WriteString(
"\n");
1741 intptr_t position) {
1743 const intptr_t next_position =
Utils::RoundUp(position, alignment);
1744 assembly_stream_->Printf(
".balign %" Pd ", 0\n", alignment);
1745 return next_position - position;
1749#if defined(DART_PRECOMPILER)
1751 NonStreamingWriteStream* vm_instructions,
1752 NonStreamingWriteStream* isolate_instructions,
1753 const Trie<const char>* deobfuscation_trie,
1756 : ImageWriter(thread,
false, deobfuscation_trie),
1765 vm_instructions_(vm_instructions),
1766 isolate_instructions_(isolate_instructions),
1768 debug_elf_(debug_elf) {
1769#if defined(DART_PRECOMPILER)
1771 ASSERT(debug_elf_ ==
nullptr || debug_elf_->dwarf() !=
nullptr);
1783#if defined(DART_PRECOMPILER)
1791#if defined(DART_PRECOMPILER)
1792 const intptr_t start_position = clustered_stream->
Position();
1798#if defined(DART_PRECOMPILER)
1801 const intptr_t padding = clustered_stream->
Position() - start_position;
1813 intptr_t* alignment_padding) {
1814#if defined(DART_PRECOMPILER)
1816 ASSERT(current_relocations_ ==
nullptr);
1817 ASSERT(current_symbols_ ==
nullptr);
1822 current_section_stream_ =
1824#if defined(DART_PRECOMPILER)
1825 current_relocations_ =
1833 ASSERT(current_section_stream_ !=
nullptr);
1834#if defined(DART_PRECOMPILER)
1835 current_relocations_ =
1850 intptr_t padding = current_section_stream_->
Align(alignment);
1851 if (alignment_padding !=
nullptr) {
1852 *alignment_padding = padding;
1858#if defined(DART_PRECOMPILER)
1860 current_section_stream_->
buffer(),
size, current_symbols_,
1861 current_relocations_);
1866 current_symbols_, current_relocations_);
1867 current_relocations_ =
nullptr;
1868 current_symbols_ =
nullptr;
1870 current_section_stream_ =
nullptr;
1880 intptr_t position) {
1881 const intptr_t stream_padding =
1882 current_section_stream_->
Align(alignment,
offset);
1886 return stream_padding;
1889#if defined(DART_PRECOMPILER)
1890intptr_t BlobImageWriter::Relocation(intptr_t section_offset,
1891 intptr_t source_label,
1892 intptr_t source_offset,
1893 intptr_t target_label,
1894 intptr_t target_offset) {
1895 ASSERT(FLAG_precompiled_mode);
1897 source_label, source_offset, target_label,
1904void BlobImageWriter::AddCodeSymbol(
const Code&
code,
1907 const intptr_t label = next_label_++;
1909 if (elf_ !=
nullptr && elf_->dwarf() !=
nullptr) {
1910 elf_->dwarf()->AddCode(
code, label);
1912 if (debug_elf_ !=
nullptr) {
1913 debug_elf_->dwarf()->AddCode(
code, label);
1917void BlobImageWriter::AddDataSymbol(
const char* symbol,
1920 if (!FLAG_add_readonly_data_symbols)
return;
1921 const intptr_t label = next_label_++;
1928 const uint8_t* instructions_image)
1935 return ApiError::New(
1942#if defined(DART_PRECOMPILED_RUNTIME)
1943uword ImageReader::GetBareInstructionsAt(uint32_t
offset)
const {
1945 return reinterpret_cast<uword>(instructions_image_) +
offset;
1948uword ImageReader::GetBareInstructionsEnd()
const {
1950 return reinterpret_cast<uword>(
image.object_start()) +
image.object_size();
1955 ASSERT(!FLAG_precompiled_mode);
1959 reinterpret_cast<uword>(instructions_image_) +
offset);
static uint32_t hash(const SkShaderBase::GradientInfo &v)
#define ASSERT_EQUAL(expected, actual)
#define RELEASE_ASSERT(cond)
#define ASSERT_NOTNULL(ptr)
static constexpr intptr_t kIsolateGroupEntryCount
static constexpr intptr_t kVmEntryCount
void WriteBytes(const void *addr, intptr_t len)
intptr_t Align(intptr_t alignment, intptr_t offset=0)
DART_FORCE_INLINE intptr_t bytes_written() const
virtual intptr_t Position() const
void WriteTargetWord(word value)
static constexpr uword encode(bool 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 intptr_t Align(intptr_t alignment, intptr_t offset, intptr_t position)
virtual intptr_t WriteBytes(const void *bytes, intptr_t size)
virtual intptr_t WriteTargetWord(word value)
StringPtr UserVisibleName() const
static InstructionsPtr InstructionsOf(const CodePtr code)
static uintptr_t PayloadSizeOf(const CompressedStackMapsPtr raw)
static Dart_FileWriteCallback file_write_callback()
static Dart_FileOpenCallback file_open_callback()
static Dart_FileCloseCallback file_close_callback()
intptr_t GetObjectId(ObjectPtr raw_obj) const
void SetObjectId(ObjectPtr raw_obj, intptr_t object_id)
ObjectPtr GetObjectAt(uint32_t offset) const
InstructionsPtr GetInstructionsAt(uint32_t offset) const
ApiErrorPtr VerifyAlignment() 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_
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 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)
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)
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)
const uint8_t * build_id() const
intptr_t build_id_length() const
bool compiled_to_elf() const
uword instructions_relocated_address() const
static intptr_t HeaderSize()
static intptr_t InstanceSize()
static constexpr intptr_t kPayloadAlignment
static constexpr intptr_t kBarePayloadAlignment
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static char * SCreate(Zone *zone, const char *format,...) PRINTF_ATTRIBUTE(2
static bool IsKeyEqual(Pair pair, Key key)
static uword Hash(Key key)
UntaggedObject * untag() const
intptr_t GetClassId() const
virtual const char * ToCString() const
static ObjectPtr RawCast(ObjectPtr obj)
static OneByteStringPtr New(intptr_t len, Heap::Space space)
static constexpr intptr_t kBytesPerElement
bool IsOneByteString() const
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
bool IsTwoByteString() const
static uint32_t GetCachedHash(const StringPtr obj)
static intptr_t LengthOf(StringPtr obj)
static const char * NameOfStub(uword entry_point)
static constexpr intptr_t kBytesPerElement
static constexpr uword encode(intptr_t size)
static ObjectPtr FromAddr(uword addr)
static uword ToAddr(const UntaggedObject *raw_obj)
intptr_t HeapSize() const
intptr_t GetClassId() const
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
static constexpr size_t BitLength(int64_t value)
static constexpr T RoundDown(T x, intptr_t alignment)
static constexpr bool IsAligned(T x, uintptr_t alignment, uintptr_t offset=0)
static const ObjectId kArtificialRootId
void AttributeReferenceTo(const ObjectId &from_object_id, const Reference &reference, const ObjectId &to_object_id)
void SetObjectTypeAndName(const ObjectId &object_id, const char *type, const char *name)
void AddRoot(const ObjectId &object_id, const char *name=nullptr)
void AttributeBytesTo(const ObjectId &object_id, size_t num_bytes)
static ObjectPtr Unwrap(ObjectPtr obj)
static word InstanceSize()
static word InstanceSize()
static word InstanceSize()
static const word kNonBarePayloadAlignment
static word InstanceSize()
static const word kBarePayloadAlignment
static word InstanceSize()
static word InstanceSize()
#define kIsolateSnapshotDataAsmSymbol
#define kIsolateSnapshotBssAsmSymbol
#define kIsolateSnapshotInstructionsAsmSymbol
#define kVmSnapshotBssAsmSymbol
#define kVmSnapshotDataAsmSymbol
#define kVmSnapshotInstructionsAsmSymbol
#define kSnapshotBuildIdAsmSymbol
const EmbeddedViewParams * params
Dart_NativeFunction function
sk_sp< const SkImage > image
static constexpr intptr_t kWordSize
static constexpr word kBitsPerWord
static constexpr intptr_t STT_FUNC
static constexpr intptr_t STT_OBJECT
static constexpr intptr_t kObjectStartAlignment
uint32_t CombineHashes(uint32_t hash, uint32_t other_hash)
static constexpr uword kReadOnlyGCBits
constexpr intptr_t kInt32SizeLog2
constexpr intptr_t kWordSizeLog2
constexpr uword kBreakInstructionFiller
constexpr intptr_t kInt16SizeLog2
constexpr intptr_t kInt8SizeLog2
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
uint32_t FinalizeHash(uint32_t hash, intptr_t hashbits=kBitsPerInt32)
constexpr intptr_t kInt64SizeLog2
static constexpr intptr_t kObjectAlignment
static int8_t data[kExtLength]
static constexpr intptr_t kObjectAlignmentLog2
COMPILE_ASSERT(kUnreachableReference==WeakTable::kNoValue)
struct PathData * Data(SkPath *path)
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
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
#define REUSABLE_CLASS_HANDLESCOPE(thread)
#define REUSABLE_STRING_HANDLESCOPE(thread)
@ InsertInstructionOfCode
@ InsertBytesOfTrampoline
static constexpr intptr_t kObjectAlignmentLog2
static constexpr intptr_t kObjectAlignment
static constexpr intptr_t kOldObjectAlignmentOffset
static Reference Element(intptr_t offset)
uint32_t description_size
#define TIMELINE_DURATION(thread, stream, name)