Added the first of hopefully many python example scripts that show how to

use the python API that is exposed through SWIG to do some cool stuff.

Also fixed synchronous debugging so that all process control APIs exposed
through the python API will now wait for the process to stop if you set
the async mode to false (see disasm.py).

llvm-svn: 115738
This commit is contained in:
Greg Clayton 2010-10-06 03:53:16 +00:00
parent 964f521e85
commit 5d5028b54e
5 changed files with 179 additions and 55 deletions

79
lldb/examples/python/disasm.py Executable file
View File

@ -0,0 +1,79 @@
#!/usr/bin/python
#----------------------------------------------------------------------
# Be sure to add the python path that points to the LLDB shared library.
# On MacOSX csh, tcsh:
# setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python
# On MacOSX sh, bash:
# export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python
#----------------------------------------------------------------------
import lldb
import os
import sys
import time
def disassemble_instructions (insts):
for i in range(0, insts.GetSize()):
print insts.GetInstructionAtIndex(i)
# Initialize LLDB so we can use it
lldb.SBDebugger.Initialize()
# Create a new debugger instance
debugger = lldb.SBDebugger.Create()
# When we step or continue, don't return from the function until the process
# stops. We do this by setting the async mode to false.
debugger.SetAsync (False)
# Create a target from a file and arch
target = debugger.CreateTargetWithFileAndArch (sys.argv[1], "x86_64")
if target.IsValid():
# If the target is valid set a breakpoint at main
main_bp = target.BreakpointCreateByName ("main", "a.out");
# Launch the process. Since we specified synchronous mode, we won't return
# from this function until we hit the breakpoint at main
process = target.LaunchProcess (sys.argv[2:], [''], "dev/stdout", 0, False)
# Make sure the launch went ok
if process.IsValid():
# Print some simple process info
print "process:", process, "\n"
# Get the first thread
thread = process.GetThreadAtIndex (0)
if thread.IsValid():
# Print some simple thread info
print "thread: ", thread
# Get the first frame
frame = thread.GetFrameAtIndex (0)
if frame.IsValid():
# Print some simple frame info
print "frame: ", frame
function = frame.GetFunction()
# See if we have debug info (a function)
if function.IsValid():
# We do have a function, print some info for the function
print "function: ", function, "\n"
# Now get all instructions for this function and print them
insts = function.GetInstructions(target)
disassemble_instructions (insts)
else:
# See if we have a symbol in the symbol table for where we stopped
symbol = frame.GetSymbol();
if symbol.IsValid():
# We do have a symbol, print some info for the symbol
print "symbol: ", symbol, "\n"
# Now get all instructions for this symbol and print them
insts = symbol.GetInstructions(target)
disassemble_instructions (insts)
# Now continue to the program exit
process.Continue()
# When we return from the above function we will hopefully be at the
# program exit. Print out some process info
print "process:", process, "\n"
lldb.SBDebugger.Terminate()

View File

