2014-07-07 16:21:29 +00:00
|
|
|
# Copyright 2014 the V8 project authors. All rights reserved.
|
|
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
|
|
# found in the LICENSE file.
|
|
|
|
|
2018-11-12 21:40:17 +00:00
|
|
|
# Print tagged object.
|
2014-07-07 16:21:29 +00:00
|
|
|
define job
|
2016-07-28 17:09:10 +00:00
|
|
|
call _v8_internal_Print_Object((void*)($arg0))
|
2014-07-07 16:21:29 +00:00
|
|
|
end
|
|
|
|
document job
|
|
|
|
Print a v8 JavaScript object
|
|
|
|
Usage: job tagged_ptr
|
|
|
|
end
|
|
|
|
|
2018-11-12 21:40:17 +00:00
|
|
|
# Print content of v8::internal::Handle.
|
|
|
|
define jh
|
|
|
|
call _v8_internal_Print_Object(*((v8::internal::Object**)($arg0).location_))
|
|
|
|
end
|
|
|
|
document jh
|
|
|
|
Print content of a v8::internal::Handle
|
|
|
|
Usage: jh internal_handle
|
|
|
|
end
|
|
|
|
|
|
|
|
# Print content of v8::Local handle.
|
2017-01-13 12:59:30 +00:00
|
|
|
define jlh
|
2017-12-05 13:10:32 +00:00
|
|
|
call _v8_internal_Print_Object(*((v8::internal::Object**)($arg0).val_))
|
2017-01-13 12:59:30 +00:00
|
|
|
end
|
|
|
|
document jlh
|
|
|
|
Print content of a v8::Local handle
|
|
|
|
Usage: jlh local_handle
|
|
|
|
end
|
|
|
|
|
2014-07-07 16:21:29 +00:00
|
|
|
# Print Code objects containing given PC.
|
|
|
|
define jco
|
2016-07-28 17:09:10 +00:00
|
|
|
call _v8_internal_Print_Code((void*)($arg0))
|
2014-07-07 16:21:29 +00:00
|
|
|
end
|
|
|
|
document jco
|
|
|
|
Print a v8 Code object from an internal code address
|
|
|
|
Usage: jco pc
|
|
|
|
end
|
|
|
|
|
2016-11-28 19:27:52 +00:00
|
|
|
# Print LayoutDescriptor.
|
|
|
|
define jld
|
|
|
|
call _v8_internal_Print_LayoutDescriptor((void*)($arg0))
|
|
|
|
end
|
|
|
|
document jld
|
|
|
|
Print a v8 LayoutDescriptor object
|
|
|
|
Usage: jld tagged_ptr
|
|
|
|
end
|
|
|
|
|
2017-07-06 08:17:19 +00:00
|
|
|
# Print TransitionTree.
|
|
|
|
define jtt
|
|
|
|
call _v8_internal_Print_TransitionTree((void*)($arg0))
|
|
|
|
end
|
|
|
|
document jtt
|
|
|
|
Print the complete transition tree of the given v8 Map.
|
|
|
|
Usage: jtt tagged_ptr
|
|
|
|
end
|
|
|
|
|
2014-07-07 16:21:29 +00:00
|
|
|
# Print JavaScript stack trace.
|
2014-07-09 10:55:55 +00:00
|
|
|
define jst
|
2016-07-28 17:09:10 +00:00
|
|
|
call _v8_internal_Print_StackTrace()
|
2014-07-07 16:21:29 +00:00
|
|
|
end
|
|
|
|
document jst
|
|
|
|
Print the current JavaScript stack trace
|
|
|
|
Usage: jst
|
|
|
|
end
|
|
|
|
|
Add a jss gdb macro that skips over the jitted stack in gdb
Use it like this:
Program received signal SIGTRAP, Trace/breakpoint trap.
[Switching to Thread 0x7f50d02c4700 (LWP 8152)]
base::debug::(anonymous namespace)::DebugBreak ()
at ../../base/debug/debugger_posix.cc:230
230 }
(gdb) bt
at ../../base/debug/debugger_posix.cc:230
...
args_object=0x7f50d02bfe00, isolate=0x2f001c9e2020)
at ../../v8/src/builtins/builtins-api.cc:123
...
(gdb) jss
(gdb) bt
isolate=0x2f001c9e2020, is_construct=false, target=..., receiver=...,
argc=1, args=0x7f50d02c0518, new_target=...)
at ../../v8/src/execution.cc:111
isolate=0x2f001c9e2020, callable=..., receiver=..., argc=1,
argv=0x7f50d02c0518) at ../../v8/src/execution.cc:168
...
R=yangguo@chromium.org
BUG=
Review-Url: https://codereview.chromium.org/2186013002
Cr-Commit-Position: refs/heads/master@{#38121}
2016-07-28 09:04:39 +00:00
|
|
|
# Skip the JavaScript stack.
|
|
|
|
define jss
|
|
|
|
set $js_entry_sp=v8::internal::Isolate::Current()->thread_local_top()->js_entry_sp_
|
|
|
|
set $rbp=*(void**)$js_entry_sp
|
|
|
|
set $rsp=$js_entry_sp + 2*sizeof(void*)
|
|
|
|
set $pc=*(void**)($js_entry_sp+sizeof(void*))
|
|
|
|
end
|
|
|
|
document jss
|
|
|
|
Skip the jitted stack on x64 to where we entered JS last.
|
|
|
|
Usage: jss
|
|
|
|
end
|
|
|
|
|
2016-11-04 07:27:39 +00:00
|
|
|
# Print stack trace with assertion scopes.
|
|
|
|
define bta
|
|
|
|
python
|
|
|
|
import re
|
2016-11-04 08:23:16 +00:00
|
|
|
frame_re = re.compile("^#(\d+)\s*(?:0x[a-f\d]+ in )?(.+) \(.+ at (.+)")
|
2019-02-18 16:45:02 +00:00
|
|
|
assert_re = re.compile("^\s*(\S+) = .+<v8::internal::Per\w+AssertScope<v8::internal::(\S*), (false|true)>")
|
2016-11-04 07:27:39 +00:00
|
|
|
btl = gdb.execute("backtrace full", to_string = True).splitlines()
|
|
|
|
for l in btl:
|
|
|
|
match = frame_re.match(l)
|
|
|
|
if match:
|
|
|
|
print("[%-2s] %-60s %-40s" % (match.group(1), match.group(2), match.group(3)))
|
|
|
|
match = assert_re.match(l)
|
|
|
|
if match:
|
|
|
|
if match.group(3) == "false":
|
|
|
|
prefix = "Disallow"
|
|
|
|
color = "\033[91m"
|
|
|
|
else:
|
|
|
|
prefix = "Allow"
|
|
|
|
color = "\033[92m"
|
|
|
|
print("%s -> %s %s (%s)\033[0m" % (color, prefix, match.group(2), match.group(1)))
|
|
|
|
end
|
2016-11-04 08:23:16 +00:00
|
|
|
end
|
2016-11-04 07:27:39 +00:00
|
|
|
document bta
|
|
|
|
Print stack trace with assertion scopes
|
|
|
|
Usage: bta
|
|
|
|
end
|
|
|
|
|
2017-05-09 12:11:27 +00:00
|
|
|
# Search for a pointer inside all valid pages.
|
|
|
|
define space_find
|
|
|
|
set $space = $arg0
|
|
|
|
set $current_page = $space->anchor()->next_page()
|
|
|
|
while ($current_page != $space->anchor())
|
|
|
|
printf "# Searching in %p - %p\n", $current_page->area_start(), $current_page->area_end()-1
|
|
|
|
find $current_page->area_start(), $current_page->area_end()-1, $arg1
|
|
|
|
set $current_page = $current_page->next_page()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
define heap_find
|
|
|
|
set $heap = v8::internal::Isolate::Current()->heap()
|
|
|
|
printf "# Searching for %p in old_space ===============================\n", $arg0
|
|
|
|
space_find $heap->old_space() ($arg0)
|
|
|
|
printf "# Searching for %p in map_space ===============================\n", $arg0
|
|
|
|
space_find $heap->map_space() $arg0
|
|
|
|
printf "# Searching for %p in code_space ===============================\n", $arg0
|
|
|
|
space_find $heap->code_space() $arg0
|
|
|
|
end
|
|
|
|
document heap_find
|
|
|
|
Find the location of a given address in V8 pages.
|
|
|
|
Usage: heap_find address
|
|
|
|
end
|
|
|
|
|
2014-07-07 16:21:29 +00:00
|
|
|
set disassembly-flavor intel
|
2014-07-09 10:55:55 +00:00
|
|
|
set disable-randomization off
|
2018-08-13 16:14:06 +00:00
|
|
|
|
|
|
|
# Install a handler whenever the debugger stops due to a signal. It walks up the
|
|
|
|
# stack looking for V8_Dcheck and moves the frame to the one above it so it's
|
|
|
|
# immediately at the line of code that triggered the DCHECK.
|
|
|
|
python
|
|
|
|
def dcheck_stop_handler(event):
|
2018-12-14 10:16:01 +00:00
|
|
|
frame = gdb.selected_frame()
|
2018-08-21 11:45:52 +00:00
|
|
|
select_frame = None
|
2018-12-14 10:16:01 +00:00
|
|
|
message = None
|
2019-01-08 10:07:20 +00:00
|
|
|
count = 0
|
|
|
|
# limit stack scanning since they're usually shallow and otherwise stack
|
|
|
|
# overflows can be very slow.
|
|
|
|
while frame is not None and count < 5:
|
|
|
|
count += 1
|
2018-12-14 10:16:01 +00:00
|
|
|
if frame.name() == 'V8_Dcheck':
|
|
|
|
frame_message = gdb.lookup_symbol('message', frame.block())[0]
|
|
|
|
if frame_message:
|
|
|
|
message = frame_message.value(frame).string()
|
|
|
|
select_frame = frame.older()
|
|
|
|
break
|
2018-12-18 09:53:49 +00:00
|
|
|
if frame.name() is not None and frame.name().startswith('V8_Fatal'):
|
2018-08-13 16:14:06 +00:00
|
|
|
select_frame = frame.older()
|
|
|
|
frame = frame.older()
|
|
|
|
|
2018-08-21 11:45:52 +00:00
|
|
|
if select_frame is not None:
|
|
|
|
select_frame.select()
|
|
|
|
gdb.execute('frame')
|
2018-12-14 10:16:01 +00:00
|
|
|
if message:
|
|
|
|
print('DCHECK error: {}'.format(message))
|
2018-08-21 11:45:52 +00:00
|
|
|
|
2018-08-13 16:14:06 +00:00
|
|
|
gdb.events.stop.connect(dcheck_stop_handler)
|
|
|
|
end
|