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



_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to