@ -52,9 +52,6 @@ public:
lldb::SBProcess
GetProcess ();
lldb::SBProcess
CreateProcess ();
lldb::SBProcess
LaunchProcess (char const **argv,
char const **envp,

View File

@ -15,6 +15,7 @@
#include "lldb/Interpreter/Args.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
@ -287,7 +288,15 @@ SBProcess::Continue ()
{
SBError sb_error;
if (IsValid())
sb_error.SetError(m_opaque_sp->Resume());
{
Error error (m_opaque_sp->Resume());
if (error.Success())
{
if (m_opaque_sp->GetTarget().GetDebugger().GetAsyncExecution () == false)
m_opaque_sp->WaitForProcessToStop (NULL);
}
sb_error.SetError(error);
}
else
sb_error.SetErrorString ("SBProcess is invalid");

View File

@ -105,17 +105,6 @@ SBTarget::GetDebugger () const
return debugger;
}
SBProcess
SBTarget::CreateProcess ()
{
SBProcess sb_process;
if (m_opaque_sp)
sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener()));
return sb_process;
}
SBProcess
SBTarget::LaunchProcess
(
@ -126,23 +115,39 @@ SBTarget::LaunchProcess
bool stop_at_entry
)
{
SBProcess process(GetProcess ());
if (!process.IsValid())
process = CreateProcess();
if (process.IsValid())
SBProcess sb_process;
if (m_opaque_sp)
{
Error error (process->Launch (argv, envp, launch_flags, tty, tty, tty));
if (error.Success())
// When launching, we always want to create a new process
sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener()));
if (sb_process.IsValid())
{
if (!stop_at_entry)
Error error (sb_process->Launch (argv, envp, launch_flags, tty, tty, tty));
if (error.Success())
{
StateType state = process->WaitForProcessToStop (NULL);
// We we are stopping at the entry point, we can return now!
if (stop_at_entry)
return sb_process;
// Make sure we are stopped at the entry
StateType state = sb_process->WaitForProcessToStop (NULL);
if (state == eStateStopped)
process->Resume();
{
// resume the process to skip the entry point
error = sb_process->Resume();
if (error.Success())
{
// If we are doing synchronous mode, then wait for the
// process to stop yet again!
if (m_opaque_sp->GetDebugger().GetAsyncExecution () == false)
sb_process->WaitForProcessToStop (NULL);
}
}
}
}
}
return process;
return sb_process;
}
SBFileSpec
@ -401,9 +406,9 @@ SBTarget::Disassemble (lldb::addr_t start_addr, lldb::addr_t end_addr, const cha
// Make sure the process object is alive if we have one (it might be
// created but we might not be launched yet).
Process *process = m_opaque_sp->GetProcessSP().get();
if (process && !process->IsAlive())
process = NULL;
Process *sb_process = m_opaque_sp->GetProcessSP().get();
if (sb_process && !sb_process->IsAlive())
sb_process = NULL;
// If we are given a module, then "start_addr" is a file address in
// that module.
@ -430,8 +435,8 @@ SBTarget::Disassemble (lldb::addr_t start_addr, lldb::addr_t end_addr, const cha
ExecutionContext exe_ctx;
if (process)
process->CalculateExecutionContext(exe_ctx);
if (sb_process)
sb_process->CalculateExecutionContext(exe_ctx);
else
m_opaque_sp->CalculateExecutionContext(exe_ctx);
@ -479,12 +484,12 @@ SBTarget::Disassemble (const char *function_name, const char *module_name)
// Make sure the process object is alive if we have one (it might be
// created but we might not be launched yet).
Process *process = m_opaque_sp->GetProcessSP().get();
if (process && !process->IsAlive())
process = NULL;
Process *sb_process = m_opaque_sp->GetProcessSP().get();
if (sb_process && !sb_process->IsAlive())
sb_process = NULL;
if (process)
process->CalculateExecutionContext(exe_ctx);
if (sb_process)
sb_process->CalculateExecutionContext(exe_ctx);
else
m_opaque_sp->CalculateExecutionContext(exe_ctx);

View File

@ -233,25 +233,32 @@ SBThread::StepOver (lldb::RunMode stop_other_threads)
{
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans,
eStepTypeOver,
sc.line_entry.range,
sc,
stop_other_threads,
false);
eStepTypeOver,
sc.line_entry.range,
sc,
stop_other_threads,
false);
}
else
{
m_opaque_sp->QueueThreadPlanForStepSingleInstruction (true,
abort_other_plans,
stop_other_threads);
abort_other_plans,
stop_other_threads);
}
}
Process &process = m_opaque_sp->GetProcess();
// Why do we need to set the current thread by ID here???
process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
process.Resume();
Error error (process.Resume());
if (error.Success())
{
// If we are doing synchronous mode, then wait for the
// process to stop yet again!
if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
process.WaitForProcessToStop (NULL);
}
}
}
@ -269,24 +276,30 @@ SBThread::StepInto (lldb::RunMode stop_other_threads)
bool avoid_code_without_debug_info = true;
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans,
eStepTypeInto,
sc.line_entry.range,
sc,
stop_other_threads,
avoid_code_without_debug_info);
eStepTypeInto,
sc.line_entry.range,
sc,
stop_other_threads,
avoid_code_without_debug_info);
}
else
{
m_opaque_sp->QueueThreadPlanForStepSingleInstruction (false,
abort_other_plans,
stop_other_threads);
abort_other_plans,
stop_other_threads);
}
Process &process = m_opaque_sp->GetProcess();
// Why do we need to set the current thread by ID here???
process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
process.Resume();
Error error (process.Resume());
if (error.Success())
{
// If we are doing synchronous mode, then wait for the
// process to stop yet again!
if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
process.WaitForProcessToStop (NULL);
}
}
}
@ -302,7 +315,14 @@ SBThread::StepOut ()
Process &process = m_opaque_sp->GetProcess();
process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
process.Resume();
Error error (process.Resume());
if (error.Success())
{
// If we are doing synchronous mode, then wait for the
// process to stop yet again!
if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
process.WaitForProcessToStop (NULL);
}
}
}
@ -314,7 +334,14 @@ SBThread::StepInstruction (bool step_over)
m_opaque_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true);
Process &process = m_opaque_sp->GetProcess();
process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
process.Resume();
Error error (process.Resume());
if (error.Success())
{
// If we are doing synchronous mode, then wait for the
// process to stop yet again!
if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
process.WaitForProcessToStop (NULL);
}
}
}
@ -331,7 +358,14 @@ SBThread::RunToAddress (lldb::addr_t addr)
m_opaque_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads);
Process &process = m_opaque_sp->GetProcess();
process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
process.Resume();
Error error (process.Resume());
if (error.Success())
{
// If we are doing synchronous mode, then wait for the
// process to stop yet again!
if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
process.WaitForProcessToStop (NULL);
}
}
}