11cb0ef41Sopenharmony_ci# Copyright 2017 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci# found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci# Load this file by adding this to your ~/.lldbinit:
61cb0ef41Sopenharmony_ci# command script import <this_dir>/lldb_commands.py
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci# for py2/py3 compatibility
91cb0ef41Sopenharmony_cifrom __future__ import print_function
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ciimport os
121cb0ef41Sopenharmony_ciimport re
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciimport lldb
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci#####################
171cb0ef41Sopenharmony_ci# Helper functions. #
181cb0ef41Sopenharmony_ci#####################
191cb0ef41Sopenharmony_cidef current_thread(debugger):
201cb0ef41Sopenharmony_ci  return debugger.GetSelectedTarget().GetProcess().GetSelectedThread()
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_cidef current_frame(debugger):
231cb0ef41Sopenharmony_ci  return current_thread(debugger).GetSelectedFrame()
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_cidef no_arg_cmd(debugger, cmd):
261cb0ef41Sopenharmony_ci  cast_to_void_expr = '(void) {}'.format(cmd)
271cb0ef41Sopenharmony_ci  evaluate_result = current_frame(debugger).EvaluateExpression(cast_to_void_expr)
281cb0ef41Sopenharmony_ci  # When a void function is called the return value type is 0x1001 which
291cb0ef41Sopenharmony_ci  # is specified in http://tiny.cc/bigskz. This does not indicate
301cb0ef41Sopenharmony_ci  # an error so we check for that value below.
311cb0ef41Sopenharmony_ci  kNoResult = 0x1001
321cb0ef41Sopenharmony_ci  error = evaluate_result.GetError()
331cb0ef41Sopenharmony_ci  if error.fail and error.value != kNoResult:
341cb0ef41Sopenharmony_ci      print("Failed to evaluate command {} :".format(cmd))
351cb0ef41Sopenharmony_ci      print(error.description)
361cb0ef41Sopenharmony_ci  else:
371cb0ef41Sopenharmony_ci    print("")
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_cidef ptr_arg_cmd(debugger, name, param, cmd):
401cb0ef41Sopenharmony_ci  if not param:
411cb0ef41Sopenharmony_ci    print("'{}' requires an argument".format(name))
421cb0ef41Sopenharmony_ci    return
431cb0ef41Sopenharmony_ci  param = '(void*)({})'.format(param)
441cb0ef41Sopenharmony_ci  no_arg_cmd(debugger, cmd.format(param))
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci#####################
471cb0ef41Sopenharmony_ci# lldb commands.    #
481cb0ef41Sopenharmony_ci#####################
491cb0ef41Sopenharmony_cidef job(debugger, param, *args):
501cb0ef41Sopenharmony_ci  """Print a v8 heap object"""
511cb0ef41Sopenharmony_ci  ptr_arg_cmd(debugger, 'job', param, "_v8_internal_Print_Object({})")
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_cidef jlh(debugger, param, *args):
541cb0ef41Sopenharmony_ci  """Print v8::Local handle value"""
551cb0ef41Sopenharmony_ci  ptr_arg_cmd(debugger, 'jlh', param,
561cb0ef41Sopenharmony_ci              "_v8_internal_Print_Object(*(v8::internal::Object**)({}.val_))")
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_cidef jco(debugger, param, *args):
591cb0ef41Sopenharmony_ci  """Print the code object at the given pc (default: current pc)"""
601cb0ef41Sopenharmony_ci  if not param:
611cb0ef41Sopenharmony_ci    param = str(current_frame(debugger).FindRegister("pc").value)
621cb0ef41Sopenharmony_ci  ptr_arg_cmd(debugger, 'jco', param, "_v8_internal_Print_Code({})")
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_cidef jtt(debugger, param, *args):
651cb0ef41Sopenharmony_ci  """Print the transition tree of a v8 Map"""
661cb0ef41Sopenharmony_ci  ptr_arg_cmd(debugger, 'jtt', param, "_v8_internal_Print_TransitionTree({})")
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_cidef jst(debugger, *args):
691cb0ef41Sopenharmony_ci  """Print the current JavaScript stack trace"""
701cb0ef41Sopenharmony_ci  no_arg_cmd(debugger, "_v8_internal_Print_StackTrace()")
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_cidef jss(debugger, *args):
731cb0ef41Sopenharmony_ci  """Skip the jitted stack on x64 to where we entered JS last"""
741cb0ef41Sopenharmony_ci  frame = current_frame(debugger)
751cb0ef41Sopenharmony_ci  js_entry_sp = frame.EvaluateExpression(
761cb0ef41Sopenharmony_ci      "v8::internal::Isolate::Current()->thread_local_top()->js_entry_sp_;") \
771cb0ef41Sopenharmony_ci       .GetValue()
781cb0ef41Sopenharmony_ci  sizeof_void = frame.EvaluateExpression("sizeof(void*)").GetValue()
791cb0ef41Sopenharmony_ci  rbp = frame.FindRegister("rbp")
801cb0ef41Sopenharmony_ci  rsp = frame.FindRegister("rsp")
811cb0ef41Sopenharmony_ci  pc = frame.FindRegister("pc")
821cb0ef41Sopenharmony_ci  rbp = js_entry_sp
831cb0ef41Sopenharmony_ci  rsp = js_entry_sp + 2 *sizeof_void
841cb0ef41Sopenharmony_ci  pc.value = js_entry_sp + sizeof_void
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_cidef bta(debugger, *args):
871cb0ef41Sopenharmony_ci  """Print stack trace with assertion scopes"""
881cb0ef41Sopenharmony_ci  func_name_re = re.compile("([^(<]+)(?:\(.+\))?")
891cb0ef41Sopenharmony_ci  assert_re = re.compile(
901cb0ef41Sopenharmony_ci      "^v8::internal::Per\w+AssertType::(\w+)_ASSERT, (false|true)>")
911cb0ef41Sopenharmony_ci  thread = current_thread(debugger)
921cb0ef41Sopenharmony_ci  for frame in thread:
931cb0ef41Sopenharmony_ci    functionSignature = frame.GetDisplayFunctionName()
941cb0ef41Sopenharmony_ci    if functionSignature is None:
951cb0ef41Sopenharmony_ci      continue
961cb0ef41Sopenharmony_ci    functionName = func_name_re.match(functionSignature)
971cb0ef41Sopenharmony_ci    line = frame.GetLineEntry().GetLine()
981cb0ef41Sopenharmony_ci    sourceFile = frame.GetLineEntry().GetFileSpec().GetFilename()
991cb0ef41Sopenharmony_ci    if line:
1001cb0ef41Sopenharmony_ci      sourceFile = sourceFile + ":" + str(line)
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci    if sourceFile is None:
1031cb0ef41Sopenharmony_ci      sourceFile = ""
1041cb0ef41Sopenharmony_ci    print("[%-2s] %-60s %-40s" % (frame.GetFrameID(),
1051cb0ef41Sopenharmony_ci                                  functionName.group(1),
1061cb0ef41Sopenharmony_ci                                  sourceFile))
1071cb0ef41Sopenharmony_ci    match = assert_re.match(str(functionSignature))
1081cb0ef41Sopenharmony_ci    if match:
1091cb0ef41Sopenharmony_ci      if match.group(3) == "false":
1101cb0ef41Sopenharmony_ci        prefix = "Disallow"
1111cb0ef41Sopenharmony_ci        color = "\033[91m"
1121cb0ef41Sopenharmony_ci      else:
1131cb0ef41Sopenharmony_ci        prefix = "Allow"
1141cb0ef41Sopenharmony_ci        color = "\033[92m"
1151cb0ef41Sopenharmony_ci      print("%s -> %s %s (%s)\033[0m" % (
1161cb0ef41Sopenharmony_ci          color, prefix, match.group(2), match.group(1)))
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_cidef setup_source_map_for_relative_paths(debugger):
1191cb0ef41Sopenharmony_ci  # Copied from Chromium's tools/lldb/lldbinit.py.
1201cb0ef41Sopenharmony_ci  # When relative paths are used for debug symbols, lldb cannot find source
1211cb0ef41Sopenharmony_ci  # files. Set up a source map to point to V8's root.
1221cb0ef41Sopenharmony_ci  this_dir = os.path.dirname(os.path.abspath(__file__))
1231cb0ef41Sopenharmony_ci  source_dir = os.path.join(this_dir, os.pardir)
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  debugger.HandleCommand(
1261cb0ef41Sopenharmony_ci    'settings set target.source-map ../.. ' + source_dir)
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_cidef __lldb_init_module(debugger, dict):
1301cb0ef41Sopenharmony_ci  setup_source_map_for_relative_paths(debugger)
1311cb0ef41Sopenharmony_ci  debugger.HandleCommand('settings set target.x86-disassembly-flavor intel')
1321cb0ef41Sopenharmony_ci  for cmd in ('job', 'jlh', 'jco', 'jld', 'jtt', 'jst', 'jss', 'bta'):
1331cb0ef41Sopenharmony_ci    debugger.HandleCommand(
1341cb0ef41Sopenharmony_ci      'command script add -f lldb_commands.{} {}'.format(cmd, cmd))
135