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 {
virtual const char* NameOfConstant(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:
v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
};
......
......@@ -30,8 +30,10 @@ class V8NameConverter: public disasm::NameConverter {
public:
explicit V8NameConverter(Isolate* isolate, CodeReference code = {})
: isolate_(isolate), code_(code) {}
virtual const char* NameOfAddress(byte* pc) const;
virtual const char* NameInCode(byte* addr) const;
const char* NameOfAddress(byte* pc) const override;
const char* NameInCode(byte* addr) const override;
const char* RootRelativeName(int offset) const override;
const CodeReference& code() const { return code_; }
private:
......@@ -82,6 +84,51 @@ const char* V8NameConverter::NameInCode(byte* addr) const {
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) {
(*os) << out->Finalize() << std::endl;
......
......@@ -50,10 +50,21 @@ class ExternalReferenceTable {
static const char* ResolveSymbol(void* address);
static constexpr uint32_t EntrySize() {
return sizeof(ExternalReferenceEntry);
}
static constexpr uint32_t OffsetOfEntry(uint32_t i) {
// Used in CodeAssembler::LookupExternalReference.
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() {
......
......@@ -853,6 +853,10 @@ class Heap {
return kRootsBuiltinsOffset;
}
static constexpr int root_register_addressable_end_offset() {
return kRootRegisterAddressableEndOffset;
}
Address root_register_addressable_end() {
return reinterpret_cast<Address>(roots_array_start()) +
kRootRegisterAddressableEndOffset;
......
......@@ -12,6 +12,7 @@
#include "src/base/lazy-instance.h"
#include "src/base/v8-fallthrough.h"
#include "src/disasm.h"
#include "src/macro-assembler.h"
#include "src/x64/sse-instr.h"
namespace disasm {
......@@ -450,6 +451,7 @@ class DisassemblerX64 {
typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const;
void TryAppendRootRelativeName(int offset);
int PrintRightOperandHelper(byte* modrmp,
RegisterNameMapping register_name);
int PrintRightOperand(byte* modrmp);
......@@ -493,6 +495,10 @@ void DisassemblerX64::AppendToBuffer(const char* format, ...) {
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(
byte* modrmp,
......@@ -572,6 +578,10 @@ int DisassemblerX64::PrintRightOperandHelper(
NameOfCPURegister(rm),
disp < 0 ? "-" : "+",
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;
}
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