Commit 1bef7d21 authored by jgruber's avatar jgruber Committed by Commit Bot

[builtins,x64] More information about root-relative accesses

When disassembling code (in particular embedded builtins), try to
print better information about root-relative accesses. For example:

 REX.W movq rdx,[r13+0x548]
 REX.W movq rax,[r13+0x10a8]

turns into

 REX.W movq rdx,[r13+0x548] (root (0x1ff420d0ccd9 <FixedArray[1672]>))
 REX.W movq rax,[r13+0x10a8] (external reference (check_object_type))

This is a band-aid solution until we come up with something better. It
does not understand multi-instruction sequences (such as loads from
the builtins constants table), assumes every kRootRegister-relative
access is actually root-relative (i.e. the register is not initialized
to some other value), and is limited to a particular instruction
pattern.

Bug: v8:6666,v8:7969
Change-Id: I35af92e8233c9bb0f2ad6ba0e86bd0ab69177205
Reviewed-on: https://chromium-review.googlesource.com/1146806
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54777}
parent 13401d2b
...@@ -24,6 +24,12 @@ class NameConverter { ...@@ -24,6 +24,12 @@ class NameConverter {
virtual const char* NameOfConstant(byte* addr) const; virtual const char* NameOfConstant(byte* addr) const;
virtual const char* NameInCode(byte* addr) const; virtual const char* NameInCode(byte* addr) const;
// Given a root-relative offset, returns either a name or nullptr if none is
// found.
// TODO(jgruber,v8:7989): This is a temporary solution until we can preserve
// code comments through snapshotting.
virtual const char* RootRelativeName(int offset) const { UNREACHABLE(); }
protected: protected:
v8::internal::EmbeddedVector<char, 128> tmp_buffer_; v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
}; };
......
...@@ -30,8 +30,10 @@ class V8NameConverter: public disasm::NameConverter { ...@@ -30,8 +30,10 @@ class V8NameConverter: public disasm::NameConverter {
public: public:
explicit V8NameConverter(Isolate* isolate, CodeReference code = {}) explicit V8NameConverter(Isolate* isolate, CodeReference code = {})
: isolate_(isolate), code_(code) {} : isolate_(isolate), code_(code) {}
virtual const char* NameOfAddress(byte* pc) const; const char* NameOfAddress(byte* pc) const override;
virtual const char* NameInCode(byte* addr) const; const char* NameInCode(byte* addr) const override;
const char* RootRelativeName(int offset) const override;
const CodeReference& code() const { return code_; } const CodeReference& code() const { return code_; }
private: private:
...@@ -82,6 +84,51 @@ const char* V8NameConverter::NameInCode(byte* addr) const { ...@@ -82,6 +84,51 @@ const char* V8NameConverter::NameInCode(byte* addr) const {
return code_.is_null() ? "" : reinterpret_cast<const char*>(addr); return code_.is_null() ? "" : reinterpret_cast<const char*>(addr);
} }
const char* V8NameConverter::RootRelativeName(int offset) const {
if (isolate_ == nullptr) return nullptr;
const int kRootsStart = 0;
const int kRootsEnd = Heap::roots_to_external_reference_table_offset();
const int kExtRefsStart = Heap::roots_to_external_reference_table_offset();
const int kExtRefsEnd = Heap::roots_to_builtins_offset();
if (kRootsStart <= offset && offset < kRootsEnd) {
uint32_t offset_in_roots_table = offset - kRootsStart;
// Fail safe in the unlikely case of an arbitrary root-relative offset.
if (offset_in_roots_table % kPointerSize != 0) return nullptr;
Heap::RootListIndex root_index =
static_cast<Heap::RootListIndex>(offset_in_roots_table / kPointerSize);
HeapStringAllocator allocator;
StringStream accumulator(&allocator);
isolate_->heap()->root(root_index)->ShortPrint(&accumulator);
std::unique_ptr<char[]> obj_name = accumulator.ToCString();
SNPrintF(v8_buffer_, "root (%s)", obj_name.get());
return v8_buffer_.start();
} else if (kExtRefsStart <= offset && offset < kExtRefsEnd) {
uint32_t offset_in_extref_table = offset - kExtRefsStart;
// Fail safe in the unlikely case of an arbitrary root-relative offset.
if (offset_in_extref_table % ExternalReferenceTable::EntrySize() != 0) {
return nullptr;
}
// Likewise if the external reference table is uninitialized.
if (!isolate_->heap()->external_reference_table()->is_initialized()) {
return nullptr;
}
SNPrintF(v8_buffer_, "external reference (%s)",
isolate_->heap()->external_reference_table()->NameFromOffset(
offset_in_extref_table));
return v8_buffer_.start();
} else {
return nullptr;
}
}
static void DumpBuffer(std::ostream* os, StringBuilder* out) { static void DumpBuffer(std::ostream* os, StringBuilder* out) {
(*os) << out->Finalize() << std::endl; (*os) << out->Finalize() << std::endl;
......
...@@ -50,10 +50,21 @@ class ExternalReferenceTable { ...@@ -50,10 +50,21 @@ class ExternalReferenceTable {
static const char* ResolveSymbol(void* address); static const char* ResolveSymbol(void* address);
static constexpr uint32_t EntrySize() {
return sizeof(ExternalReferenceEntry);
}
static constexpr uint32_t OffsetOfEntry(uint32_t i) { static constexpr uint32_t OffsetOfEntry(uint32_t i) {
// Used in CodeAssembler::LookupExternalReference. // Used in CodeAssembler::LookupExternalReference.
STATIC_ASSERT(offsetof(ExternalReferenceEntry, address) == 0); STATIC_ASSERT(offsetof(ExternalReferenceEntry, address) == 0);
return i * sizeof(ExternalReferenceEntry); return i * EntrySize();
}
const char* NameFromOffset(uint32_t offset) {
DCHECK_EQ(offset % EntrySize(), 0);
DCHECK_LT(offset, SizeInBytes());
int index = offset / EntrySize();
return name(index);
} }
static constexpr uint32_t SizeInBytes() { static constexpr uint32_t SizeInBytes() {
......
...@@ -853,6 +853,10 @@ class Heap { ...@@ -853,6 +853,10 @@ class Heap {
return kRootsBuiltinsOffset; return kRootsBuiltinsOffset;
} }
static constexpr int root_register_addressable_end_offset() {
return kRootRegisterAddressableEndOffset;
}
Address root_register_addressable_end() { Address root_register_addressable_end() {
return reinterpret_cast<Address>(roots_array_start()) + return reinterpret_cast<Address>(roots_array_start()) +
kRootRegisterAddressableEndOffset; kRootRegisterAddressableEndOffset;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "src/base/lazy-instance.h" #include "src/base/lazy-instance.h"
#include "src/base/v8-fallthrough.h" #include "src/base/v8-fallthrough.h"
#include "src/disasm.h" #include "src/disasm.h"
#include "src/macro-assembler.h"
#include "src/x64/sse-instr.h" #include "src/x64/sse-instr.h"
namespace disasm { namespace disasm {
...@@ -450,6 +451,7 @@ class DisassemblerX64 { ...@@ -450,6 +451,7 @@ class DisassemblerX64 {
typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const; typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const;
void TryAppendRootRelativeName(int offset);
int PrintRightOperandHelper(byte* modrmp, int PrintRightOperandHelper(byte* modrmp,
RegisterNameMapping register_name); RegisterNameMapping register_name);
int PrintRightOperand(byte* modrmp); int PrintRightOperand(byte* modrmp);
...@@ -493,6 +495,10 @@ void DisassemblerX64::AppendToBuffer(const char* format, ...) { ...@@ -493,6 +495,10 @@ void DisassemblerX64::AppendToBuffer(const char* format, ...) {
tmp_buffer_pos_ += result; tmp_buffer_pos_ += result;
} }
void DisassemblerX64::TryAppendRootRelativeName(int offset) {
const char* maybe_name = converter_.RootRelativeName(offset);
if (maybe_name != nullptr) AppendToBuffer(" (%s)", maybe_name);
}
int DisassemblerX64::PrintRightOperandHelper( int DisassemblerX64::PrintRightOperandHelper(
byte* modrmp, byte* modrmp,
...@@ -572,6 +578,10 @@ int DisassemblerX64::PrintRightOperandHelper( ...@@ -572,6 +578,10 @@ int DisassemblerX64::PrintRightOperandHelper(
NameOfCPURegister(rm), NameOfCPURegister(rm),
disp < 0 ? "-" : "+", disp < 0 ? "-" : "+",
disp < 0 ? -disp : disp); disp < 0 ? -disp : disp);
if (rm == i::kRootRegister.code()) {
// For root-relative accesses, try to append a description.
TryAppendRootRelativeName(i::kRootRegisterBias + disp);
}
return (mod == 2) ? 5 : 2; return (mod == 2) ? 5 : 2;
} }
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment