1# Copyright 2017 the V8 project authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5# Load this file by adding this to your ~/.lldbinit: 6# command script import <this_dir>/lldb_commands.py 7 8import lldb 9import re 10 11##################### 12# Helper functions. # 13##################### 14def current_thread(debugger): 15 return debugger.GetSelectedTarget().GetProcess().GetSelectedThread() 16 17def current_frame(debugger): 18 return current_thread(debugger).GetSelectedFrame() 19 20def no_arg_cmd(debugger, cmd): 21 current_frame(debugger).EvaluateExpression(cmd) 22 print("") 23 24def ptr_arg_cmd(debugger, name, param, cmd): 25 if not param: 26 print("'{}' requires an argument".format(name)) 27 return 28 param = '(void*)({})'.format(param) 29 no_arg_cmd(debugger, cmd.format(param)) 30 31##################### 32# lldb commands. # 33##################### 34def job(debugger, param, *args): 35 """Print a v8 heap object""" 36 ptr_arg_cmd(debugger, 'job', param, "_v8_internal_Print_Object({})") 37 38def jlh(debugger, param, *args): 39 """Print v8::Local handle value""" 40 ptr_arg_cmd(debugger, 'jlh', param, 41 "_v8_internal_Print_Object(*(v8::internal::Object**)(*{}))") 42 43def jco(debugger, param, *args): 44 """Print the code object at the given pc (default: current pc)""" 45 if not param: 46 param = str(current_frame(debugger).FindRegister("pc").value) 47 ptr_arg_cmd(debugger, 'jco', param, "_v8_internal_Print_Code({})") 48 49def jld(debugger, param, *args): 50 """Print a v8 LayoutDescriptor object""" 51 ptr_arg_cmd(debugger, 'jld', param, 52 "_v8_internal_Print_LayoutDescriptor({})") 53 54def jtt(debugger, param, *args): 55 """Print the transition tree of a v8 Map""" 56 ptr_arg_cmd(debugger, 'jtt', param, "_v8_internal_Print_TransitionTree({})") 57 58def jst(debugger, *args): 59 """Print the current JavaScript stack trace""" 60 no_arg_cmd(debugger, "_v8_internal_Print_StackTrace()") 61 62def jss(debugger, *args): 63 """Skip the jitted stack on x64 to where we entered JS last""" 64 frame = current_frame(debugger) 65 js_entry_sp = frame.EvaluateExpression( 66 "v8::internal::Isolate::Current()->thread_local_top()->js_entry_sp_;") \ 67 .GetValue() 68 sizeof_void = frame.EvaluateExpression("sizeof(void*)").GetValue() 69 rbp = frame.FindRegister("rbp") 70 rsp = frame.FindRegister("rsp") 71 pc = frame.FindRegister("pc") 72 rbp = js_entry_sp 73 rsp = js_entry_sp + 2 *sizeof_void 74 pc.value = js_entry_sp + sizeof_void 75 76def bta(debugger, *args): 77 """Print stack trace with assertion scopes""" 78 func_name_re = re.compile("([^(<]+)(?:\(.+\))?") 79 assert_re = re.compile( 80 "^v8::internal::Per\w+AssertType::(\w+)_ASSERT, (false|true)>") 81 thread = current_thread(debugger) 82 for frame in thread: 83 functionSignature = frame.GetDisplayFunctionName() 84 if functionSignature is None: 85 continue 86 functionName = func_name_re.match(functionSignature) 87 line = frame.GetLineEntry().GetLine() 88 sourceFile = frame.GetLineEntry().GetFileSpec().GetFilename() 89 if line: 90 sourceFile = sourceFile + ":" + str(line) 91 92 if sourceFile is None: 93 sourceFile = "" 94 print("[%-2s] %-60s %-40s" % (frame.GetFrameID(), 95 functionName.group(1), 96 sourceFile)) 97 match = assert_re.match(str(functionSignature)) 98 if match: 99 if match.group(3) == "false": 100 prefix = "Disallow" 101 color = "\033[91m" 102 else: 103 prefix = "Allow" 104 color = "\033[92m" 105 print("%s -> %s %s (%s)\033[0m" % ( 106 color, prefix, match.group(2), match.group(1))) 107 108def __lldb_init_module(debugger, dict): 109 debugger.HandleCommand('settings set target.x86-disassembly-flavor intel') 110 for cmd in ('job', 'jlh', 'jco', 'jld', 'jtt', 'jst', 'jss', 'bta'): 111 debugger.HandleCommand( 112 'command script add -f lldb_commands.{} {}'.format(cmd, cmd)) 113