Commit f8eef3ae authored by ishell@chromium.org's avatar ishell@chromium.org Committed by V8 LUCI CQ

[heap][cleanup] Avoid crashes when using 'jco' gdb macro

... with addresses unexpected by V8.

Bug: v8:12425
Change-Id: I602ea79e84242a4a163bdbd6b22fb16e76eda1a2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3807585Reviewed-by: 's avatarDominik Inführ <dinfuehr@chromium.org>
Auto-Submit: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82164}
parent c0d5d4d6
...@@ -2944,10 +2944,9 @@ V8_EXPORT_PRIVATE extern void _v8_internal_Print_Code(void* object) { ...@@ -2944,10 +2944,9 @@ V8_EXPORT_PRIVATE extern void _v8_internal_Print_Code(void* object) {
} }
#endif // V8_ENABLE_WEBASSEMBLY #endif // V8_ENABLE_WEBASSEMBLY
if (!isolate->heap()->InSpaceSlow(address, i::CODE_SPACE) && i::CodeLookupResult lookup_result =
!isolate->heap()->InSpaceSlow(address, i::CODE_LO_SPACE) && isolate->heap()->GcSafeFindCodeForInnerPointerForPrinting(address);
!i::OffHeapInstructionStream::PcIsOffHeap(isolate, address) && if (!lookup_result.IsFound()) {
!i::ReadOnlyHeap::Contains(address)) {
i::PrintF( i::PrintF(
"%p is not within the current isolate's code, read_only or embedded " "%p is not within the current isolate's code, read_only or embedded "
"spaces\n", "spaces\n",
...@@ -2955,12 +2954,6 @@ V8_EXPORT_PRIVATE extern void _v8_internal_Print_Code(void* object) { ...@@ -2955,12 +2954,6 @@ V8_EXPORT_PRIVATE extern void _v8_internal_Print_Code(void* object) {
return; return;
} }
i::CodeLookupResult lookup_result = isolate->FindCodeObject(address);
if (!lookup_result.IsFound()) {
i::PrintF("No code object found containing %p\n", object);
return;
}
i::Code code = lookup_result.ToCode(); i::Code code = lookup_result.ToCode();
#ifdef ENABLE_DISASSEMBLER #ifdef ENABLE_DISASSEMBLER
......
...@@ -7166,7 +7166,8 @@ bool Heap::GcSafeCodeContains(Code code, Address addr) { ...@@ -7166,7 +7166,8 @@ bool Heap::GcSafeCodeContains(Code code, Address addr) {
return start <= addr && addr < end; return start <= addr && addr < end;
} }
CodeLookupResult Heap::GcSafeFindCodeForInnerPointer(Address inner_pointer) { CodeLookupResult Heap::GcSafeFindCodeForInnerPointer(
Address inner_pointer, bool die_on_unsuccessful_lookup) {
Builtin maybe_builtin = Builtin maybe_builtin =
OffHeapInstructionStream::TryLookupCode(isolate(), inner_pointer); OffHeapInstructionStream::TryLookupCode(isolate(), inner_pointer);
if (Builtins::IsBuiltinId(maybe_builtin)) { if (Builtins::IsBuiltinId(maybe_builtin)) {
...@@ -7195,25 +7196,10 @@ CodeLookupResult Heap::GcSafeFindCodeForInnerPointer(Address inner_pointer) { ...@@ -7195,25 +7196,10 @@ CodeLookupResult Heap::GcSafeFindCodeForInnerPointer(Address inner_pointer) {
return GcSafeCastToCode(HeapObject::FromAddress(start), inner_pointer); return GcSafeCastToCode(HeapObject::FromAddress(start), inner_pointer);
} }
// It can only fall through to here during debugging, where for instance "jco" if (!die_on_unsuccessful_lookup) return {};
// was called on an address within a RO_SPACE builtin. It cannot reach here
// during stack iteration as RO_SPACE memory is not executable so cannot // Put useful info on the stack for debugging and crash the process.
// appear on the stack as an instruction address.
DCHECK(ReadOnlyHeap::Contains(
HeapObject::FromAddress(inner_pointer & ~kHeapObjectTagMask)));
// TODO(delphick): Possibly optimize this as it iterates over all pages in
// RO_SPACE instead of just the one containing the address.
ReadOnlyHeapObjectIterator iterator(isolate()->read_only_heap());
for (HeapObject object = iterator.Next(); !object.is_null();
object = iterator.Next()) {
if (!object.IsCode()) continue;
Code code = Code::cast(object);
if (inner_pointer >= code.address() &&
inner_pointer < code.address() + code.Size()) {
return CodeLookupResult{code};
}
}
// TODO(1241665): Remove once the issue is solved. // TODO(1241665): Remove once the issue is solved.
std::shared_ptr<CodeRange> code_range = CodeRange::GetProcessWideCodeRange(); std::shared_ptr<CodeRange> code_range = CodeRange::GetProcessWideCodeRange();
void* code_range_embedded_blob_code_copy = void* code_range_embedded_blob_code_copy =
...@@ -7233,6 +7219,38 @@ CodeLookupResult Heap::GcSafeFindCodeForInnerPointer(Address inner_pointer) { ...@@ -7233,6 +7219,38 @@ CodeLookupResult Heap::GcSafeFindCodeForInnerPointer(Address inner_pointer) {
UNREACHABLE(); UNREACHABLE();
} }
CodeLookupResult Heap::GcSafeFindCodeForInnerPointerForPrinting(
Address inner_pointer) {
if (InSpaceSlow(inner_pointer, i::CODE_SPACE) ||
InSpaceSlow(inner_pointer, i::CODE_LO_SPACE) ||
i::OffHeapInstructionStream::PcIsOffHeap(isolate(), inner_pointer)) {
CodeLookupResult result =
GcSafeFindCodeForInnerPointer(inner_pointer, false);
if (result.IsFound()) return result;
}
// During normal execution builtins from RO_SPACE can't appear on the stack
// as instruction address because RO_SPACE is not executable. However during
// debugging "jco" macro might be called with an address from a readonly
// builtin trampoline.
if (read_only_space()->ContainsSlow(inner_pointer)) {
// TODO(delphick): Possibly optimize this as it iterates over all pages in
// RO_SPACE instead of just the one containing the address.
ReadOnlyHeapObjectIterator iterator(isolate()->read_only_heap());
for (HeapObject object = iterator.Next(); !object.is_null();
object = iterator.Next()) {
if (!object.IsCode()) continue;
Code code = Code::cast(object);
if (inner_pointer >= code.address() &&
inner_pointer < code.address() + code.Size()) {
return CodeLookupResult{code};
}
}
}
return {};
}
void Heap::WriteBarrierForCodeSlow(Code code) { void Heap::WriteBarrierForCodeSlow(Code code) {
PtrComprCageBase cage_base = code.main_cage_base(); PtrComprCageBase cage_base = code.main_cage_base();
for (RelocIterator it(code, RelocInfo::EmbeddedObjectModeMask()); !it.done(); for (RelocIterator it(code, RelocInfo::EmbeddedObjectModeMask()); !it.done();
......
...@@ -1593,8 +1593,18 @@ class Heap { ...@@ -1593,8 +1593,18 @@ class Heap {
// Stack frame support. ====================================================== // Stack frame support. ======================================================
// =========================================================================== // ===========================================================================
// Returns the Code object for a given interior pointer. // Searches for compiled code or embedded builtins code object by given
CodeLookupResult GcSafeFindCodeForInnerPointer(Address inner_pointer); // interior pointer.
// Crashes process on unsuccessful lookup if {die_on_unsuccessful_lookup}
// is true. All code lookups made by GC must succeed.
CodeLookupResult GcSafeFindCodeForInnerPointer(
Address inner_pointer, bool die_on_unsuccessful_lookup = true);
// Same as GcSafeFindCodeForInnerPointer() but it doesn't crash the process
// on unsuccessful lookup.
// It's intended to be used only from gdb's 'jco' macro.
CodeLookupResult GcSafeFindCodeForInnerPointerForPrinting(
Address inner_pointer);
// Returns true if {addr} is contained within {code} and false otherwise. // Returns true if {addr} is contained within {code} and false otherwise.
// Mostly useful for debugging. // Mostly useful for debugging.
......
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