[Lldb-commits] [PATCH] D51830: Add a way to make scripted breakpoints

Jim Ingham via Phabricator via lldb-commits lldb-commits at lists.llvm.org
Fri Sep 7 18:06:16 PDT 2018


jingham created this revision.
Herald added subscribers: lldb-commits, teemperor, abidh, jfb, srhines.

This change allows you to make a breakpoint resolver kernel in Python.

The breakpoint search mechanism in lldb works on top of a generic mechanism that uses a pair of Searcher - with its associated SearchFilter - and Resolver.  The Searcher iterates through the contours of a target, stopping at a depth (module, comp_unit, function...) specified by the Resolver.  If the object at the requested depth matches the search filter, then the Searcher calls the Resolver's SearchCallback function, handing it a SymbolContext representing that stage of the search.

In the case of a BreakpointResolver, if the Resolver finds any addresses in that SymbolContext which it wants to break on, it calls AddLocation on its owning Breakpoint to add that location to the breakpoint.

This change allows you to write a simple Python class to add whatever collection of locations makes sense using whatever logic you want.  The class must provide an __callback__ method that takes a SBSymbolContext.  This will get called at each appropriate stage of the search.  You can optionally provide a __get_depth__ method that returns the search depth (which defaults to Module if unspecified), and a get_short_help method that will be used in the breakpoint description.

When objects of the given class are constructed to represent a specific breakpoint, they are passed a StructuredData object which can be used to parametrize that particular breakpoint.  From the SB API's you can pass in an arbitrary SBStructuredData.  From the command line I added -k and -v options to "break set" that you provide in pairs to build up a StructuredData::Dictionary which is passed to the resolver.  Also, from the command-line the -f and -s options are used to construct the SearchFilter for the breakpoint's Searcher.

For instance, a simple full symbol name breakpoint can be implemented with:

  > cat resolver.py
  import lldb
  
  class Resolver:
    def __init__(self, bkpt, extra_args, dict):
        self.bkpt = bkpt
        self.extra_args = extra_args
  
    def __callback__(self, sym_ctx):
        sym_item = self.extra_args.GetValueForKey("symbol")
        if not sym_item.IsValid():
            return
        sym_name = sym_item.GetStringValue(1000)
  
        sym = sym_ctx.module.FindSymbol(sym_name, lldb.eSymbolTypeCode)
        if sym.IsValid():
            self.bkpt.AddLocation(sym.GetStartAddress())
  
    def get_short_help(self):
        return "I am a python breakpoint resolver"
  > lldb a.out
  (lldb) target create "a.out"
  Current executable set to 'a.out' (x86_64).
  (lldb) command script import resolver.py
  (lldb) break set -P resolver.Resolver -k symbol -v break_on_me
  (lldb)  break set -P resolver.Resolver -k symbol -v break_on_me
  Breakpoint 1: where = a.out`break_on_me at main.c:5, address = 0x0000000100000f40
  (lldb) break list
  Current breakpoints:
  1: I am a python breakpoint resolver, locations = 1
    1.1: where = a.out`break_on_me at main.c:5, address = a.out[0x0000000100000f40], unresolved, hit count = 0 

The functionality is advanced enough that this is useful, and I don't expect that will change much.  There are tests for all of this.

There are some future work items:

Docs are forthcoming.

Serialization is not all the way working, but I think it's worth getting the current state of things in before I tackle that.

I also need to invent a way for the __init__ to vet its incoming arguments and return an error - which will abort the breakpoint creation - if they don't have some necessary entries.


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D51830

Files:
  include/lldb/API/SBAddress.h
  include/lldb/API/SBBreakpoint.h
  include/lldb/API/SBStructuredData.h
  include/lldb/API/SBSymbolContext.h
  include/lldb/API/SBTarget.h
  include/lldb/Breakpoint/BreakpointResolver.h
  include/lldb/Breakpoint/BreakpointResolverScripted.h
  include/lldb/Interpreter/ScriptInterpreter.h
  include/lldb/Target/Target.h
  include/lldb/lldb-defines.h
  include/lldb/lldb-enumerations.h
  lldb.xcodeproj/project.pbxproj
  packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile
  packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py
  packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c
  packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py
  packages/Python/lldbsuite/test/lldbutil.py
  scripts/Python/python-swigsafecast.swig
  scripts/Python/python-wrapper.swig
  scripts/interface/SBBreakpoint.i
  scripts/interface/SBStringList.i
  scripts/interface/SBStructuredData.i
  scripts/interface/SBTarget.i
  source/API/SBBreakpoint.cpp
  source/API/SBStructuredData.cpp
  source/API/SBTarget.cpp
  source/API/SystemInitializerFull.cpp
  source/Breakpoint/BreakpointResolver.cpp
  source/Breakpoint/BreakpointResolverScripted.cpp
  source/Commands/CommandObjectBreakpoint.cpp
  source/Core/SearchFilter.cpp
  source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
  source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
  source/Target/Target.cpp





More information about the lldb-commits mailing list