1*1020150eSMehdi Amini#!/usr/bin/env python 2*1020150eSMehdi Amini 3*1020150eSMehdi Amini# --------------------------------------------------------------------- 4*1020150eSMehdi Amini# Be sure to add the python path that points to the LLDB shared library. 5*1020150eSMehdi Amini# 6*1020150eSMehdi Amini# # To use this in the embedded python interpreter using "lldb" just 7*1020150eSMehdi Amini# import it with the full path using the "command script import" 8*1020150eSMehdi Amini# command 9*1020150eSMehdi Amini# (lldb) command script import /path/to/cmdtemplate.py 10*1020150eSMehdi Amini# --------------------------------------------------------------------- 11*1020150eSMehdi Amini 12*1020150eSMehdi Aminiimport inspect 13*1020150eSMehdi Aminiimport lldb 14*1020150eSMehdi Aminiimport argparse 15*1020150eSMehdi Aminiimport shlex 16*1020150eSMehdi Aminiimport sys 17*1020150eSMehdi Amini 18*1020150eSMehdi Amini# Each new breakpoint gets a unique ID starting from 1. 19*1020150eSMehdi Amininextid = 1 20*1020150eSMehdi Amini# List of breakpoint set from python, the key is the ID and the value the 21*1020150eSMehdi Amini# actual breakpoint. These are NOT LLDB SBBreakpoint objects. 22*1020150eSMehdi Aminibreakpoints = dict() 23*1020150eSMehdi Amini 24*1020150eSMehdi AminiexprOptions = lldb.SBExpressionOptions() 25*1020150eSMehdi AminiexprOptions.SetIgnoreBreakpoints() 26*1020150eSMehdi AminiexprOptions.SetLanguage(lldb.eLanguageTypeC) 27*1020150eSMehdi Amini 28*1020150eSMehdi Amini 29*1020150eSMehdi Aminiclass MlirDebug: 30*1020150eSMehdi Amini """MLIR debugger commands 31*1020150eSMehdi Amini This is the class that hooks into LLDB and registers the `mlir` command. 32*1020150eSMehdi Amini Other providers can register subcommands below this one. 33*1020150eSMehdi Amini """ 34*1020150eSMehdi Amini 35*1020150eSMehdi Amini lldb_command = "mlir" 36*1020150eSMehdi Amini parser = None 37*1020150eSMehdi Amini 38*1020150eSMehdi Amini def __init__(self, debugger, unused): 39*1020150eSMehdi Amini super().__init__() 40*1020150eSMehdi Amini self.create_options() 41*1020150eSMehdi Amini self.help_string = MlirDebug.parser.format_help() 42*1020150eSMehdi Amini 43*1020150eSMehdi Amini @classmethod 44*1020150eSMehdi Amini def create_options(cls): 45*1020150eSMehdi Amini if MlirDebug.parser: 46*1020150eSMehdi Amini return MlirDebug.parser 47*1020150eSMehdi Amini usage = "usage: %s [options]" % (cls.lldb_command) 48*1020150eSMehdi Amini description = "TODO." 49*1020150eSMehdi Amini 50*1020150eSMehdi Amini # Pass add_help_option = False, since this keeps the command in line 51*1020150eSMehdi Amini # with lldb commands, and we wire up "help command" to work by 52*1020150eSMehdi Amini # providing the long & short help methods below. 53*1020150eSMehdi Amini MlirDebug.parser = argparse.ArgumentParser( 54*1020150eSMehdi Amini prog=cls.lldb_command, usage=usage, description=description, add_help=False 55*1020150eSMehdi Amini ) 56*1020150eSMehdi Amini MlirDebug.subparsers = MlirDebug.parser.add_subparsers(dest="command") 57*1020150eSMehdi Amini return MlirDebug.parser 58*1020150eSMehdi Amini 59*1020150eSMehdi Amini def get_short_help(self): 60*1020150eSMehdi Amini return "MLIR debugger commands" 61*1020150eSMehdi Amini 62*1020150eSMehdi Amini def get_long_help(self): 63*1020150eSMehdi Amini return self.help_string 64*1020150eSMehdi Amini 65*1020150eSMehdi Amini def __call__(self, debugger, command, exe_ctx, result): 66*1020150eSMehdi Amini # Use the Shell Lexer to properly parse up command options just like a 67*1020150eSMehdi Amini # shell would 68*1020150eSMehdi Amini command_args = shlex.split(command) 69*1020150eSMehdi Amini 70*1020150eSMehdi Amini try: 71*1020150eSMehdi Amini args = MlirDebug.parser.parse_args(command_args) 72*1020150eSMehdi Amini except: 73*1020150eSMehdi Amini result.SetError("option parsing failed") 74*1020150eSMehdi Amini raise 75*1020150eSMehdi Amini args.func(args, debugger, command, exe_ctx, result) 76*1020150eSMehdi Amini 77*1020150eSMehdi Amini @classmethod 78*1020150eSMehdi Amini def on_process_start(frame, bp_loc, dict): 79*1020150eSMehdi Amini print("Process started") 80*1020150eSMehdi Amini 81*1020150eSMehdi Amini 82*1020150eSMehdi Aminiclass SetControl: 83*1020150eSMehdi Amini # Define the subcommands that controls what to do when a breakpoint is hit. 84*1020150eSMehdi Amini # The key is the subcommand name, the value is a tuple of the command ID to 85*1020150eSMehdi Amini # pass to MLIR and the help string. 86*1020150eSMehdi Amini commands = { 87*1020150eSMehdi Amini "apply": (1, "Apply the current action and continue the execution"), 88*1020150eSMehdi Amini "skip": (2, "Skip the current action and continue the execution"), 89*1020150eSMehdi Amini "step": (3, "Step into the current action"), 90*1020150eSMehdi Amini "next": (4, "Step over the current action"), 91*1020150eSMehdi Amini "finish": (5, "Step out of the current action"), 92*1020150eSMehdi Amini } 93*1020150eSMehdi Amini 94*1020150eSMehdi Amini @classmethod 95*1020150eSMehdi Amini def register_mlir_subparser(cls): 96*1020150eSMehdi Amini for cmd, (cmdInt, help) in cls.commands.items(): 97*1020150eSMehdi Amini parser = MlirDebug.subparsers.add_parser( 98*1020150eSMehdi Amini cmd, 99*1020150eSMehdi Amini help=help, 100*1020150eSMehdi Amini ) 101*1020150eSMehdi Amini parser.set_defaults(func=cls.process_options) 102*1020150eSMehdi Amini 103*1020150eSMehdi Amini @classmethod 104*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 105*1020150eSMehdi Amini frame = exe_ctx.GetFrame() 106*1020150eSMehdi Amini if not frame.IsValid(): 107*1020150eSMehdi Amini result.SetError("No valid frame (program not running?)") 108*1020150eSMehdi Amini return 109*1020150eSMehdi Amini cmdInt = cls.commands.get(options.command, None) 110*1020150eSMehdi Amini if not cmdInt: 111*1020150eSMehdi Amini result.SetError("Invalid command: %s" % (options.command)) 112*1020150eSMehdi Amini return 113*1020150eSMehdi Amini 114*1020150eSMehdi Amini result = frame.EvaluateExpression( 115*1020150eSMehdi Amini "((bool (*)(int))mlirDebuggerSetControl)(%d)" % (cmdInt[0]), 116*1020150eSMehdi Amini exprOptions, 117*1020150eSMehdi Amini ) 118*1020150eSMehdi Amini if not result.error.Success(): 119*1020150eSMehdi Amini print("Error setting up command: %s" % (result.error)) 120*1020150eSMehdi Amini return 121*1020150eSMehdi Amini debugger.SetAsync(True) 122*1020150eSMehdi Amini result = exe_ctx.GetProcess().Continue() 123*1020150eSMehdi Amini debugger.SetAsync(False) 124*1020150eSMehdi Amini 125*1020150eSMehdi Amini 126*1020150eSMehdi Aminiclass PrintContext: 127*1020150eSMehdi Amini @classmethod 128*1020150eSMehdi Amini def register_mlir_subparser(cls): 129*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 130*1020150eSMehdi Amini "context", help="Print the current context" 131*1020150eSMehdi Amini ) 132*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 133*1020150eSMehdi Amini 134*1020150eSMehdi Amini @classmethod 135*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 136*1020150eSMehdi Amini frame = exe_ctx.GetFrame() 137*1020150eSMehdi Amini if not frame.IsValid(): 138*1020150eSMehdi Amini result.SetError("Can't print context without a valid frame") 139*1020150eSMehdi Amini return 140*1020150eSMehdi Amini result = frame.EvaluateExpression( 141*1020150eSMehdi Amini "((bool (*)())&mlirDebuggerPrintContext)()", exprOptions 142*1020150eSMehdi Amini ) 143*1020150eSMehdi Amini if not result.error.Success(): 144*1020150eSMehdi Amini print("Error printing context: %s" % (result.error)) 145*1020150eSMehdi Amini return 146*1020150eSMehdi Amini 147*1020150eSMehdi Amini 148*1020150eSMehdi Aminiclass Backtrace: 149*1020150eSMehdi Amini @classmethod 150*1020150eSMehdi Amini def register_mlir_subparser(cls): 151*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 152*1020150eSMehdi Amini "backtrace", aliases=["bt"], help="Print the current backtrace" 153*1020150eSMehdi Amini ) 154*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 155*1020150eSMehdi Amini cls.parser.add_argument("--context", default=False, action="store_true") 156*1020150eSMehdi Amini 157*1020150eSMehdi Amini @classmethod 158*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 159*1020150eSMehdi Amini frame = exe_ctx.GetFrame() 160*1020150eSMehdi Amini if not frame.IsValid(): 161*1020150eSMehdi Amini result.SetError( 162*1020150eSMehdi Amini "Can't backtrace without a valid frame (program not running?)" 163*1020150eSMehdi Amini ) 164*1020150eSMehdi Amini result = frame.EvaluateExpression( 165*1020150eSMehdi Amini "((bool(*)(bool))mlirDebuggerPrintActionBacktrace)(%d)" % (options.context), 166*1020150eSMehdi Amini exprOptions, 167*1020150eSMehdi Amini ) 168*1020150eSMehdi Amini if not result.error.Success(): 169*1020150eSMehdi Amini print("Error printing breakpoints: %s" % (result.error)) 170*1020150eSMehdi Amini return 171*1020150eSMehdi Amini 172*1020150eSMehdi Amini 173*1020150eSMehdi Amini############################################################################### 174*1020150eSMehdi Amini# Cursor manipulation 175*1020150eSMehdi Amini############################################################################### 176*1020150eSMehdi Amini 177*1020150eSMehdi Amini 178*1020150eSMehdi Aminiclass PrintCursor: 179*1020150eSMehdi Amini @classmethod 180*1020150eSMehdi Amini def register_mlir_subparser(cls): 181*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 182*1020150eSMehdi Amini "cursor-print", aliases=["cursor-p"], help="Print the current cursor" 183*1020150eSMehdi Amini ) 184*1020150eSMehdi Amini cls.parser.add_argument( 185*1020150eSMehdi Amini "--print-region", "--regions", "-r", default=False, action="store_true" 186*1020150eSMehdi Amini ) 187*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 188*1020150eSMehdi Amini 189*1020150eSMehdi Amini @classmethod 190*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 191*1020150eSMehdi Amini frame = exe_ctx.GetFrame() 192*1020150eSMehdi Amini if not frame.IsValid(): 193*1020150eSMehdi Amini result.SetError( 194*1020150eSMehdi Amini "Can't print cursor without a valid frame (program not running?)" 195*1020150eSMehdi Amini ) 196*1020150eSMehdi Amini result = frame.EvaluateExpression( 197*1020150eSMehdi Amini "((bool(*)(bool))mlirDebuggerCursorPrint)(%d)" % (options.print_region), 198*1020150eSMehdi Amini exprOptions, 199*1020150eSMehdi Amini ) 200*1020150eSMehdi Amini if not result.error.Success(): 201*1020150eSMehdi Amini print("Error printing cursor: %s" % (result.error)) 202*1020150eSMehdi Amini return 203*1020150eSMehdi Amini 204*1020150eSMehdi Amini 205*1020150eSMehdi Aminiclass SelectCursorFromContext: 206*1020150eSMehdi Amini @classmethod 207*1020150eSMehdi Amini def register_mlir_subparser(cls): 208*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 209*1020150eSMehdi Amini "cursor-select-from-context", 210*1020150eSMehdi Amini aliases=["cursor-s"], 211*1020150eSMehdi Amini help="Select the cursor from the current context", 212*1020150eSMehdi Amini ) 213*1020150eSMehdi Amini cls.parser.add_argument("index", type=int, help="Index in the context") 214*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 215*1020150eSMehdi Amini 216*1020150eSMehdi Amini @classmethod 217*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 218*1020150eSMehdi Amini frame = exe_ctx.GetFrame() 219*1020150eSMehdi Amini if not frame.IsValid(): 220*1020150eSMehdi Amini result.SetError( 221*1020150eSMehdi Amini "Can't manipulate cursor without a valid frame (program not running?)" 222*1020150eSMehdi Amini ) 223*1020150eSMehdi Amini result = frame.EvaluateExpression( 224*1020150eSMehdi Amini "((bool(*)(int))mlirDebuggerCursorSelectIRUnitFromContext)(%d)" 225*1020150eSMehdi Amini % options.index, 226*1020150eSMehdi Amini exprOptions, 227*1020150eSMehdi Amini ) 228*1020150eSMehdi Amini if not result.error.Success(): 229*1020150eSMehdi Amini print("Error manipulating cursor: %s" % (result.error)) 230*1020150eSMehdi Amini return 231*1020150eSMehdi Amini 232*1020150eSMehdi Amini 233*1020150eSMehdi Aminiclass CursorSelectParent: 234*1020150eSMehdi Amini @classmethod 235*1020150eSMehdi Amini def register_mlir_subparser(cls): 236*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 237*1020150eSMehdi Amini "cursor-parent", aliases=["cursor-up"], help="Select the cursor parent" 238*1020150eSMehdi Amini ) 239*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 240*1020150eSMehdi Amini 241*1020150eSMehdi Amini @classmethod 242*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 243*1020150eSMehdi Amini frame = exe_ctx.GetFrame() 244*1020150eSMehdi Amini if not frame.IsValid(): 245*1020150eSMehdi Amini result.SetError( 246*1020150eSMehdi Amini "Can't manipulate cursor without a valid frame (program not running?)" 247*1020150eSMehdi Amini ) 248*1020150eSMehdi Amini result = frame.EvaluateExpression( 249*1020150eSMehdi Amini "((bool(*)())mlirDebuggerCursorSelectParentIRUnit)()", 250*1020150eSMehdi Amini exprOptions, 251*1020150eSMehdi Amini ) 252*1020150eSMehdi Amini if not result.error.Success(): 253*1020150eSMehdi Amini print("Error manipulating cursor: %s" % (result.error)) 254*1020150eSMehdi Amini return 255*1020150eSMehdi Amini 256*1020150eSMehdi Amini 257*1020150eSMehdi Aminiclass SelectCursorChild: 258*1020150eSMehdi Amini @classmethod 259*1020150eSMehdi Amini def register_mlir_subparser(cls): 260*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 261*1020150eSMehdi Amini "cursor-child", aliases=["cursor-c"], help="Select the nth child" 262*1020150eSMehdi Amini ) 263*1020150eSMehdi Amini cls.parser.add_argument("index", type=int, help="Index of the child to select") 264*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 265*1020150eSMehdi Amini 266*1020150eSMehdi Amini @classmethod 267*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 268*1020150eSMehdi Amini frame = exe_ctx.GetFrame() 269*1020150eSMehdi Amini if not frame.IsValid(): 270*1020150eSMehdi Amini result.SetError( 271*1020150eSMehdi Amini "Can't manipulate cursor without a valid frame (program not running?)" 272*1020150eSMehdi Amini ) 273*1020150eSMehdi Amini result = frame.EvaluateExpression( 274*1020150eSMehdi Amini "((bool(*)(int))mlirDebuggerCursorSelectChildIRUnit)(%d)" % options.index, 275*1020150eSMehdi Amini exprOptions, 276*1020150eSMehdi Amini ) 277*1020150eSMehdi Amini if not result.error.Success(): 278*1020150eSMehdi Amini print("Error manipulating cursor: %s" % (result.error)) 279*1020150eSMehdi Amini return 280*1020150eSMehdi Amini 281*1020150eSMehdi Amini 282*1020150eSMehdi Aminiclass CursorSelecPrevious: 283*1020150eSMehdi Amini @classmethod 284*1020150eSMehdi Amini def register_mlir_subparser(cls): 285*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 286*1020150eSMehdi Amini "cursor-previous", 287*1020150eSMehdi Amini aliases=["cursor-prev"], 288*1020150eSMehdi Amini help="Select the cursor previous element", 289*1020150eSMehdi Amini ) 290*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 291*1020150eSMehdi Amini 292*1020150eSMehdi Amini @classmethod 293*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 294*1020150eSMehdi Amini frame = exe_ctx.GetFrame() 295*1020150eSMehdi Amini if not frame.IsValid(): 296*1020150eSMehdi Amini result.SetError( 297*1020150eSMehdi Amini "Can't manipulate cursor without a valid frame (program not running?)" 298*1020150eSMehdi Amini ) 299*1020150eSMehdi Amini result = frame.EvaluateExpression( 300*1020150eSMehdi Amini "((bool(*)())mlirDebuggerCursorSelectPreviousIRUnit)()", 301*1020150eSMehdi Amini exprOptions, 302*1020150eSMehdi Amini ) 303*1020150eSMehdi Amini if not result.error.Success(): 304*1020150eSMehdi Amini print("Error manipulating cursor: %s" % (result.error)) 305*1020150eSMehdi Amini return 306*1020150eSMehdi Amini 307*1020150eSMehdi Amini 308*1020150eSMehdi Aminiclass CursorSelecNext: 309*1020150eSMehdi Amini @classmethod 310*1020150eSMehdi Amini def register_mlir_subparser(cls): 311*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 312*1020150eSMehdi Amini "cursor-next", aliases=["cursor-n"], help="Select the cursor next element" 313*1020150eSMehdi Amini ) 314*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 315*1020150eSMehdi Amini 316*1020150eSMehdi Amini @classmethod 317*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 318*1020150eSMehdi Amini frame = exe_ctx.GetFrame() 319*1020150eSMehdi Amini if not frame.IsValid(): 320*1020150eSMehdi Amini result.SetError( 321*1020150eSMehdi Amini "Can't manipulate cursor without a valid frame (program not running?)" 322*1020150eSMehdi Amini ) 323*1020150eSMehdi Amini result = frame.EvaluateExpression( 324*1020150eSMehdi Amini "((bool(*)())mlirDebuggerCursorSelectNextIRUnit)()", 325*1020150eSMehdi Amini exprOptions, 326*1020150eSMehdi Amini ) 327*1020150eSMehdi Amini if not result.error.Success(): 328*1020150eSMehdi Amini print("Error manipulating cursor: %s" % (result.error)) 329*1020150eSMehdi Amini return 330*1020150eSMehdi Amini 331*1020150eSMehdi Amini 332*1020150eSMehdi Amini############################################################################### 333*1020150eSMehdi Amini# Breakpoints 334*1020150eSMehdi Amini############################################################################### 335*1020150eSMehdi Amini 336*1020150eSMehdi Amini 337*1020150eSMehdi Aminiclass EnableBreakpoint: 338*1020150eSMehdi Amini @classmethod 339*1020150eSMehdi Amini def register_mlir_subparser(cls): 340*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 341*1020150eSMehdi Amini "enable", help="Enable a single breakpoint (given its ID)" 342*1020150eSMehdi Amini ) 343*1020150eSMehdi Amini cls.parser.add_argument("id", help="ID of the breakpoint to enable") 344*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 345*1020150eSMehdi Amini 346*1020150eSMehdi Amini @classmethod 347*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 348*1020150eSMehdi Amini bp = breakpoints.get(int(options.id), None) 349*1020150eSMehdi Amini if not bp: 350*1020150eSMehdi Amini result.SetError("No breakpoint with ID %d" % int(options.id)) 351*1020150eSMehdi Amini return 352*1020150eSMehdi Amini bp.enable(exe_ctx.GetFrame()) 353*1020150eSMehdi Amini 354*1020150eSMehdi Amini 355*1020150eSMehdi Aminiclass DisableBreakpoint: 356*1020150eSMehdi Amini @classmethod 357*1020150eSMehdi Amini def register_mlir_subparser(cls): 358*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 359*1020150eSMehdi Amini "disable", help="Disable a single breakpoint (given its ID)" 360*1020150eSMehdi Amini ) 361*1020150eSMehdi Amini cls.parser.add_argument("id", help="ID of the breakpoint to disable") 362*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 363*1020150eSMehdi Amini 364*1020150eSMehdi Amini @classmethod 365*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 366*1020150eSMehdi Amini bp = breakpoints.get(int(options.id), None) 367*1020150eSMehdi Amini if not bp: 368*1020150eSMehdi Amini result.SetError("No breakpoint with ID %s" % options.id) 369*1020150eSMehdi Amini return 370*1020150eSMehdi Amini bp.disable(exe_ctx.GetFrame()) 371*1020150eSMehdi Amini 372*1020150eSMehdi Amini 373*1020150eSMehdi Aminiclass ListBreakpoints: 374*1020150eSMehdi Amini @classmethod 375*1020150eSMehdi Amini def register_mlir_subparser(cls): 376*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 377*1020150eSMehdi Amini "list", help="List all current breakpoints" 378*1020150eSMehdi Amini ) 379*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 380*1020150eSMehdi Amini 381*1020150eSMehdi Amini @classmethod 382*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 383*1020150eSMehdi Amini for id, bp in sorted(breakpoints.items()): 384*1020150eSMehdi Amini print(id, type(id), str(bp), "enabled" if bp.isEnabled else "disabled") 385*1020150eSMehdi Amini 386*1020150eSMehdi Amini 387*1020150eSMehdi Aminiclass Breakpoint: 388*1020150eSMehdi Amini def __init__(self): 389*1020150eSMehdi Amini global nextid 390*1020150eSMehdi Amini self.id = nextid 391*1020150eSMehdi Amini nextid += 1 392*1020150eSMehdi Amini breakpoints[self.id] = self 393*1020150eSMehdi Amini self.isEnabled = True 394*1020150eSMehdi Amini 395*1020150eSMehdi Amini def enable(self, frame=None): 396*1020150eSMehdi Amini self.isEnabled = True 397*1020150eSMehdi Amini if not frame or not frame.IsValid(): 398*1020150eSMehdi Amini return 399*1020150eSMehdi Amini # use a C cast to force the type of the breakpoint handle to be void * so 400*1020150eSMehdi Amini # that we don't rely on DWARF. Also add a fake bool return value otherwise 401*1020150eSMehdi Amini # LLDB can't signal any error with the expression evaluation (at least I don't know how). 402*1020150eSMehdi Amini cmd = ( 403*1020150eSMehdi Amini "((bool (*)(void *))mlirDebuggerEnableBreakpoint)((void *)%s)" % self.handle 404*1020150eSMehdi Amini ) 405*1020150eSMehdi Amini result = frame.EvaluateExpression(cmd, exprOptions) 406*1020150eSMehdi Amini if not result.error.Success(): 407*1020150eSMehdi Amini print("Error enabling breakpoint: %s" % (result.error)) 408*1020150eSMehdi Amini return 409*1020150eSMehdi Amini 410*1020150eSMehdi Amini def disable(self, frame=None): 411*1020150eSMehdi Amini self.isEnabled = False 412*1020150eSMehdi Amini if not frame or not frame.IsValid(): 413*1020150eSMehdi Amini return 414*1020150eSMehdi Amini # use a C cast to force the type of the breakpoint handle to be void * so 415*1020150eSMehdi Amini # that we don't rely on DWARF. Also add a fake bool return value otherwise 416*1020150eSMehdi Amini # LLDB can't signal any error with the expression evaluation (at least I don't know how). 417*1020150eSMehdi Amini cmd = ( 418*1020150eSMehdi Amini "((bool (*)(void *)) mlirDebuggerDisableBreakpoint)((void *)%s)" 419*1020150eSMehdi Amini % self.handle 420*1020150eSMehdi Amini ) 421*1020150eSMehdi Amini result = frame.EvaluateExpression(cmd, exprOptions) 422*1020150eSMehdi Amini if not result.error.Success(): 423*1020150eSMehdi Amini print("Error disabling breakpoint: %s" % (result.error)) 424*1020150eSMehdi Amini return 425*1020150eSMehdi Amini 426*1020150eSMehdi Amini 427*1020150eSMehdi Aminiclass TagBreakpoint(Breakpoint): 428*1020150eSMehdi Amini mlir_subcommand = "break-on-tag" 429*1020150eSMehdi Amini 430*1020150eSMehdi Amini def __init__(self, tag): 431*1020150eSMehdi Amini super().__init__() 432*1020150eSMehdi Amini self.tag = tag 433*1020150eSMehdi Amini 434*1020150eSMehdi Amini def __str__(self): 435*1020150eSMehdi Amini return "[%d] TagBreakpoint(%s)" % (self.id, self.tag) 436*1020150eSMehdi Amini 437*1020150eSMehdi Amini @classmethod 438*1020150eSMehdi Amini def register_mlir_subparser(cls): 439*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 440*1020150eSMehdi Amini cls.mlir_subcommand, help="add a breakpoint on actions' tag matching" 441*1020150eSMehdi Amini ) 442*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 443*1020150eSMehdi Amini cls.parser.add_argument("tag", help="tag to match") 444*1020150eSMehdi Amini 445*1020150eSMehdi Amini @classmethod 446*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 447*1020150eSMehdi Amini breakpoint = TagBreakpoint(options.tag) 448*1020150eSMehdi Amini print("Added breakpoint %s" % str(breakpoint)) 449*1020150eSMehdi Amini 450*1020150eSMehdi Amini frame = exe_ctx.GetFrame() 451*1020150eSMehdi Amini if frame.IsValid(): 452*1020150eSMehdi Amini breakpoint.install(frame) 453*1020150eSMehdi Amini 454*1020150eSMehdi Amini def install(self, frame): 455*1020150eSMehdi Amini result = frame.EvaluateExpression( 456*1020150eSMehdi Amini '((void *(*)(const char *))mlirDebuggerAddTagBreakpoint)("%s")' 457*1020150eSMehdi Amini % (self.tag), 458*1020150eSMehdi Amini exprOptions, 459*1020150eSMehdi Amini ) 460*1020150eSMehdi Amini if not result.error.Success(): 461*1020150eSMehdi Amini print("Error installing breakpoint: %s" % (result.error)) 462*1020150eSMehdi Amini return 463*1020150eSMehdi Amini # Save the handle, this is necessary to implement enable/disable. 464*1020150eSMehdi Amini self.handle = result.GetValue() 465*1020150eSMehdi Amini 466*1020150eSMehdi Amini 467*1020150eSMehdi Aminiclass FileLineBreakpoint(Breakpoint): 468*1020150eSMehdi Amini mlir_subcommand = "break-on-file" 469*1020150eSMehdi Amini 470*1020150eSMehdi Amini def __init__(self, file, line, col): 471*1020150eSMehdi Amini super().__init__() 472*1020150eSMehdi Amini self.file = file 473*1020150eSMehdi Amini self.line = line 474*1020150eSMehdi Amini self.col = col 475*1020150eSMehdi Amini 476*1020150eSMehdi Amini def __str__(self): 477*1020150eSMehdi Amini return "[%d] FileLineBreakpoint(%s, %d, %d)" % ( 478*1020150eSMehdi Amini self.id, 479*1020150eSMehdi Amini self.file, 480*1020150eSMehdi Amini self.line, 481*1020150eSMehdi Amini self.col, 482*1020150eSMehdi Amini ) 483*1020150eSMehdi Amini 484*1020150eSMehdi Amini @classmethod 485*1020150eSMehdi Amini def register_mlir_subparser(cls): 486*1020150eSMehdi Amini cls.parser = MlirDebug.subparsers.add_parser( 487*1020150eSMehdi Amini cls.mlir_subcommand, 488*1020150eSMehdi Amini help="add a breakpoint that filters on location of the IR affected by an action. The syntax is file:line:col where file and col are optional", 489*1020150eSMehdi Amini ) 490*1020150eSMehdi Amini cls.parser.set_defaults(func=cls.process_options) 491*1020150eSMehdi Amini cls.parser.add_argument("location", type=str) 492*1020150eSMehdi Amini 493*1020150eSMehdi Amini @classmethod 494*1020150eSMehdi Amini def process_options(cls, options, debugger, command, exe_ctx, result): 495*1020150eSMehdi Amini split_loc = options.location.split(":") 496*1020150eSMehdi Amini file = split_loc[0] 497*1020150eSMehdi Amini line = int(split_loc[1]) if len(split_loc) > 1 else -1 498*1020150eSMehdi Amini col = int(split_loc[2]) if len(split_loc) > 2 else -1 499*1020150eSMehdi Amini breakpoint = FileLineBreakpoint(file, line, col) 500*1020150eSMehdi Amini print("Added breakpoint %s" % str(breakpoint)) 501*1020150eSMehdi Amini 502*1020150eSMehdi Amini frame = exe_ctx.GetFrame() 503*1020150eSMehdi Amini if frame.IsValid(): 504*1020150eSMehdi Amini breakpoint.install(frame) 505*1020150eSMehdi Amini 506*1020150eSMehdi Amini def install(self, frame): 507*1020150eSMehdi Amini result = frame.EvaluateExpression( 508*1020150eSMehdi Amini '((void *(*)(const char *, int, int))mlirDebuggerAddFileLineColLocBreakpoint)("%s", %d, %d)' 509*1020150eSMehdi Amini % (self.file, self.line, self.col), 510*1020150eSMehdi Amini exprOptions, 511*1020150eSMehdi Amini ) 512*1020150eSMehdi Amini if not result.error.Success(): 513*1020150eSMehdi Amini print("Error installing breakpoint: %s" % (result.error)) 514*1020150eSMehdi Amini return 515*1020150eSMehdi Amini # Save the handle, this is necessary to implement enable/disable. 516*1020150eSMehdi Amini self.handle = result.GetValue() 517*1020150eSMehdi Amini 518*1020150eSMehdi Amini 519*1020150eSMehdi Aminidef on_start(frame, bpno, err): 520*1020150eSMehdi Amini print("MLIR debugger attaching...") 521*1020150eSMehdi Amini for _, bp in sorted(breakpoints.items()): 522*1020150eSMehdi Amini if bp.isEnabled: 523*1020150eSMehdi Amini print("Installing breakpoint %s" % (str(bp))) 524*1020150eSMehdi Amini bp.install(frame) 525*1020150eSMehdi Amini else: 526*1020150eSMehdi Amini print("Skipping disabled breakpoint %s" % (str(bp))) 527*1020150eSMehdi Amini 528*1020150eSMehdi Amini return True 529*1020150eSMehdi Amini 530*1020150eSMehdi Amini 531*1020150eSMehdi Aminidef __lldb_init_module(debugger, dict): 532*1020150eSMehdi Amini target = debugger.GetTargetAtIndex(0) 533*1020150eSMehdi Amini debugger.SetAsync(False) 534*1020150eSMehdi Amini if not target: 535*1020150eSMehdi Amini print("No target is loaded, please load a target before loading this script.") 536*1020150eSMehdi Amini return 537*1020150eSMehdi Amini if debugger.GetNumTargets() > 1: 538*1020150eSMehdi Amini print( 539*1020150eSMehdi Amini "Multiple targets (%s) loaded, attaching MLIR debugging to %s" 540*1020150eSMehdi Amini % (debugger.GetNumTargets(), target) 541*1020150eSMehdi Amini ) 542*1020150eSMehdi Amini 543*1020150eSMehdi Amini # Register all classes that have a register_lldb_command method 544*1020150eSMehdi Amini module_name = __name__ 545*1020150eSMehdi Amini parser = MlirDebug.create_options() 546*1020150eSMehdi Amini MlirDebug.__doc__ = parser.format_help() 547*1020150eSMehdi Amini 548*1020150eSMehdi Amini # Add the MLIR entry point to LLDB as a command. 549*1020150eSMehdi Amini command = "command script add -o -c %s.%s %s" % ( 550*1020150eSMehdi Amini module_name, 551*1020150eSMehdi Amini MlirDebug.__name__, 552*1020150eSMehdi Amini MlirDebug.lldb_command, 553*1020150eSMehdi Amini ) 554*1020150eSMehdi Amini debugger.HandleCommand(command) 555*1020150eSMehdi Amini 556*1020150eSMehdi Amini main_bp = target.BreakpointCreateByName("main") 557*1020150eSMehdi Amini main_bp.SetScriptCallbackFunction("action_debugging.on_start") 558*1020150eSMehdi Amini main_bp.SetAutoContinue(auto_continue=True) 559*1020150eSMehdi Amini 560*1020150eSMehdi Amini on_breackpoint = target.BreakpointCreateByName("mlirDebuggerBreakpointHook") 561*1020150eSMehdi Amini 562*1020150eSMehdi Amini print( 563*1020150eSMehdi Amini 'The "{0}" command has been installed for target `{1}`, type "help {0}" or "{0} ' 564*1020150eSMehdi Amini '--help" for detailed help.'.format(MlirDebug.lldb_command, target) 565*1020150eSMehdi Amini ) 566*1020150eSMehdi Amini for _name, cls in inspect.getmembers(sys.modules[module_name]): 567*1020150eSMehdi Amini if inspect.isclass(cls) and getattr(cls, "register_mlir_subparser", None): 568*1020150eSMehdi Amini cls.register_mlir_subparser() 569