How to Import Lldb in a Python Script

How to import lldb in a python script

Looks like the symlinks that the lldb python package installs are botched. If you look in /usr/lib/llvm-3.6/lib/python2.7/site-packages/lldb you'll see three broken simlinks referencing the nonexistent x86_64-linux-gnu directory. This fixed it for me (tested on Ubuntu 14.04, not Lubuntu but I'm assuming the issue is the same):

cd /usr/lib/llvm-3.6/lib/python2.7/site-packages/lldb
sudo ln -sf ../../../liblldb.so.1 _lldb.so
sudo ln -sf ../../../libLLVM-3.6.0.so.1 libLLVM-3.6.0.so.1
sudo ln -sf ../../../libLLVM-3.6.0.so.1 libLLVM-3.6.so.1
export PYTHONPATH='/usr/lib/llvm-3.6/lib/python2.7/site-packages'
vagrant@Ubuntu:~$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import lldb
>>>

How to import lldb module for python on Mac?

The lldb python module shipped with Xcode builds against a specific version of Python.

Prior to Xcode 11 lldb was built against the Python2.7.1 in /System/Library/Frameworks. Starting with Xcode 11, lldb is built against the version of Python 3 (currently 3.7.3) that ships with the Xcode from which you got your lldb. You can locate the proper python3 command line tool by running xcrun python3.

We haven't had much success getting the lldb module we build against this 3.7.3 Python to load into other hand-built Pythons. I'm not sure that this is particularly well supported by Python, though I don't know of anybody who has looked into what it would take to support this.

We do use a lot of the Python C API's in the lldb bindings, so we are more bound to the Python version than pure Python modules. Anyway, at present if you need to load the lldb module into a python you have installed from elsewhere, you will most likely need to hand-build lldb against that python library.

Debugging Python script that runs inside lldb

You can use Python's pdb module to insert tracepoints in your test.py and lldb will stop in the pdb shell and allow you to step through the code. E.g.:

 > lldb
(lldb) platform shell cat /tmp/test.py
print("About to break")
import pdb
pdb.set_trace()
print("Back from break.")
(lldb) command script impo /tmp/test.py
About to break
> /tmp/test.py(4)<module>()
-> print("Back from break.")
(Pdb) n
Back from break.
--Return--
> /tmp/test.py(4)<module>()->None
-> print("Back from break.")
(Pdb) c
(lldb)

LLDB Python scripting in Xcode

Between Xcode, lldb, and the Python interpreter there are some problems with the interactive console, unfortunately. Please do file a bug report at http://bugreport.apple.com/ - I don't know if there is a bug report about this specific issue already, although problems in general here are known. You may want to use the command line lldb tool if you're exploring the interactive python scripting interface; that works better.

I put all my python scripts for lldb in ~/lldb. In my ~/.lldbinit file I source them in. For instance, I have ~/lldb/stopifcaller.py which is

import lldb

# Use this like
# (lldb) command script import ~/lldb/stopifcaller.py
# (lldb) br s -n bar
# (lldb) br comm add --script-type python -o "stopifcaller.stop_if_caller(frame, 'foo')" 1

def stop_if_caller(current_frame, function_of_interest):
thread = current_frame.GetThread()
if thread.GetNumFrames() > 1:
if thread.GetFrameAtIndex(1).GetFunctionName() != function_of_interest:
thread.GetProcess().Continue()

I would put the command script import in my ~/.lldbinit file to load it automatically, if that's what I wanted. This particular example adds a python command to breakpoint #1 -- when lldb stops at the breakpoint, it will look at the calling function. If the calling function is not foo, it will automatically resume execution. In essence, breakpoint 1 will only stop if foo() calls bar(). Note that there may be a problem with Xcode 4.5 lldb in doing command script import ~/... -- you may need to type out the full path to your home directory (/Users/benwad/ or whatever). I can't remember for sure - there were a few tilde-expansion problems with Xcode 4.5 that have been fixed for a while.

You can add simple type summaries to your ~/.lldbinit directly. For instance, if I'm debugging lldb itself, ConstString objects have only one field of interest to me normally, the m_string ivar. So I have

type summary add -w lldb lldb_private::ConstString -s "${var.m_string}"

Or if it's the type addr_t, I always want that formatted as hex so I have

type format add -f x lldb::addr_t

If you want to add a new command to lldb, you would have a python file like ~/lldb/sayhello.py,

import lldb

def say_hello(debugger, command, result, dict):
print 'hello'

def __lldb_init_module (debugger, dict):
debugger.HandleCommand('command script add -f sayhello.say_hello hello')

and you would load it in to lldb like

(lldb) comma script import  ~/lldb/sayhello.py
(lldb) hello
hello
(lldb)

Most of the time when you're adding a command written in python you'll use the shlex and optparse libraries so the command can do option parsing, and you'll add a __doc__ string - I omitted those things to keep the example simple.

Can't run python scripts in lldb

You need to have python-lldb installed for this to work. sudo dnf install python-lldb should do it.

How to write an lldb script to launch the process to be debugged

This is lldb's SIGINT handler fighting with the Python one while we are running the Python interpreter. lldb will have to do something cleverer to figure out which handler to dispatch to.

Fortunately, there is a workaround which is to make sure your command just starts the target running, then returns command to the lldb command interpreter. The way to do that is to make sure the debugger is running execution control commands in "Asynchronous mode" for the run command. You don't want to permanently so do something like:

def runcmd(debugger, command, result, internal_dict):
old_val = debugger.GetAsync()
debugger.SetAsync(True)
debugger.HandleCommand("run")
debugger.SetAsync(old_val)


Related Topics



Leave a reply



Submit