Call python script on stop?

I’m working on a simple python gui proof-of-concept. I’m going to use the Tkinter module to open a Tk window that displays registers. I’d like to have it auto-update when the target stops.

Is there a way to automatically call a python script when a target stops, and to call another (to clean up) when the target is killed?

Why not just consume the events yourself?

See the following sample python code:

svn cat http://llvm.org/svn/llvm-project/lldb/trunk/examples/python/process_events.py

There is a "target stop-hook" command you could use:

(lldb) help target stop-hook

But I would suggest consuming the events on another thread from python, or just making a polling loop where you want for events for a specified amount of time.

Greg

Yes, you definitely want to handle events yourself. The target stop hooks are fine for printing some variables and threads, etc, but I wouldn't try to update your GUI, etc, from there.

Jim

Is there a way to launch another lldb thread, so I have the command prompt and a python script running at the same time?

You will need to launch another python thread, and in that thread, handle all events just like the process_events.py script.

Can I do that from inside lldb, or are we talking another python process? If inside lldb, how do I do that?

You would use two python threads.

Info on python threads:

http://www.tutorialspoint.com/python/python_multithreading.htm

You would make one thread run your command prompt code, and one thread just consuming events. You would make a function in python:

def lldb_event_thread():
    ....

And the code inside lldb_event_thread would be consuming the events (copy code from process_events.py).

You actually might want 3 thread:
1 - main thread that waits for anything from the two other threads
2 - command prompt thread
3 - event thread

I think I know what you mean - use the python threads module to start a new thread, and run my TK stuff in there. Write an event loop that TK and LLDB events.

If I use SBListener.WaitForEvent(), will that keep the main lldb thread from seeing events that I see?

Let me back up a little - I'm running this from lldb, not python. Ultimately I want to have lldb run from eclipse, connected to a gdb server, but use python to pop up TK windows so we can enhance the gui without having to write eclipse java code.

I've got my script creating the TK window, and I can populate the window by reading registers. Then I moved the window code to another thread, but now I can't read registers. I'm connected to the gdb server, and can read registers from the command line. I pass the debugger in to my handler code in the other thread, and lldb crashes when I try to access it. If I create a new debugger instead, I get "error: invalid frame".

How do I start up a new thread, but access the debugger on the main thread, which is attached to the remote gdb server?

Let me back up a little - I'm running this from lldb, not python.

Ah, gotcha.

Ultimately I want to have lldb run from eclipse, connected to a gdb server, but use python to pop up TK windows so we can enhance the gui without having to write eclipse java code.

Got it.

I've got my script creating the TK window, and I can populate the window by reading registers. Then I moved the window code to another thread, but now I can't read registers.

Many windowing frameworks require UI updates happen on a specific thread. I am not sure if you are running into such a problem here. There should be nothing stopping you from being able to read registers from another thread. You will need to make sure your target is stopped (otherwise the register read will fail saying the process is running).

I'm connected to the gdb server, and can read registers from the command line. I pass the debugger in to my handler code in the other thread, and lldb crashes when I try to access it.

That shouldn't happen if you have a valid debugger handle.

If I create a new debugger instead, I get "error: invalid frame".

Each debugger has a target list:

debugger
   target = 0x11110000
   target = 0x22220000

Each target may or may not have a process

debugger
   target = 0x11110000
       process = 0x12340000
   target = 0x22220000
       process = 0x00000000

Then each process, if valid might have one or more threads and one or more frames within each thread:

debugger
   target = 0x11110000
       process = 0x12340000
            thread 1 = 0x12310000
            thread 2 = 0x12310000
                frame[0] = 0x123092302
                frame[1] = 0x223092302
   target = 0x22220000
       process = 0x00000000

So there is no reason to create a new debugger, it won't contain anything. You need to access the current debugger. If you are running through the embedded python interpreter, you can just use "lldb.debugger". That will always be correct for your current session.

How do I start up a new thread, but access the debugger on the main thread, which is attached to the remote gdb server?

All LLDB code is multi-theaded so you should be able to read registers on any thread. You need to make sure you have good instances:

(lldb) script print lldb.debugger
Debugger (instance: "debugger_1", id: 1)

When you print the debugger, you get valid text. You should also validate that you have valid target, process, thread, and frame objects before you use them.

Maybe you can post the code that is using the debugger to get the current target, and how you are getting the thread and frame that you are getting registers from?

Greg

I think I found the problem. I'm running on Windows. :slight_smile:

OK, the real problem:
(lldb) script print lldb.debugger
No value

I tried passing the debugger as a variable, but that crashes on both Windows and Linux.

My code looks like:

def __lldb_init_module(debugger, dict):
  debugger.HandleCommand('command script add -f vregwin.vrs vrs')

def vrs(debugger, command, result, dict):
  foo = thread.start_new_thread(vregwin, (debugger,))

def vregwin(debugger):
  result = lldb.SBCommandReturnObject()
  debugger.GetCommandInterpreter().HandleCommand('help gdb-remote', result)
  print result.GetOutput()
  print result.GetError()

A "print debugger" in there gives:
Debugger (instance: "HÄ]ÃåHì@", id: 140736691407232)

So I need to use lldb.debugger, which doesn't work on Windows. I guess I'll switch to Linux.

Ted

lldb.debugger should work on Windows, but python still has some kinks to work out on Windows, definitely. For starters, “script print” doesn’t work on Windows. I know how to fix it, but I’m just not there yet and it’s a large fix.

Any chance you want to just try fixing this python stuff on Windows instead? :slight_smile:

I think it’s more than just “script print”:

Windows:

result = lldb.SBCommandReturnObject()

lldb.debugger.GetCommandInterpreter().HandleCommand(‘help gdb-remote’, result)

6

result.GetOutput()

‘’

result.GetError()

‘error: SBCommandInterpreter or the command line is not valid\n’

Linux:

result = lldb.SBCommandReturnObject()

lldb.debugger.GetCommandInterpreter().HandleCommand(‘help gdb-remote’, result)

1

result.GetOutput()

" Connect to a remote GDB server. If no hostname is provided, localhost is\n assumed. This command takes ‘raw’ input (no need to quote stuff).\n\nSyntax: gdb-remote [:]\n"

If I create a command, I can use the passed in debugger to run HandleCommand() on Windows, but can’t do it using lldb.debugger, interactively or in a script.