5 #include "src/disassembler.h" 8 #include <unordered_map> 11 #include "src/assembler-inl.h" 12 #include "src/code-reference.h" 13 #include "src/code-stubs.h" 14 #include "src/debug/debug.h" 15 #include "src/deoptimizer.h" 16 #include "src/disasm.h" 17 #include "src/ic/ic.h" 18 #include "src/isolate-data.h" 19 #include "src/macro-assembler.h" 20 #include "src/objects-inl.h" 21 #include "src/snapshot/embedded-data.h" 22 #include "src/snapshot/serializer-common.h" 23 #include "src/string-stream.h" 24 #include "src/wasm/wasm-code-manager.h" 25 #include "src/wasm/wasm-engine.h" 30 #ifdef ENABLE_DISASSEMBLER 34 explicit V8NameConverter(Isolate* isolate, CodeReference code = {})
35 : isolate_(isolate), code_(code) {}
36 const char* NameOfAddress(byte* pc)
const override;
37 const char* NameInCode(byte* addr)
const override;
38 const char* RootRelativeName(
int offset)
const override;
40 const CodeReference& code()
const {
return code_; }
43 void InitExternalRefsCache()
const;
48 EmbeddedVector<char, 128> v8_buffer_;
54 mutable std::unordered_map<int, const char*> directly_accessed_external_refs_;
57 void V8NameConverter::InitExternalRefsCache()
const {
58 ExternalReferenceTable* external_reference_table =
59 isolate_->external_reference_table();
60 if (!external_reference_table->is_initialized())
return;
62 base::AddressRegion addressable_region =
63 isolate_->root_register_addressable_region();
64 Address isolate_root = isolate_->isolate_root();
66 for (
uint32_t i = 0;
i < external_reference_table->size();
i++) {
67 Address address = external_reference_table->address(
i);
68 if (addressable_region.contains(address)) {
69 int offset =
static_cast<int>(address - isolate_root);
70 const char* name = external_reference_table->name(
i);
71 directly_accessed_external_refs_.insert({offset, name});
76 const char* V8NameConverter::NameOfAddress(byte* pc)
const {
77 if (!code_.is_null()) {
79 isolate_ ? isolate_->builtins()->Lookup(reinterpret_cast<Address>(pc))
82 if (name !=
nullptr) {
83 SNPrintF(v8_buffer_,
"%p (%s)", static_cast<void*>(pc), name);
84 return v8_buffer_.start();
87 int offs =
static_cast<int>(
reinterpret_cast<Address
>(pc) -
88 code_.instruction_start());
90 if (0 <= offs && offs < code_.instruction_size()) {
91 SNPrintF(v8_buffer_,
"%p <+0x%x>", static_cast<void*>(pc), offs);
92 return v8_buffer_.start();
95 wasm::WasmCode* wasm_code =
96 isolate_ ? isolate_->wasm_engine()->code_manager()->LookupCode(
97 reinterpret_cast<Address>(pc))
99 if (wasm_code !=
nullptr) {
100 SNPrintF(v8_buffer_,
"%p (%s)", static_cast<void*>(pc),
101 wasm::GetWasmCodeKindAsString(wasm_code->kind()));
102 return v8_buffer_.start();
106 return disasm::NameConverter::NameOfAddress(pc);
110 const char* V8NameConverter::NameInCode(byte* addr)
const {
113 return code_.is_null() ?
"" :
reinterpret_cast<const char*
>(addr);
116 const char* V8NameConverter::RootRelativeName(
int offset)
const {
117 if (isolate_ ==
nullptr)
return nullptr;
119 const int kRootsTableStart = IsolateData::roots_table_offset();
120 const unsigned kRootsTableSize =
sizeof(RootsTable);
121 const int kExtRefsTableStart = IsolateData::external_reference_table_offset();
122 const unsigned kExtRefsTableSize = ExternalReferenceTable::SizeInBytes();
123 const int kBuiltinsTableStart = IsolateData::builtins_table_offset();
124 const unsigned kBuiltinsTableSize = Builtins::builtin_count * kPointerSize;
126 if (static_cast<unsigned>(offset - kRootsTableStart) < kRootsTableSize) {
127 uint32_t offset_in_roots_table = offset - kRootsTableStart;
130 if (offset_in_roots_table % kPointerSize != 0)
return nullptr;
132 RootIndex root_index =
133 static_cast<RootIndex
>(offset_in_roots_table / kPointerSize);
135 SNPrintF(v8_buffer_,
"root (%s)", RootsTable::name(root_index));
136 return v8_buffer_.start();
138 }
else if (static_cast<unsigned>(offset - kExtRefsTableStart) <
140 uint32_t offset_in_extref_table = offset - kExtRefsTableStart;
143 if (offset_in_extref_table % ExternalReferenceTable::EntrySize() != 0) {
148 if (!isolate_->external_reference_table()->is_initialized()) {
152 SNPrintF(v8_buffer_,
"external reference (%s)",
153 isolate_->external_reference_table()->NameFromOffset(
154 offset_in_extref_table));
155 return v8_buffer_.start();
157 }
else if (static_cast<unsigned>(offset - kBuiltinsTableStart) <
158 kBuiltinsTableSize) {
159 uint32_t offset_in_builtins_table = (offset - kBuiltinsTableStart);
161 Builtins::Name builtin_id =
162 static_cast<Builtins::Name
>(offset_in_builtins_table / kPointerSize);
164 const char* name = Builtins::name(builtin_id);
165 SNPrintF(v8_buffer_,
"builtin (%s)", name);
166 return v8_buffer_.start();
170 if (directly_accessed_external_refs_.empty()) {
171 InitExternalRefsCache();
174 auto iter = directly_accessed_external_refs_.find(offset);
175 if (iter != directly_accessed_external_refs_.end()) {
176 SNPrintF(v8_buffer_,
"external value (%s)", iter->second);
177 return v8_buffer_.start();
179 return "WAAT??? What are we accessing here???";
183 static void DumpBuffer(std::ostream* os, StringBuilder* out) {
184 (*os) << out->Finalize() << std::endl;
189 static const int kOutBufferSize = 2048 + String::kMaxShortPrintLength;
190 static const int kRelocInfoPosition = 57;
192 static void PrintRelocInfo(StringBuilder* out, Isolate* isolate,
193 const ExternalReferenceEncoder* ref_encoder,
194 std::ostream* os, CodeReference host,
195 RelocInfo* relocinfo,
bool first_reloc_info =
true) {
197 if (first_reloc_info) {
199 out->AddPadding(
' ', kRelocInfoPosition - out->position());
203 out->AddPadding(
' ', kRelocInfoPosition);
206 RelocInfo::Mode rmode = relocinfo->rmode();
207 if (rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) {
208 out->AddFormatted(
" ;; debug: deopt position, script offset '%d'",
209 static_cast<int>(relocinfo->data()));
210 }
else if (rmode == RelocInfo::DEOPT_INLINING_ID) {
211 out->AddFormatted(
" ;; debug: deopt position, inlining id '%d'",
212 static_cast<int>(relocinfo->data()));
213 }
else if (rmode == RelocInfo::DEOPT_REASON) {
214 DeoptimizeReason reason =
static_cast<DeoptimizeReason
>(relocinfo->data());
215 out->AddFormatted(
" ;; debug: deopt reason '%s'",
216 DeoptimizeReasonToString(reason));
217 }
else if (rmode == RelocInfo::DEOPT_ID) {
218 out->AddFormatted(
" ;; debug: deopt index %d",
219 static_cast<int>(relocinfo->data()));
220 }
else if (rmode == RelocInfo::EMBEDDED_OBJECT) {
221 HeapStringAllocator allocator;
222 StringStream accumulator(&allocator);
223 relocinfo->target_object()->ShortPrint(&accumulator);
224 std::unique_ptr<char[]> obj_name = accumulator.ToCString();
225 out->AddFormatted(
" ;; object: %s", obj_name.get());
226 }
else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
227 const char* reference_name =
228 ref_encoder ? ref_encoder->NameOfAddress(
229 isolate, relocinfo->target_external_reference())
231 out->AddFormatted(
" ;; external reference (%s)", reference_name);
232 }
else if (RelocInfo::IsCodeTargetMode(rmode)) {
233 out->AddFormatted(
" ;; code:");
234 Code code = isolate->heap()->GcSafeFindCodeForInnerPointer(
235 relocinfo->target_address());
236 Code::Kind kind = code->kind();
237 if (kind == Code::STUB) {
240 uint32_t minor_key = CodeStub::MinorKeyFromKey(key);
241 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
242 DCHECK(major_key == CodeStub::MajorKeyFromKey(key));
243 out->AddFormatted(
" %s, %s, ", Code::Kind2String(kind),
244 CodeStub::MajorName(major_key));
245 out->AddFormatted(
"minor: %d", minor_key);
246 }
else if (code->is_builtin()) {
247 out->AddFormatted(
" Builtin::%s", Builtins::name(code->builtin_index()));
249 out->AddFormatted(
" %s", Code::Kind2String(kind));
251 }
else if (RelocInfo::IsWasmStubCall(rmode) && !isolate) {
253 wasm::WasmCode* code = host.as_wasm_code()->native_module()->Lookup(
254 relocinfo->wasm_stub_call_address());
255 out->AddFormatted(
" ;; wasm stub: %s", code->GetRuntimeStubName());
256 }
else if (RelocInfo::IsRuntimeEntry(rmode) && isolate &&
257 isolate->deoptimizer_data() !=
nullptr) {
259 Address addr = relocinfo->target_address();
261 if (Deoptimizer::IsDeoptimizationEntry(isolate, addr, &type)) {
262 int id = relocinfo->GetDeoptimizationId(isolate, type);
263 out->AddFormatted(
" ;; %s deoptimization bailout %d",
264 Deoptimizer::MessageFor(type),
id);
266 out->AddFormatted(
" ;; %s", RelocInfo::RelocModeName(rmode));
269 out->AddFormatted(
" ;; %s", RelocInfo::RelocModeName(rmode));
273 static int DecodeIt(Isolate* isolate, ExternalReferenceEncoder* ref_encoder,
274 std::ostream* os, CodeReference code,
275 const V8NameConverter& converter, byte* begin, byte* end,
276 Address current_pc) {
279 StringBuilder out(out_buffer.start(), out_buffer.length());
282 disasm::Disassembler::kContinueOnUnimplementedOpcode);
283 RelocIterator* it =
nullptr;
284 if (!code.is_null()) {
285 it =
new RelocIterator(code);
295 SNPrintF(decode_buffer,
297 *reinterpret_cast<int32_t*>(pc));
301 int num_const = d.ConstantPoolSizeAt(pc);
302 if (num_const >= 0) {
303 SNPrintF(decode_buffer,
304 "%08x constant pool begin (num_const = %d)",
305 *reinterpret_cast<int32_t*>(pc), num_const);
306 constants = num_const;
308 }
else if (it !=
nullptr && !it->done() &&
309 it->rinfo()->pc() ==
reinterpret_cast<Address
>(pc) &&
310 it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) {
312 byte* ptr = *
reinterpret_cast<byte**
>(pc);
314 decode_buffer,
"%08" V8PRIxPTR
" jump table entry %4" PRIuS,
315 reinterpret_cast<intptr_t>(ptr), static_cast<size_t>(ptr - begin));
318 decode_buffer[0] =
'\0';
319 pc += d.InstructionDecode(decode_buffer, pc);
324 std::vector<const char*> comments;
325 std::vector<Address> pcs;
326 std::vector<RelocInfo::Mode> rmodes;
327 std::vector<intptr_t> datas;
329 while (!it->done() && it->rinfo()->pc() <
reinterpret_cast<Address
>(pc)) {
330 if (RelocInfo::IsComment(it->rinfo()->rmode())) {
333 reinterpret_cast<const char*>(it->rinfo()->data()));
336 pcs.push_back(it->rinfo()->pc());
337 rmodes.push_back(it->rinfo()->rmode());
338 datas.push_back(it->rinfo()->data());
345 for (
size_t i = 0;
i < comments.size();
i++) {
346 out.AddFormatted(
" %s", comments[
i]);
347 DumpBuffer(os, &out);
351 if (FLAG_log_colour && reinterpret_cast<Address>(prev_pc) == current_pc) {
353 out.AddFormatted(
"\033[33;1m");
355 out.AddFormatted(
"%p %4" V8PRIxPTRDIFF
" ", static_cast<void*>(prev_pc),
359 out.AddFormatted(
"%s", decode_buffer.start());
362 for (
size_t i = 0;
i < pcs.size();
i++) {
364 const CodeReference& host = code;
365 Address constant_pool =
366 host.is_null() ? kNullAddress : host.constant_pool();
367 RelocInfo relocinfo(pcs[
i], rmodes[
i], datas[
i], Code(), constant_pool);
369 bool first_reloc_info = (
i == 0);
370 PrintRelocInfo(&out, isolate, ref_encoder, os, code, &relocinfo,
377 if (pcs.empty() && !code.is_null()) {
378 RelocInfo dummy_rinfo(reinterpret_cast<Address>(prev_pc), RelocInfo::NONE,
380 if (dummy_rinfo.IsInConstantPool()) {
381 Address constant_pool_entry_address =
382 dummy_rinfo.constant_pool_entry_address();
383 RelocIterator reloc_it(code);
384 while (!reloc_it.done()) {
385 if (reloc_it.rinfo()->IsInConstantPool() &&
386 (reloc_it.rinfo()->constant_pool_entry_address() ==
387 constant_pool_entry_address)) {
388 PrintRelocInfo(&out, isolate, ref_encoder, os, code,
397 if (FLAG_log_colour && reinterpret_cast<Address>(prev_pc) == current_pc) {
398 out.AddFormatted(
"\033[m");
401 DumpBuffer(os, &out);
406 for ( ; !it->done(); it->next()) {
407 if (RelocInfo::IsComment(it->rinfo()->rmode())) {
408 out.AddFormatted(
" %s",
409 reinterpret_cast<const char*>(it->rinfo()->data()));
410 DumpBuffer(os, &out);
416 return static_cast<int>(pc - begin);
419 int Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin,
420 byte* end, CodeReference code, Address current_pc) {
421 V8NameConverter v8NameConverter(isolate, code);
422 bool decode_off_heap = isolate && InstructionStream::PcIsOffHeap(
423 isolate, bit_cast<Address>(begin));
424 CodeReference code_ref = decode_off_heap ? CodeReference() : code;
427 SealHandleScope shs(isolate);
428 DisallowHeapAllocation no_alloc;
429 ExternalReferenceEncoder ref_encoder(isolate);
430 return DecodeIt(isolate, &ref_encoder, os, code_ref, v8NameConverter, begin,
434 return DecodeIt(
nullptr,
nullptr, os, code_ref, v8NameConverter, begin, end,
439 #else // ENABLE_DISASSEMBLER 441 int Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin,
442 byte* end, CodeReference code, Address current_pc) {
446 #endif // ENABLE_DISASSEMBLER