720 changes: 499 additions & 221 deletions lldb/examples/darwin/heap_find/heap.py

Large diffs are not rendered by default.

1,470 changes: 655 additions & 815 deletions lldb/examples/darwin/heap_find/heap/heap_find.cpp

Large diffs are not rendered by default.

584 changes: 283 additions & 301 deletions lldb/examples/functions/main.cpp

Large diffs are not rendered by default.

1,533 changes: 683 additions & 850 deletions lldb/examples/interposing/darwin/fd_interposing/FDInterposing.cpp

Large diffs are not rendered by default.

343 changes: 165 additions & 178 deletions lldb/examples/lookup/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
#include "LLDB/SBDebugger.h"
#include "LLDB/SBFunction.h"
#include "LLDB/SBModule.h"
#include "LLDB/SBProcess.h"
#include "LLDB/SBStream.h"
#include "LLDB/SBSymbol.h"
#include "LLDB/SBTarget.h"
#include "LLDB/SBThread.h"
#include "LLDB/SBProcess.h"
#endif

#include <string>
Expand All @@ -34,8 +34,8 @@ using namespace lldb;
// This quick sample code shows how to create a debugger instance and
// create an "i386" executable target. Then we can lookup the executable
// module and resolve a file address into a section offset address,
// and find all symbol context objects (if any) for that address:
// compile unit, function, deepest block, line table entry and the
// and find all symbol context objects (if any) for that address:
// compile unit, function, deepest block, line table entry and the
// symbol.
//
// To build the program, type (while in this directory):
Expand All @@ -44,192 +44,179 @@ using namespace lldb;
//
// then (for example):
//
// $ DYLD_FRAMEWORK_PATH=/Volumes/data/lldb/svn/ToT/build/Debug ./a.out executable_path file_address
// $ DYLD_FRAMEWORK_PATH=/Volumes/data/lldb/svn/ToT/build/Debug ./a.out
// executable_path file_address
//----------------------------------------------------------------------
class LLDBSentry
{
class LLDBSentry {
public:
LLDBSentry() {
// Initialize LLDB
SBDebugger::Initialize();
}
~LLDBSentry() {
// Terminate LLDB
SBDebugger::Terminate();
}
LLDBSentry() {
// Initialize LLDB
SBDebugger::Initialize();
}
~LLDBSentry() {
// Terminate LLDB
SBDebugger::Terminate();
}
};

static struct option g_long_options[] =
{
{ "help", no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'v' },
{ "arch", required_argument, NULL, 'a' },
{ "platform", required_argument, NULL, 'p' },
{ NULL, 0, NULL, 0 }
};
static struct option g_long_options[] = {
{"help", no_argument, NULL, 'h'},
{"verbose", no_argument, NULL, 'v'},
{"arch", required_argument, NULL, 'a'},
{"platform", required_argument, NULL, 'p'},
{NULL, 0, NULL, 0}};

#define PROGRAM_NAME "lldb-lookup"
void
usage ()
{
puts (
"NAME\n"
" " PROGRAM_NAME " -- symbolicate addresses using lldb.\n"
"\n"
"SYNOPSIS\n"
" " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] [--verbose] [--help] --] <PATH> <ADDRESS> [<ADDRESS>....]\n"
"\n"
"DESCRIPTION\n"
" Loads the executable pointed to by <PATH> and looks up and <ADDRESS>\n"
" arguments\n"
"\n"
"EXAMPLE\n"
" " PROGRAM_NAME " --arch=x86_64 -- /usr/lib/dyld 0x100000000\n"
);
exit(0);
void usage() {
puts("NAME\n"
" " PROGRAM_NAME " -- symbolicate addresses using lldb.\n"
"\n"
"SYNOPSIS\n"
" " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] "
"[--verbose] [--help] --] <PATH> <ADDRESS> "
"[<ADDRESS>....]\n"
"\n"
"DESCRIPTION\n"
" Loads the executable pointed to by <PATH> and looks up and "
"<ADDRESS>\n"
" arguments\n"
"\n"
"EXAMPLE\n"
" " PROGRAM_NAME " --arch=x86_64 -- /usr/lib/dyld 0x100000000\n");
exit(0);
}
int
main (int argc, char const *argv[])
{
// Use a sentry object to properly initialize/terminate LLDB.
LLDBSentry sentry;

SBDebugger debugger (SBDebugger::Create());

// Create a debugger instance so we can create a target
if (!debugger.IsValid())
fprintf (stderr, "error: failed to create a debugger object\n");

bool show_usage = false;
bool verbose = false;
const char *arch = NULL;
const char *platform = NULL;
std::string short_options("h?");
for (const struct option *opt = g_long_options; opt->name; ++opt)
{
if (isprint(opt->val))
{
short_options.append(1, (char)opt->val);
switch (opt->has_arg)
{
case no_argument:
break;
case required_argument:
short_options.append(1, ':');
break;
case optional_argument:
short_options.append(2, ':');
break;
}
}
int main(int argc, char const *argv[]) {
// Use a sentry object to properly initialize/terminate LLDB.
LLDBSentry sentry;

SBDebugger debugger(SBDebugger::Create());

// Create a debugger instance so we can create a target
if (!debugger.IsValid())
fprintf(stderr, "error: failed to create a debugger object\n");

bool show_usage = false;
bool verbose = false;
const char *arch = NULL;
const char *platform = NULL;
std::string short_options("h?");
for (const struct option *opt = g_long_options; opt->name; ++opt) {
if (isprint(opt->val)) {
short_options.append(1, (char)opt->val);
switch (opt->has_arg) {
case no_argument:
break;
case required_argument:
short_options.append(1, ':');
break;
case optional_argument:
short_options.append(2, ':');
break;
}
}
}
#ifdef __GLIBC__
optind = 0;
optind = 0;
#else
optreset = 1;
optind = 1;
optreset = 1;
optind = 1;
#endif
char ch;
while ((ch = getopt_long_only(argc, (char * const *)argv, short_options.c_str(), g_long_options, 0)) != -1)
{
switch (ch)
{
case 0:
break;

case 'a':
if (arch != NULL)
{
fprintf (stderr, "error: the --arch option can only be specified once\n");
exit(1);
}
arch = optarg;
break;

case 'p':
platform = optarg;
break;

case 'v':
verbose = true;
break;

case 'h':
case '?':
default:
show_usage = true;
break;
}
}
argc -= optind;
argv += optind;

if (show_usage || argc < 2)
usage();

int arg_idx = 0;
// The first argument is the file path we want to look something up in
const char *exe_file_path = argv[arg_idx];
const char *addr_cstr;
const bool add_dependent_libs = false;
SBError error;
SBStream strm;
strm.RedirectToFileHandle (stdout, false);

while ((addr_cstr = argv[++arg_idx]) != NULL)
{
// The second argument in the address that we want to lookup
lldb::addr_t file_addr = strtoull (addr_cstr, NULL, 0);

// Create a target using the executable.
SBTarget target = debugger.CreateTarget (exe_file_path,
arch,
platform,
add_dependent_libs,
error);
if (!error.Success())
{
fprintf (stderr, "error: %s\n", error.GetCString());
exit(1);
}

printf ("%sLooking up 0x%llx in '%s':\n", (arg_idx > 1) ? "\n" : "", file_addr, exe_file_path);

if (target.IsValid())
{
// Find the executable module so we can do a lookup inside it
SBFileSpec exe_file_spec (exe_file_path, true);
SBModule module (target.FindModule (exe_file_spec));

// Take a file virtual address and resolve it to a section offset
// address that can be used to do a symbol lookup by address
SBAddress addr = module.ResolveFileAddress (file_addr);
bool success = addr.IsValid() && addr.GetSection().IsValid();
if (success)
{
// We can resolve a section offset address in the module
// and only ask for what we need. You can logical or together
// bits from the SymbolContextItem enumeration found in
// lldb-enumeration.h to request only what you want. Here we
// are asking for everything.
//
// NOTE: the less you ask for, the less LLDB will parse as
// LLDB does partial parsing on just about everything.
SBSymbolContext sc (module.ResolveSymbolContextForAddress (addr, eSymbolContextEverything));

strm.Printf (" Address: %s + 0x%llx\n Summary: ", addr.GetSection().GetName (), addr.GetOffset());
addr.GetDescription (strm);
strm.Printf ("\n");
if (verbose)
sc.GetDescription (strm);
}
else
{
printf ("error: 0x%llx does not resolve to a valid file address in '%s'\n", file_addr, exe_file_path);
}
}
char ch;
while ((ch = getopt_long_only(argc, (char *const *)argv,
short_options.c_str(), g_long_options, 0)) !=
-1) {
switch (ch) {
case 0:
break;

case 'a':
if (arch != NULL) {
fprintf(stderr,
"error: the --arch option can only be specified once\n");
exit(1);
}
arch = optarg;
break;

case 'p':
platform = optarg;
break;

case 'v':
verbose = true;
break;

case 'h':
case '?':
default:
show_usage = true;
break;
}
}
argc -= optind;
argv += optind;

if (show_usage || argc < 2)
usage();

int arg_idx = 0;
// The first argument is the file path we want to look something up in
const char *exe_file_path = argv[arg_idx];
const char *addr_cstr;
const bool add_dependent_libs = false;
SBError error;
SBStream strm;
strm.RedirectToFileHandle(stdout, false);

while ((addr_cstr = argv[++arg_idx]) != NULL) {
// The second argument in the address that we want to lookup
lldb::addr_t file_addr = strtoull(addr_cstr, NULL, 0);

// Create a target using the executable.
SBTarget target = debugger.CreateTarget(exe_file_path, arch, platform,
add_dependent_libs, error);
if (!error.Success()) {
fprintf(stderr, "error: %s\n", error.GetCString());
exit(1);
}

return 0;
}
printf("%sLooking up 0x%llx in '%s':\n", (arg_idx > 1) ? "\n" : "",
file_addr, exe_file_path);

if (target.IsValid()) {
// Find the executable module so we can do a lookup inside it
SBFileSpec exe_file_spec(exe_file_path, true);
SBModule module(target.FindModule(exe_file_spec));

// Take a file virtual address and resolve it to a section offset
// address that can be used to do a symbol lookup by address
SBAddress addr = module.ResolveFileAddress(file_addr);
bool success = addr.IsValid() && addr.GetSection().IsValid();
if (success) {
// We can resolve a section offset address in the module
// and only ask for what we need. You can logical or together
// bits from the SymbolContextItem enumeration found in
// lldb-enumeration.h to request only what you want. Here we
// are asking for everything.
//
// NOTE: the less you ask for, the less LLDB will parse as
// LLDB does partial parsing on just about everything.
SBSymbolContext sc(module.ResolveSymbolContextForAddress(
addr, eSymbolContextEverything));

strm.Printf(" Address: %s + 0x%llx\n Summary: ",
addr.GetSection().GetName(), addr.GetOffset());
addr.GetDescription(strm);
strm.Printf("\n");
if (verbose)
sc.GetDescription(strm);
} else {
printf(
"error: 0x%llx does not resolve to a valid file address in '%s'\n",
file_addr, exe_file_path);
}
}
}

return 0;
}
53 changes: 22 additions & 31 deletions lldb/examples/plugins/commands/fooplugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
//===----------------------------------------------------------------------===//

/*
An example plugin for LLDB that provides a new foo command with a child subcommand
Compile this into a dylib foo.dylib and load by placing in appropriate locations on disk or
An example plugin for LLDB that provides a new foo command with a child
subcommand
Compile this into a dylib foo.dylib and load by placing in appropriate locations
on disk or
by typing plugin load foo.dylib at the LLDB command line
*/

Expand All @@ -18,39 +20,28 @@ by typing plugin load foo.dylib at the LLDB command line
#include <LLDB/SBDebugger.h>

namespace lldb {
bool
PluginInitialize (lldb::SBDebugger debugger);
bool PluginInitialize(lldb::SBDebugger debugger);
}

class ChildCommand : public lldb::SBCommandPluginInterface
{
class ChildCommand : public lldb::SBCommandPluginInterface {
public:
virtual bool
DoExecute (lldb::SBDebugger debugger,
char** command,
lldb::SBCommandReturnObject &result)
{
if (command)
{
const char* arg = *command;
while (arg)
{
result.Printf("%s\n",arg);
arg = *(++command);
}
return true;
}
return false;
virtual bool DoExecute(lldb::SBDebugger debugger, char **command,
lldb::SBCommandReturnObject &result) {
if (command) {
const char *arg = *command;
while (arg) {
result.Printf("%s\n", arg);
arg = *(++command);
}
return true;
}

return false;
}
};

bool
lldb::PluginInitialize (lldb::SBDebugger debugger)
{
lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
lldb::SBCommand foo = interpreter.AddMultiwordCommand("foo",NULL);
foo.AddCommand("child",new ChildCommand(),"a child of foo");
return true;
bool lldb::PluginInitialize(lldb::SBDebugger debugger) {
lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
lldb::SBCommand foo = interpreter.AddMultiwordCommand("foo", NULL);
foo.AddCommand("child", new ChildCommand(), "a child of foo");
return true;
}

70 changes: 53 additions & 17 deletions lldb/examples/python/cmdtemplate.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Be sure to add the python path that points to the LLDB shared library.
#
# # To use this in the embedded python interpreter using "lldb" just
# import it with the full path using the "command script import"
# import it with the full path using the "command script import"
# command
# (lldb) command script import /path/to/cmdtemplate.py
#----------------------------------------------------------------------
Expand All @@ -14,22 +14,51 @@
import optparse
import shlex


def create_framestats_options():
usage = "usage: %prog [options]"
description='''This command is meant to be an example of how to make an LLDB command that
description = '''This command is meant to be an example of how to make an LLDB command that
does something useful, follows best practices, and exploits the SB API.
Specifically, this command computes the aggregate and average size of the variables in the current frame
and allows you to tweak exactly which variables are to be accounted in the computation.
'''
parser = optparse.OptionParser(description=description, prog='framestats',usage=usage)
parser.add_option('-i', '--in-scope', action='store_true', dest='inscope', help='in_scope_only = True', default=False)
parser.add_option('-a', '--arguments', action='store_true', dest='arguments', help='arguments = True', default=False)
parser.add_option('-l', '--locals', action='store_true', dest='locals', help='locals = True', default=False)
parser.add_option('-s', '--statics', action='store_true', dest='statics', help='statics = True', default=False)
parser = optparse.OptionParser(
description=description,
prog='framestats',
usage=usage)
parser.add_option(
'-i',
'--in-scope',
action='store_true',
dest='inscope',
help='in_scope_only = True',
default=False)
parser.add_option(
'-a',
'--arguments',
action='store_true',
dest='arguments',
help='arguments = True',
default=False)
parser.add_option(
'-l',
'--locals',
action='store_true',
dest='locals',
help='locals = True',
default=False)
parser.add_option(
'-s',
'--statics',
action='store_true',
dest='statics',
help='statics = True',
default=False)
return parser


def the_framestats_command(debugger, command, result, dict):
# Use the Shell Lexer to properly parse up command options just like a
# Use the Shell Lexer to properly parse up command options just like a
# shell would
command_args = shlex.split(command)
parser = create_framestats_options()
Expand All @@ -38,9 +67,9 @@ def the_framestats_command(debugger, command, result, dict):
except:
# if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit
# (courtesy of OptParse dealing with argument errors by throwing SystemExit)
result.SetError ("option parsing failed")
result.SetError("option parsing failed")
return

# in a command - the lldb.* convenience variables are not to be used
# and their values (if any) are undefined
# this is the best practice to access those objects from within a command
Expand All @@ -51,26 +80,33 @@ def the_framestats_command(debugger, command, result, dict):
if not frame.IsValid():
return "no frame here"
# from now on, replace lldb.<thing>.whatever with <thing>.whatever
variables_list = frame.GetVariables(options.arguments, options.locals, options.statics, options.inscope)
variables_list = frame.GetVariables(
options.arguments,
options.locals,
options.statics,
options.inscope)
variables_count = variables_list.GetSize()
if variables_count == 0:
print >> result, "no variables here"
return
total_size = 0
for i in range(0,variables_count):
for i in range(0, variables_count):
variable = variables_list.GetValueAtIndex(i)
variable_type = variable.GetType()
total_size = total_size + variable_type.GetByteSize()
average_size = float(total_size) / variables_count
print >>result, "Your frame has %d variables. Their total size is %d bytes. The average size is %f bytes" % (variables_count,total_size,average_size)
print >>result, "Your frame has %d variables. Their total size is %d bytes. The average size is %f bytes" % (
variables_count, total_size, average_size)
# not returning anything is akin to returning success

def __lldb_init_module (debugger, dict):
# This initializer is being run from LLDB in the embedded command interpreter
# Make the options so we can generate the help text for the new LLDB

def __lldb_init_module(debugger, dict):
# This initializer is being run from LLDB in the embedded command interpreter
# Make the options so we can generate the help text for the new LLDB
# command line command prior to registering it with LLDB below
parser = create_framestats_options()
the_framestats_command.__doc__ = parser.format_help()
# Add any commands contained in this module to LLDB
debugger.HandleCommand('command script add -f cmdtemplate.the_framestats_command framestats')
debugger.HandleCommand(
'command script add -f cmdtemplate.the_framestats_command framestats')
print 'The "framestats" command has been installed, type "help framestats" or "framestats --help" for detailed help.'
579 changes: 375 additions & 204 deletions lldb/examples/python/crashlog.py

Large diffs are not rendered by default.

67 changes: 43 additions & 24 deletions lldb/examples/python/delta.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#!/usr/bin/python

#----------------------------------------------------------------------
# This module will enable GDB remote packet logging when the
# This module will enable GDB remote packet logging when the
# 'start_gdb_log' command is called with a filename to log to. When the
# 'stop_gdb_log' command is called, it will disable the logging and
# 'stop_gdb_log' command is called, it will disable the logging and
# print out statistics about how long commands took to execute and also
# will primnt ou
# Be sure to add the python path that points to the LLDB shared library.
#
# To use this in the embedded python interpreter using "lldb" just
# import it with the full path using the "command script import"
# import it with the full path using the "command script import"
# command. This can be done from the LLDB command line:
# (lldb) command script import /path/to/gdbremote.py
# Or it can be added to your ~/.lldbinit file so this module is always
Expand All @@ -23,13 +23,16 @@
import re
import tempfile


def start_gdb_log(debugger, command, result, dict):
'''Start logging GDB remote packets by enabling logging with timestamps and
'''Start logging GDB remote packets by enabling logging with timestamps and
thread safe logging. Follow a call to this function with a call to "stop_gdb_log"
in order to dump out the commands.'''
global log_file
if log_file:
result.PutCString ('error: logging is already in progress with file "%s"', log_file)
result.PutCString(
'error: logging is already in progress with file "%s"',
log_file)
else:
args_len = len(args)
if args_len == 0:
Expand All @@ -38,36 +41,52 @@ def start_gdb_log(debugger, command, result, dict):
log_file = args[0]

if log_file:
debugger.HandleCommand('log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % log_file);
result.PutCString ("GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics." % log_file)
debugger.HandleCommand(
'log enable --threadsafe --timestamp --file "%s" gdb-remote packets' %
log_file)
result.PutCString(
"GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics." %
log_file)
return

result.PutCString ('error: invalid log file path')
result.PutCString (usage)
result.PutCString('error: invalid log file path')
result.PutCString(usage)


def parse_time_log(debugger, command, result, dict):
# Any commands whose names might be followed by more valid C identifier
# Any commands whose names might be followed by more valid C identifier
# characters must be listed here
command_args = shlex.split(command)
parse_time_log_args (command_args)
parse_time_log_args(command_args)


def parse_time_log_args(command_args):
usage = "usage: parse_time_log [options] [<LOGFILEPATH>]"
description='''Parse a log file that contains timestamps and convert the timestamps to delta times between log lines.'''
parser = optparse.OptionParser(description=description, prog='parse_time_log',usage=usage)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
description = '''Parse a log file that contains timestamps and convert the timestamps to delta times between log lines.'''
parser = optparse.OptionParser(
description=description,
prog='parse_time_log',
usage=usage)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
try:
(options, args) = parser.parse_args(command_args)
except:
return
for log_file in args:
parse_log_file (log_file, options)
parse_log_file(log_file, options)


def parse_log_file(file, options):
'''Parse a log file that was contains timestamps. These logs are typically
generated using:
(lldb) log enable --threadsafe --timestamp --file <FILE> ....
This log file will contain timestamps and this function will then normalize
those packets to be relative to the first value timestamp that is found and
show delta times between log lines and also keep track of how long it takes
Expand All @@ -86,9 +105,9 @@ def parse_log_file(file, options):
file = open(file)
lines = file.read().splitlines()
for line in lines:
match = timestamp_regex.match (line)
match = timestamp_regex.match(line)
if match:
curr_time = float (match.group(2))
curr_time = float(match.group(2))
delta = 0.0
if base_time:
delta = curr_time - last_time
Expand All @@ -99,17 +118,17 @@ def parse_log_file(file, options):
last_time = curr_time
else:
print line





if __name__ == '__main__':
import sys
parse_time_log_args (sys.argv[1:])
parse_time_log_args(sys.argv[1:])

else:
import lldb
if lldb.debugger:
if lldb.debugger:
# This initializer is being run from LLDB in the embedded command interpreter
# Add any commands contained in this module to LLDB
lldb.debugger.HandleCommand('command script add -f delta.parse_time_log parse_time_log')
lldb.debugger.HandleCommand(
'command script add -f delta.parse_time_log parse_time_log')
print 'The "parse_time_log" command is now installed and ready for use, type "parse_time_log --help" for more information'
250 changes: 131 additions & 119 deletions lldb/examples/python/diagnose_nsstring.py
Original file line number Diff line number Diff line change
@@ -1,64 +1,67 @@
# This implements the "diagnose-nsstring" command, usually installed in the debug session like
# command script import lldb.diagnose
# it is used when NSString summary formatter fails to replicate the logic that went into LLDB making the
# decisions it did and providing some useful context information that can be used for improving the formatter
# decisions it did and providing some useful context information that can
# be used for improving the formatter

import lldb

def read_memory(process,location,size):
data = ""
error = lldb.SBError()
for x in range(0,size-1):
byte = process.ReadUnsignedFromMemory(x+location,1,error)
if error.fail:
data = data + "err%s" % "" if x == size-2 else ":"
else:
try:
data = data + "0x%x" % byte
if byte == 0:
data = data + "(\\0)"
elif byte == 0xa:
data = data + "(\\a)"
elif byte == 0xb:
data = data + "(\\b)"
elif byte == 0xc:
data = data + "(\\c)"
elif byte == '\n':
data = data + "(\\n)"
else:
data = data + "(%s)" % chr(byte)
if x < size-2:
data = data + ":"
except Exception as e:
print e
return data

def diagnose_nsstring_Command_Impl(debugger,command,result,internal_dict):
"""
A command to diagnose the LLDB NSString data formatter
invoke as
(lldb) diagnose-nsstring <expr returning NSString>
e.g.
(lldb) diagnose-nsstring @"Hello world"
"""
target = debugger.GetSelectedTarget()
process = target.GetProcess()
thread = process.GetSelectedThread()
frame = thread.GetSelectedFrame()
if not target.IsValid() or not process.IsValid():
return "unable to get target/process - cannot proceed"
options = lldb.SBExpressionOptions()
options.SetFetchDynamicValue()
error = lldb.SBError()
if frame.IsValid():
nsstring = frame.EvaluateExpression(command,options)
else:
nsstring = target.EvaluateExpression(command,options)
print >>result,str(nsstring)
nsstring_address = nsstring.GetValueAsUnsigned(0)
if nsstring_address == 0:
return "unable to obtain the string - cannot proceed"
expression = "\
def read_memory(process, location, size):
data = ""
error = lldb.SBError()
for x in range(0, size - 1):
byte = process.ReadUnsignedFromMemory(x + location, 1, error)
if error.fail:
data = data + "err%s" % "" if x == size - 2 else ":"
else:
try:
data = data + "0x%x" % byte
if byte == 0:
data = data + "(\\0)"
elif byte == 0xa:
data = data + "(\\a)"
elif byte == 0xb:
data = data + "(\\b)"
elif byte == 0xc:
data = data + "(\\c)"
elif byte == '\n':
data = data + "(\\n)"
else:
data = data + "(%s)" % chr(byte)
if x < size - 2:
data = data + ":"
except Exception as e:
print e
return data


def diagnose_nsstring_Command_Impl(debugger, command, result, internal_dict):
"""
A command to diagnose the LLDB NSString data formatter
invoke as
(lldb) diagnose-nsstring <expr returning NSString>
e.g.
(lldb) diagnose-nsstring @"Hello world"
"""
target = debugger.GetSelectedTarget()
process = target.GetProcess()
thread = process.GetSelectedThread()
frame = thread.GetSelectedFrame()
if not target.IsValid() or not process.IsValid():
return "unable to get target/process - cannot proceed"
options = lldb.SBExpressionOptions()
options.SetFetchDynamicValue()
error = lldb.SBError()
if frame.IsValid():
nsstring = frame.EvaluateExpression(command, options)
else:
nsstring = target.EvaluateExpression(command, options)
print >>result, str(nsstring)
nsstring_address = nsstring.GetValueAsUnsigned(0)
if nsstring_address == 0:
return "unable to obtain the string - cannot proceed"
expression = "\
struct $__lldb__notInlineMutable {\
char* buffer;\
signed long length;\
Expand Down Expand Up @@ -97,75 +100,84 @@ def diagnose_nsstring_Command_Impl(debugger,command,result,internal_dict):
};\
"

expression = expression + "*(($__lldb__CFString*) %d)" % nsstring_address
# print expression
dumped = target.EvaluateExpression(expression,options)
print >>result, str(dumped)

little_endian = (target.byte_order == lldb.eByteOrderLittle)
ptr_size = target.addr_size

info_bits = dumped.GetChildMemberWithName("_cfinfo").GetChildAtIndex(0 if little_endian else 3).GetValueAsUnsigned(0)
is_mutable = (info_bits & 1) == 1
is_inline = (info_bits & 0x60) == 0
has_explicit_length = (info_bits & (1 | 4)) != 4
is_unicode = (info_bits & 0x10) == 0x10
is_special = (nsstring.GetDynamicValue(lldb.eDynamicCanRunTarget).GetTypeName() == "NSPathStore2")
has_null = (info_bits & 8) == 8

print >>result,"\nInfo=%d\nMutable=%s\nInline=%s\nExplicit=%s\nUnicode=%s\nSpecial=%s\nNull=%s\n" % \
(info_bits, "yes" if is_mutable else "no","yes" if is_inline else "no","yes" if has_explicit_length else "no","yes" if is_unicode else "no","yes" if is_special else "no","yes" if has_null else "no")
expression = expression + "*(($__lldb__CFString*) %d)" % nsstring_address
# print expression
dumped = target.EvaluateExpression(expression, options)
print >>result, str(dumped)

little_endian = (target.byte_order == lldb.eByteOrderLittle)
ptr_size = target.addr_size

info_bits = dumped.GetChildMemberWithName("_cfinfo").GetChildAtIndex(
0 if little_endian else 3).GetValueAsUnsigned(0)
is_mutable = (info_bits & 1) == 1
is_inline = (info_bits & 0x60) == 0
has_explicit_length = (info_bits & (1 | 4)) != 4
is_unicode = (info_bits & 0x10) == 0x10
is_special = (
nsstring.GetDynamicValue(
lldb.eDynamicCanRunTarget).GetTypeName() == "NSPathStore2")
has_null = (info_bits & 8) == 8

print >>result, "\nInfo=%d\nMutable=%s\nInline=%s\nExplicit=%s\nUnicode=%s\nSpecial=%s\nNull=%s\n" % \
(info_bits, "yes" if is_mutable else "no", "yes" if is_inline else "no", "yes" if has_explicit_length else "no", "yes" if is_unicode else "no", "yes" if is_special else "no", "yes" if has_null else "no")

explicit_length_offset = 0
if not has_null and has_explicit_length and not is_special:
explicit_length_offset = 2 * ptr_size
if is_mutable and not is_inline:
explicit_length_offset = explicit_length_offset + ptr_size
elif is_inline:
pass
elif not is_inline and not is_mutable:
explicit_length_offset = explicit_length_offset + ptr_size
else:
explicit_length_offset = 0

explicit_length_offset = 0
if not has_null and has_explicit_length and not is_special:
explicit_length_offset = 2*ptr_size
if is_mutable and not is_inline:
explicit_length_offset = explicit_length_offset + ptr_size
elif is_inline:
pass
elif not is_inline and not is_mutable:
explicit_length_offset = explicit_length_offset + ptr_size
else:
explicit_length_offset = 0
if explicit_length_offset == 0:
print >>result, "There is no explicit length marker - skipping this step\n"
else:
explicit_length_offset = nsstring_address + explicit_length_offset
explicit_length = process.ReadUnsignedFromMemory(
explicit_length_offset, 4, error)
print >>result, "Explicit length location is at 0x%x - read value is %d\n" % (
explicit_length_offset, explicit_length)

if explicit_length_offset == 0:
print >>result,"There is no explicit length marker - skipping this step\n"
else:
explicit_length_offset = nsstring_address + explicit_length_offset
explicit_length = process.ReadUnsignedFromMemory(explicit_length_offset, 4, error)
print >>result,"Explicit length location is at 0x%x - read value is %d\n" % (explicit_length_offset,explicit_length)
if is_mutable:
location = 2 * ptr_size + nsstring_address
location = process.ReadPointerFromMemory(location, error)
elif is_inline and has_explicit_length and not is_unicode and not is_special and not is_mutable:
location = 3 * ptr_size + nsstring_address
elif is_unicode:
location = 2 * ptr_size + nsstring_address
if is_inline:
if not has_explicit_length:
print >>result, "Unicode & Inline & !Explicit is a new combo - no formula for it"
else:
location += ptr_size
else:
location = process.ReadPointerFromMemory(location, error)
elif is_special:
location = nsstring_address + ptr_size + 4
elif is_inline:
location = 2 * ptr_size + nsstring_address
if not has_explicit_length:
location += 1
else:
location = 2 * ptr_size + nsstring_address
location = process.ReadPointerFromMemory(location, error)
print >>result, "Expected data location: 0x%x\n" % (location)
print >>result, "1K of data around location: %s\n" % read_memory(
process, location, 1024)
print >>result, "5K of data around string pointer: %s\n" % read_memory(
process, nsstring_address, 1024 * 5)

if is_mutable:
location = 2 * ptr_size + nsstring_address
location = process.ReadPointerFromMemory(location,error)
elif is_inline and has_explicit_length and not is_unicode and not is_special and not is_mutable:
location = 3 * ptr_size + nsstring_address
elif is_unicode:
location = 2 * ptr_size + nsstring_address
if is_inline:
if not has_explicit_length:
print >>result,"Unicode & Inline & !Explicit is a new combo - no formula for it"
else:
location += ptr_size
else:
location = process.ReadPointerFromMemory(location,error)
elif is_special:
location = nsstring_address + ptr_size + 4
elif is_inline:
location = 2 * ptr_size + nsstring_address
if not has_explicit_length:
location += 1
else:
location = 2 * ptr_size + nsstring_address
location = process.ReadPointerFromMemory(location,error)
print >>result,"Expected data location: 0x%x\n" % (location)
print >>result,"1K of data around location: %s\n" % read_memory(process,location,1024)
print >>result,"5K of data around string pointer: %s\n" % read_memory(process,nsstring_address,1024*5)

def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand("command script add -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" % __name__)
print 'The "diagnose-nsstring" command has been installed, type "help diagnose-nsstring" for detailed help.'
debugger.HandleCommand(
"command script add -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" %
__name__)
print 'The "diagnose-nsstring" command has been installed, type "help diagnose-nsstring" for detailed help.'

__lldb_init_module(lldb.debugger,None)
__lldb_init_module = None
__lldb_init_module(lldb.debugger, None)
__lldb_init_module = None
491 changes: 267 additions & 224 deletions lldb/examples/python/diagnose_unwind.py

Large diffs are not rendered by default.

29 changes: 15 additions & 14 deletions lldb/examples/python/dict_utils.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@

class LookupDictionary(dict):
"""
a dictionary which can lookup value by key, or keys by value
"""

def __init__(self, items=[]):
"""items can be a list of pair_lists or a dictionary"""
dict.__init__(self, items)
def get_keys_for_value(self, value, fail_value = None):

def get_keys_for_value(self, value, fail_value=None):
"""find the key(s) as a list given a value"""
list_result = [item[0] for item in self.items() if item[1] == value]
if len(list_result) > 0:
return list_result
return fail_value
def get_first_key_for_value(self, value, fail_value = None):

def get_first_key_for_value(self, value, fail_value=None):
"""return the first key of this dictionary given the value"""
list_result = [item[0] for item in self.items() if item[1] == value]
if len(list_result) > 0:
return list_result[0]
return fail_value

def get_value(self, key, fail_value = None):
def get_value(self, key, fail_value=None):
"""find the value given a key"""
if key in self:
return self[key]
return fail_value


class Enum(LookupDictionary):

def __init__(self, initial_value=0, items=[]):
"""items can be a list of pair_lists or a dictionary"""
LookupDictionary.__init__(self, items)
self.value = initial_value

def set_value(self, v):
v_typename = typeof(v).__name__
if v_typename == 'str':
Expand All @@ -44,18 +45,18 @@ def set_value(self, v):
v = 0
else:
self.value = v

def get_enum_value(self):
return self.value

def get_enum_name(self):
return self.__str__()

def __str__(self):
s = self.get_first_key_for_value (self.value, None)
if s == None:
s = self.get_first_key_for_value(self.value, None)
if s is None:
s = "%#8.8x" % self.value
return s

def __repr__(self):
return self.__str__()
return self.__str__()
120 changes: 91 additions & 29 deletions lldb/examples/python/disasm-stress-test.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,82 @@
#!/usr/bin/python

import argparse, datetime, re, subprocess, sys, time

parser = argparse.ArgumentParser(description="Run an exhaustive test of the LLDB disassembler for a specific architecture.")

parser.add_argument('--arch', required=True, action='store', help='The architecture whose disassembler is to be tested')
parser.add_argument('--bytes', required=True, action='store', type=int, help='The byte width of instructions for that architecture')
parser.add_argument('--random', required=False, action='store_true', help='Enables non-sequential testing')
parser.add_argument('--start', required=False, action='store', type=int, help='The first instruction value to test')
parser.add_argument('--skip', required=False, action='store', type=int, help='The interval between instructions to test')
parser.add_argument('--log', required=False, action='store', help='A log file to write the most recent instruction being tested')
parser.add_argument('--time', required=False, action='store_true', help='Every 100,000 instructions, print an ETA to standard out')
parser.add_argument('--lldb', required=False, action='store', help='The path to LLDB.framework, if LLDB should be overridden')
import argparse
import datetime
import re
import subprocess
import sys
import time

parser = argparse.ArgumentParser(
description="Run an exhaustive test of the LLDB disassembler for a specific architecture.")

parser.add_argument(
'--arch',
required=True,
action='store',
help='The architecture whose disassembler is to be tested')
parser.add_argument(
'--bytes',
required=True,
action='store',
type=int,
help='The byte width of instructions for that architecture')
parser.add_argument(
'--random',
required=False,
action='store_true',
help='Enables non-sequential testing')
parser.add_argument(
'--start',
required=False,
action='store',
type=int,
help='The first instruction value to test')
parser.add_argument(
'--skip',
required=False,
action='store',
type=int,
help='The interval between instructions to test')
parser.add_argument(
'--log',
required=False,
action='store',
help='A log file to write the most recent instruction being tested')
parser.add_argument(
'--time',
required=False,
action='store_true',
help='Every 100,000 instructions, print an ETA to standard out')
parser.add_argument(
'--lldb',
required=False,
action='store',
help='The path to LLDB.framework, if LLDB should be overridden')

arguments = sys.argv[1:]

arg_ns = parser.parse_args(arguments)


def AddLLDBToSysPathOnMacOSX():
def GetLLDBFrameworkPath():
lldb_path = subprocess.check_output(["xcrun", "-find", "lldb"])
re_result = re.match("(.*)/Developer/usr/bin/lldb", lldb_path)
if re_result == None:
if re_result is None:
return None
xcode_contents_path = re_result.group(1)
return xcode_contents_path + "/SharedFrameworks/LLDB.framework"

lldb_framework_path = GetLLDBFrameworkPath()
if lldb_framework_path == None:

if lldb_framework_path is None:
print "Couldn't find LLDB.framework"
sys.exit(-1)

sys.path.append(lldb_framework_path + "/Resources/Python")

if arg_ns.lldb == None:
if arg_ns.lldb is None:
AddLLDBToSysPathOnMacOSX()
else:
sys.path.append(arg_ns.lldb + "/Resources/Python")
Expand All @@ -53,87 +95,104 @@ def GetLLDBFrameworkPath():
print "Couldn't create an SBTarget for architecture " + arg_ns.arch
sys.exit(-1)


def ResetLogFile(log_file):
if log_file != sys.stdout:
log_file.seek(0)


def PrintByteArray(log_file, byte_array):
for byte in byte_array:
print >>log_file, hex(byte) + " ",
print >>log_file



class SequentialInstructionProvider:

def __init__(self, byte_width, log_file, start=0, skip=1):
self.m_byte_width = byte_width
self.m_log_file = log_file
self.m_start = start
self.m_skip = skip
self.m_value = start
self.m_last = (1 << (byte_width * 8)) - 1

def PrintCurrentState(self, ret):
ResetLogFile(self.m_log_file)
print >>self.m_log_file, self.m_value
PrintByteArray(self.m_log_file, ret)

def GetNextInstruction(self):
if self.m_value > self.m_last:
return None
ret = bytearray(self.m_byte_width)
for i in range(self.m_byte_width):
ret[self.m_byte_width - (i + 1)] = (self.m_value >> (i * 8)) & 255
ret[self.m_byte_width - (i + 1)] = (self.m_value >> (i * 8)) & 255
self.PrintCurrentState(ret)
self.m_value += self.m_skip
return ret

def GetNumInstructions(self):
return (self.m_last - self.m_start) / self.m_skip

def __iter__(self):
return self

def next(self):
ret = self.GetNextInstruction()
if ret == None:
if ret is None:
raise StopIteration
return ret


class RandomInstructionProvider:

def __init__(self, byte_width, log_file):
self.m_byte_width = byte_width
self.m_log_file = log_file
self.m_random_file = open("/dev/random", 'r')

def PrintCurrentState(self, ret):
ResetLogFile(self.m_log_file)
PrintByteArray(self.m_log_file, ret)

def GetNextInstruction(self):
ret = bytearray(self.m_byte_width)
for i in range(self.m_byte_width):
ret[i] = self.m_random_file.read(1)
self.PrintCurrentState(ret)
return ret

def __iter__(self):
return self

def next(self):
ret = self.GetNextInstruction()
if ret == None:
if ret is None:
raise StopIteration
return ret

log_file = None


def GetProviderWithArguments(args):
global log_file
if args.log != None:
if args.log is not None:
log_file = open(args.log, 'w')
else:
log_file = sys.stdout
instruction_provider = None
if args.random == True:
if args.random:
instruction_provider = RandomInstructionProvider(args.bytes, log_file)
else:
start = 0
skip = 1
if args.start != None:
if args.start is not None:
start = args.start
if args.skip != None:
if args.skip is not None:
skip = args.skip
instruction_provider = SequentialInstructionProvider(args.bytes, log_file, start, skip)
instruction_provider = SequentialInstructionProvider(
args.bytes, log_file, start, skip)
return instruction_provider

instruction_provider = GetProviderWithArguments(arg_ns)
Expand All @@ -149,10 +208,13 @@ def GetProviderWithArguments(args):

for inst_bytes in instruction_provider:
if actually_time:
if (num_instructions_logged != 0) and (num_instructions_logged % 100000 == 0):
if (num_instructions_logged != 0) and (
num_instructions_logged % 100000 == 0):
curr_time = time.time()
elapsed_time = curr_time - start_time
remaining_time = float(total_num_instructions - num_instructions_logged) * (float(elapsed_time) / float(num_instructions_logged))
remaining_time = float(
total_num_instructions - num_instructions_logged) * (
float(elapsed_time) / float(num_instructions_logged))
print str(datetime.timedelta(seconds=remaining_time))
num_instructions_logged = num_instructions_logged + 1
inst_list = target.GetInstructions(fake_address, inst_bytes)
Expand Down
49 changes: 28 additions & 21 deletions lldb/examples/python/disasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
import os
import sys

def disassemble_instructions (insts):

def disassemble_instructions(insts):
for i in insts:
print i


def usage():
print "Usage: disasm.py [-n name] executable-image"
print " By default, it breaks at and disassembles the 'main' function."
Expand All @@ -36,63 +38,69 @@ def usage():
# Create a new debugger instance
debugger = lldb.SBDebugger.Create()

# When we step or continue, don't return from the function until the process
# 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)
debugger.SetAsync(False)

# Create a target from a file and arch
print "Creating a target for '%s'" % exe

target = debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)
target = debugger.CreateTargetWithFileAndArch(exe, lldb.LLDB_ARCH_DEFAULT)

if target:
# If the target is valid set a breakpoint at main
main_bp = target.BreakpointCreateByName (fname, target.GetExecutable().GetFilename());
main_bp = target.BreakpointCreateByName(
fname, target.GetExecutable().GetFilename())

print main_bp

# Launch the process. Since we specified synchronous mode, we won't return
# from this function until we hit the breakpoint at main
process = target.LaunchSimple (None, None, os.getcwd())
process = target.LaunchSimple(None, None, os.getcwd())

# Make sure the launch went ok
if process:
# Print some simple process info
state = process.GetState ()
state = process.GetState()
print process
if state == lldb.eStateStopped:
# Get the first thread
thread = process.GetThreadAtIndex (0)
thread = process.GetThreadAtIndex(0)
if thread:
# Print some simple thread info
print thread
# Get the first frame
frame = thread.GetFrameAtIndex (0)
frame = thread.GetFrameAtIndex(0)
if frame:
# Print some simple frame info
print frame
function = frame.GetFunction()
# See if we have debug info (a function)
if function:
# We do have a function, print some info for the function
# We do have a function, print some info for the
# function
print function
# Now get all instructions for this function and print them
# Now get all instructions for this function and print
# them
insts = function.GetInstructions(target)
disassemble_instructions (insts)
disassemble_instructions(insts)
else:
# See if we have a symbol in the symbol table for where we stopped
symbol = frame.GetSymbol();
# See if we have a symbol in the symbol table for where
# we stopped
symbol = frame.GetSymbol()
if symbol:
# We do have a symbol, print some info for the symbol
# We do have a symbol, print some info for the
# symbol
print symbol
# Now get all instructions for this symbol and print them
# Now get all instructions for this symbol and
# print them
insts = symbol.GetInstructions(target)
disassemble_instructions (insts)
disassemble_instructions(insts)

registerList = frame.GetRegisters()
print "Frame registers (size of register set = %d):" % registerList.GetSize()
for value in registerList:
#print value
# print value
print "%s (number of children = %d):" % (value.GetName(), value.GetNumChildren())
for child in value:
print "Name: ", child.GetName(), " Value: ", child.GetValue()
Expand All @@ -111,9 +119,8 @@ def usage():
elif state == lldb.eStateExited:
print "Didn't hit the breakpoint at main, program has exited..."
else:
print "Unexpected process state: %s, killing process..." % debugger.StateAsCString (state)
print "Unexpected process state: %s, killing process..." % debugger.StateAsCString(state)
process.Kill()



lldb.SBDebugger.Terminate()
45 changes: 25 additions & 20 deletions lldb/examples/python/file_extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
import struct
import sys


class FileExtract:
'''Decode binary data from a file'''
def __init__(self, f, b = '='):

def __init__(self, f, b='='):
'''Initialize with an open binary file and optional byte order'''

self.file = f
self.byte_order = b
self.offsets = list()

def set_byte_order(self, b):
'''Set the byte order, valid values are "big", "little", "swap", "native", "<", ">", "@", "="'''
if b == 'big':
Expand All @@ -32,18 +33,18 @@ def set_byte_order(self, b):

def is_in_memory(self):
return False
def seek(self, offset, whence = 0):

def seek(self, offset, whence=0):
if self.file:
return self.file.seek(offset, whence)
raise ValueError
raise ValueError

def tell(self):
if self.file:
return self.file.tell()
raise ValueError
def read_size (self, byte_size):
raise ValueError

def read_size(self, byte_size):
s = self.file.read(byte_size)
if len(s) != byte_size:
return None
Expand All @@ -53,12 +54,12 @@ def push_offset_and_seek(self, offset):
'''Push the current file offset and seek to "offset"'''
self.offsets.append(self.file.tell())
self.file.seek(offset, 0)

def pop_offset_and_seek(self):
'''Pop a previously pushed file offset, or do nothing if there were no previously pushed offsets'''
if len(self.offsets) > 0:
self.file.seek(self.offsets.pop())

def get_sint8(self, fail_value=0):
'''Extract a single int8_t from the binary file at the current file position, returns a single integer'''
s = self.read_size(1)
Expand Down Expand Up @@ -112,7 +113,7 @@ def get_uint32(self, fail_value=0):
return v
else:
return fail_value

def get_sint64(self, fail_value=0):
'''Extract a single int64_t from the binary file at the current file position, returns a single integer'''
s = self.read_size(8)
Expand All @@ -131,7 +132,11 @@ def get_uint64(self, fail_value=0):
else:
return fail_value

def get_fixed_length_c_string(self, n, fail_value='', isprint_only_with_space_padding=False):
def get_fixed_length_c_string(
self,
n,
fail_value='',
isprint_only_with_space_padding=False):
'''Extract a single fixed length C string from the binary file at the current file position, returns a single C string'''
s = self.read_size(n)
if s:
Expand Down Expand Up @@ -174,47 +179,47 @@ def get_n_uint8(self, n, fail_value=0):

def get_n_sint16(self, n, fail_value=0):
'''Extract "n" int16_t integers from the binary file at the current file position, returns a list of integers'''
s = self.read_size(2*n)
s = self.read_size(2 * n)
if s:
return struct.unpack(self.byte_order + ("%u" % n) + 'h', s)
else:
return (fail_value,) * n

def get_n_uint16(self, n, fail_value=0):
'''Extract "n" uint16_t integers from the binary file at the current file position, returns a list of integers'''
s = self.read_size(2*n)
s = self.read_size(2 * n)
if s:
return struct.unpack(self.byte_order + ("%u" % n) + 'H', s)
else:
return (fail_value,) * n

def get_n_sint32(self, n, fail_value=0):
'''Extract "n" int32_t integers from the binary file at the current file position, returns a list of integers'''
s = self.read_size(4*n)
s = self.read_size(4 * n)
if s:
return struct.unpack(self.byte_order + ("%u" % n) + 'i', s)
else:
return (fail_value,) * n

def get_n_uint32(self, n, fail_value=0):
'''Extract "n" uint32_t integers from the binary file at the current file position, returns a list of integers'''
s = self.read_size(4*n)
s = self.read_size(4 * n)
if s:
return struct.unpack(self.byte_order + ("%u" % n) + 'I', s)
else:
return (fail_value,) * n

def get_n_sint64(self, n, fail_value=0):
'''Extract "n" int64_t integers from the binary file at the current file position, returns a list of integers'''
s = self.read_size(8*n)
s = self.read_size(8 * n)
if s:
return struct.unpack(self.byte_order + ("%u" % n) + 'q', s)
else:
return (fail_value,) * n

def get_n_uint64(self, n, fail_value=0):
'''Extract "n" uint64_t integers from the binary file at the current file position, returns a list of integers'''
s = self.read_size(8*n)
s = self.read_size(8 * n)
if s:
return struct.unpack(self.byte_order + ("%u" % n) + 'Q', s)
else:
Expand Down
10 changes: 6 additions & 4 deletions lldb/examples/python/gdb_disassemble.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import lldb


def disassemble(debugger, command, result, dict):
if lldb.frame.function:
instructions = lldb.frame.function.instructions
Expand All @@ -9,7 +10,7 @@ def disassemble(debugger, command, result, dict):
instructions = lldb.frame.symbol.instructions
start_addr = lldb.frame.symbol.addr.load_addr
name = lldb.frame.symbol.name

for inst in instructions:
inst_addr = inst.addr.load_addr
inst_offset = inst_addr - start_addr
Expand All @@ -18,7 +19,8 @@ def disassemble(debugger, command, result, dict):
print "<%s + %-4u> 0x%x %8s %s ; %s" % (name, inst_offset, inst_addr, inst.mnemonic, inst.operands, comment)
else:
print "<%s + %-4u> 0x%x %8s %s" % (name, inst_offset, inst_addr, inst.mnemonic, inst.operands)

# Install the command when the module gets imported
lldb.debugger.HandleCommand('command script add -f gdb_disassemble.disassemble gdb-disassemble')
print 'Installed "gdb-disassemble" command for disassembly'
lldb.debugger.HandleCommand(
'command script add -f gdb_disassemble.disassemble gdb-disassemble')
print 'Installed "gdb-disassemble" command for disassembly'
757 changes: 462 additions & 295 deletions lldb/examples/python/gdbremote.py

Large diffs are not rendered by default.

74 changes: 54 additions & 20 deletions lldb/examples/python/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,58 +15,92 @@
import shlex
import sys


def get_globals(raw_path, options):
error = lldb.SBError()
# Resolve the path if needed
path = os.path.expanduser(raw_path)
# Create a target using path + options
target = lldb.debugger.CreateTarget(path, options.arch, options.platform, False, error)
target = lldb.debugger.CreateTarget(
path, options.arch, options.platform, False, error)
if target:
# Get the executable module
module = target.module[target.executable.basename]
if module:
# Keep track of which variables we have already looked up
global_names = list()
# Iterate through all symbols in the symbol table and watch for any DATA symbols
# Iterate through all symbols in the symbol table and watch for any
# DATA symbols
for symbol in module.symbols:
if symbol.type == lldb.eSymbolTypeData:
# The symbol is a DATA symbol, lets try and find all global variables
# The symbol is a DATA symbol, lets try and find all global variables
# that match this name and print them
global_name = symbol.name
# Make sure we don't lookup the same variable twice
if global_name not in global_names:
global_names.append(global_name)
# Find all global variables by name
global_variable_list = module.FindGlobalVariables (target, global_name, lldb.UINT32_MAX)
global_variable_list = module.FindGlobalVariables(
target, global_name, lldb.UINT32_MAX)
if global_variable_list:
# Print results for anything that matched
for global_variable in global_variable_list:
print 'name = %s' % global_variable.name # returns the global variable name as a string
print 'value = %s' % global_variable.value # Returns the variable value as a string
# returns the global variable name as a string
print 'name = %s' % global_variable.name
# Returns the variable value as a string
print 'value = %s' % global_variable.value
print 'type = %s' % global_variable.type # Returns an lldb.SBType object
print 'addr = %s' % global_variable.addr # Returns an lldb.SBAddress (section offset address) for this global
print 'file_addr = 0x%x' % global_variable.addr.file_addr # Returns the file virtual address for this global
print 'location = %s' % global_variable.location # returns the global variable value as a string
print 'size = %s' % global_variable.size # Returns the size in bytes of this global variable
# Returns an lldb.SBAddress (section offset
# address) for this global
print 'addr = %s' % global_variable.addr
# Returns the file virtual address for this
# global
print 'file_addr = 0x%x' % global_variable.addr.file_addr
# returns the global variable value as a string
print 'location = %s' % global_variable.location
# Returns the size in bytes of this global
# variable
print 'size = %s' % global_variable.size
print


def globals(command_args):
'''Extract all globals from any arguments which must be paths to object files.'''
usage = "usage: %prog [options] <PATH> [PATH ...]"
description='''This command will find all globals in the specified object file and return an list() of lldb.SBValue objects (which might be empty).'''
parser = optparse.OptionParser(description=description, prog='globals',usage=usage)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
parser.add_option('-a', '--arch', type='string', metavar='arch', dest='arch', help='Specify an architecture (or triple) to use when extracting from a file.')
parser.add_option('-p', '--platform', type='string', metavar='platform', dest='platform', help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
description = '''This command will find all globals in the specified object file and return an list() of lldb.SBValue objects (which might be empty).'''
parser = optparse.OptionParser(
description=description,
prog='globals',
usage=usage)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
parser.add_option(
'-a',
'--arch',
type='string',
metavar='arch',
dest='arch',
help='Specify an architecture (or triple) to use when extracting from a file.')
parser.add_option(
'-p',
'--platform',
type='string',
metavar='platform',
dest='platform',
help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
try:
(options, args) = parser.parse_args(command_args)
except:
return

for path in args:
get_globals (path, options)
get_globals(path, options)

if __name__ == '__main__':
lldb.debugger = lldb.SBDebugger.Create()
globals (sys.argv[1:])

globals(sys.argv[1:])
79 changes: 51 additions & 28 deletions lldb/examples/python/jump.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import lldb, re
import lldb
import re

def parse_linespec (linespec, frame, result):

def parse_linespec(linespec, frame, result):
"""Handles a subset of GDB-style linespecs. Specifically:
number - A line in the current file
+offset - The line /offset/ lines after this line
-offset - The line /offset/ lines before this line
Expand All @@ -21,65 +23,73 @@ def parse_linespec (linespec, frame, result):

if (not matched):
mo = re.match("^([0-9]+)$", linespec)
if (mo != None):
if (mo is not None):
matched = True
#print "Matched <linenum>"
# print "Matched <linenum>"
line_number = int(mo.group(1))
line_entry = frame.GetLineEntry()
if not line_entry.IsValid():
result.AppendMessage("Specified a line in the current file, but the current frame doesn't have line table information.")
result.AppendMessage(
"Specified a line in the current file, but the current frame doesn't have line table information.")
return
breakpoint = target.BreakpointCreateByLocation (line_entry.GetFileSpec(), line_number)
breakpoint = target.BreakpointCreateByLocation(
line_entry.GetFileSpec(), line_number)

if (not matched):
mo = re.match("^\+([0-9]+)$", linespec)
if (mo != None):
if (mo is not None):
matched = True
#print "Matched +<count>"
# print "Matched +<count>"
line_number = int(mo.group(1))
line_entry = frame.GetLineEntry()
if not line_entry.IsValid():
result.AppendMessage("Specified a line in the current file, but the current frame doesn't have line table information.")
result.AppendMessage(
"Specified a line in the current file, but the current frame doesn't have line table information.")
return
breakpoint = target.BreakpointCreateByLocation(line_entry.GetFileSpec(), (line_entry.GetLine() + line_number))

breakpoint = target.BreakpointCreateByLocation(
line_entry.GetFileSpec(), (line_entry.GetLine() + line_number))

if (not matched):
mo = re.match("^\-([0-9]+)$", linespec)
if (mo != None):
if (mo is not None):
matched = True
#print "Matched -<count>"
# print "Matched -<count>"
line_number = int(mo.group(1))
line_entry = frame.GetLineEntry()
if not line_entry.IsValid():
result.AppendMessage("Specified a line in the current file, but the current frame doesn't have line table information.")
result.AppendMessage(
"Specified a line in the current file, but the current frame doesn't have line table information.")
return
breakpoint = target.BreakpointCreateByLocation(line_entry.GetFileSpec(), (line_entry.GetLine() - line_number))
breakpoint = target.BreakpointCreateByLocation(
line_entry.GetFileSpec(), (line_entry.GetLine() - line_number))

if (not matched):
mo = re.match("^(.*):([0-9]+)$", linespec)
if (mo != None):
if (mo is not None):
matched = True
#print "Matched <filename>:<linenum>"
# print "Matched <filename>:<linenum>"
file_name = mo.group(1)
line_number = int(mo.group(2))
breakpoint = target.BreakpointCreateByLocation(file_name, line_number)
breakpoint = target.BreakpointCreateByLocation(
file_name, line_number)

if (not matched):
mo = re.match("\*((0x)?([0-9a-f]+))$", linespec)
if (mo != None):
if (mo is not None):
matched = True
#print "Matched <address-expression>"
# print "Matched <address-expression>"
address = long(mo.group(1), base=0)
breakpoint = target.BreakpointCreateByAddress(address)

if (not matched):
#print "Trying <function-name>"
# print "Trying <function-name>"
breakpoint = target.BreakpointCreateByName(linespec)

num_locations = breakpoint.GetNumLocations()

if (num_locations == 0):
result.AppendMessage("The line specification provided doesn't resolve to any addresses.")
result.AppendMessage(
"The line specification provided doesn't resolve to any addresses.")

addr_list = []

Expand All @@ -91,6 +101,7 @@ def parse_linespec (linespec, frame, result):

return addr_list


def usage_string():
return """ Sets the program counter to a specific address.
Expand All @@ -106,7 +117,8 @@ def usage_string():
<location-id> serves to disambiguate when multiple locations could be meant."""

def jump (debugger, command, result, internal_dict):

def jump(debugger, command, result, internal_dict):
if (command == ""):
result.AppendMessage(usage_string())

Expand Down Expand Up @@ -151,17 +163,28 @@ def jump (debugger, command, result, internal_dict):
if (desired_index >= 0) and (desired_index < len(addresses)):
desired_address = addresses[desired_index]
else:
result.AppendMessage("Desired index " + args[1] + " is not one of the options.")
result.AppendMessage(
"Desired index " +
args[1] +
" is not one of the options.")
return
else:
index = 0
result.AppendMessage("The specified location resolves to multiple targets.");
result.AppendMessage(
"The specified location resolves to multiple targets.")
for address in addresses:
stream.Clear()
address.GetDescription(stream)
result.AppendMessage(" Location ID " + str(index) + ": " + stream.GetData())
result.AppendMessage(
" Location ID " +
str(index) +
": " +
stream.GetData())
index = index + 1
result.AppendMessage("Please type 'jump " + command + " <location-id>' to choose one.")
result.AppendMessage(
"Please type 'jump " +
command +
" <location-id>' to choose one.")
return

frame.SetPC(desired_address.GetLoadAddress(target))
Expand Down
57 changes: 38 additions & 19 deletions lldb/examples/python/lldb_module_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,29 @@
import string
import sys

def create_dump_module_line_tables_options ():

def create_dump_module_line_tables_options():
usage = "usage: dump_module_line_tables [options] MODULE1 [MODULE2 ...]"
description='''Dumps all line tables from all compile units for any modules specified as arguments. Specifying the --verbose flag will output address ranges for each line entry.'''
parser = optparse.OptionParser(description=description, prog='start_gdb_log',usage=usage)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='Display verbose output.', default=False)
description = '''Dumps all line tables from all compile units for any modules specified as arguments. Specifying the --verbose flag will output address ranges for each line entry.'''
parser = optparse.OptionParser(
description=description,
prog='start_gdb_log',
usage=usage)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='Display verbose output.',
default=False)
return parser



def dump_module_line_tables(debugger, command, result, dict):
'''Dumps all line tables from all compile units for any modules specified as arguments.'''
command_args = shlex.split(command)
parser = create_dump_module_line_tables_options ()

parser = create_dump_module_line_tables_options()
try:
(options, args) = parser.parse_args(command_args)
except:
Expand All @@ -27,33 +38,41 @@ def dump_module_line_tables(debugger, command, result, dict):
lldb.target = target
for module_name in command_args:
result.PutCString('Searching for module "%s"' % (module_name,))
module_fspec = lldb.SBFileSpec (module_name, False)
module = target.FindModule (module_fspec);
module_fspec = lldb.SBFileSpec(module_name, False)
module = target.FindModule(module_fspec)
if module:
for cu_idx in range (module.GetNumCompileUnits()):
for cu_idx in range(module.GetNumCompileUnits()):
cu = module.GetCompileUnitAtIndex(cu_idx)
result.PutCString("\n%s:" % (cu.file))
for line_idx in range(cu.GetNumLineEntries()):
line_entry = cu.GetLineEntryAtIndex(line_idx)
start_file_addr = line_entry.addr.file_addr
end_file_addr = line_entry.end_addr.file_addr
# If the two addresses are equal, this line table entry is a termination entry
# If the two addresses are equal, this line table entry
# is a termination entry
if options.verbose:
if start_file_addr != end_file_addr:
result.PutCString('[%#x - %#x): %s' % (start_file_addr, end_file_addr, line_entry))
result.PutCString(
'[%#x - %#x): %s' %
(start_file_addr, end_file_addr, line_entry))
else:
if start_file_addr == end_file_addr:
result.PutCString('%#x: END' % (start_file_addr))
result.PutCString('%#x: END' %
(start_file_addr))
else:
result.PutCString('%#x: %s' % (start_file_addr, line_entry))
result.PutCString(
'%#x: %s' %
(start_file_addr, line_entry))
if start_file_addr == end_file_addr:
result.Printf("\n")
else:
result.PutCString ("no module for '%s'" % module)
result.PutCString("no module for '%s'" % module)
else:
result.PutCString ("error: invalid target")
result.PutCString("error: invalid target")

parser = create_dump_module_line_tables_options ()
parser = create_dump_module_line_tables_options()
dump_module_line_tables.__doc__ = parser.format_help()
lldb.debugger.HandleCommand('command script add -f %s.dump_module_line_tables dump_module_line_tables' % __name__)
print 'Installed "dump_module_line_tables" command'
lldb.debugger.HandleCommand(
'command script add -f %s.dump_module_line_tables dump_module_line_tables' %
__name__)
print 'Installed "dump_module_line_tables" command'
365 changes: 217 additions & 148 deletions lldb/examples/python/lldbtk.py

Large diffs are not rendered by default.

1,426 changes: 792 additions & 634 deletions lldb/examples/python/mach_o.py

Large diffs are not rendered by default.

185 changes: 140 additions & 45 deletions lldb/examples/python/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Be sure to add the python path that points to the LLDB shared library.
#
# # To use this in the embedded python interpreter using "lldb" just
# import it with the full path using the "command script import"
# import it with the full path using the "command script import"
# command
# (lldb) command script import /path/to/cmdtemplate.py
#----------------------------------------------------------------------
Expand All @@ -15,7 +15,7 @@
import re
import sys

try:
try:
# Just try for LLDB in case PYTHONPATH is already correctly setup
import lldb
except ImportError:
Expand All @@ -26,15 +26,20 @@
# On Darwin, try the currently selected Xcode directory
xcode_dir = commands.getoutput("xcode-select --print-path")
if xcode_dir:
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append(
os.path.realpath(
xcode_dir +
'/../SharedFrameworks/LLDB.framework/Resources/Python'))
lldb_python_dirs.append(
xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append(
'/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
success = False
for lldb_python_dir in lldb_python_dirs:
if os.path.exists(lldb_python_dir):
if not (sys.path.__contains__(lldb_python_dir)):
sys.path.append(lldb_python_dir)
try:
try:
import lldb
except ImportError:
pass
Expand All @@ -53,52 +58,129 @@
import struct
import time


def append_data_callback(option, opt_str, value, parser):
if opt_str == "--uint8":
int8 = int(value, 0)
parser.values.data += struct.pack('1B',int8)
parser.values.data += struct.pack('1B', int8)
if opt_str == "--uint16":
int16 = int(value, 0)
parser.values.data += struct.pack('1H',int16)
parser.values.data += struct.pack('1H', int16)
if opt_str == "--uint32":
int32 = int(value, 0)
parser.values.data += struct.pack('1I',int32)
parser.values.data += struct.pack('1I', int32)
if opt_str == "--uint64":
int64 = int(value, 0)
parser.values.data += struct.pack('1Q',int64)
parser.values.data += struct.pack('1Q', int64)
if opt_str == "--int8":
int8 = int(value, 0)
parser.values.data += struct.pack('1b',int8)
parser.values.data += struct.pack('1b', int8)
if opt_str == "--int16":
int16 = int(value, 0)
parser.values.data += struct.pack('1h',int16)
parser.values.data += struct.pack('1h', int16)
if opt_str == "--int32":
int32 = int(value, 0)
parser.values.data += struct.pack('1i',int32)
parser.values.data += struct.pack('1i', int32)
if opt_str == "--int64":
int64 = int(value, 0)
parser.values.data += struct.pack('1q',int64)
parser.values.data += struct.pack('1q', int64)


def create_memfind_options():
usage = "usage: %prog [options] STARTADDR [ENDADDR]"
description='''This command can find data in a specified address range.
description = '''This command can find data in a specified address range.
Options are used to specify the data that is to be looked for and the options
can be specified multiple times to look for longer streams of data.
'''
parser = optparse.OptionParser(description=description, prog='memfind',usage=usage)
parser.add_option('-s', '--size', type='int', metavar='BYTESIZE', dest='size', help='Specify the byte size to search.', default=0)
parser.add_option('--int8', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 8 bit signed integer value to search for in memory.', default='')
parser.add_option('--int16', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 16 bit signed integer value to search for in memory.', default='')
parser.add_option('--int32', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 32 bit signed integer value to search for in memory.', default='')
parser.add_option('--int64', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 64 bit signed integer value to search for in memory.', default='')
parser.add_option('--uint8', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 8 bit unsigned integer value to search for in memory.', default='')
parser.add_option('--uint16', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 16 bit unsigned integer value to search for in memory.', default='')
parser.add_option('--uint32', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 32 bit unsigned integer value to search for in memory.', default='')
parser.add_option('--uint64', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 64 bit unsigned integer value to search for in memory.', default='')
parser = optparse.OptionParser(
description=description,
prog='memfind',
usage=usage)
parser.add_option(
'-s',
'--size',
type='int',
metavar='BYTESIZE',
dest='size',
help='Specify the byte size to search.',
default=0)
parser.add_option(
'--int8',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 8 bit signed integer value to search for in memory.',
default='')
parser.add_option(
'--int16',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 16 bit signed integer value to search for in memory.',
default='')
parser.add_option(
'--int32',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 32 bit signed integer value to search for in memory.',
default='')
parser.add_option(
'--int64',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 64 bit signed integer value to search for in memory.',
default='')
parser.add_option(
'--uint8',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 8 bit unsigned integer value to search for in memory.',
default='')
parser.add_option(
'--uint16',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 16 bit unsigned integer value to search for in memory.',
default='')
parser.add_option(
'--uint32',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 32 bit unsigned integer value to search for in memory.',
default='')
parser.add_option(
'--uint64',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 64 bit unsigned integer value to search for in memory.',
default='')
return parser

def memfind_command (debugger, command, result, dict):
# Use the Shell Lexer to properly parse up command options just like a


def memfind_command(debugger, command, result, dict):
# Use the Shell Lexer to properly parse up command options just like a
# shell would
command_args = shlex.split(command)
parser = create_memfind_options()
Expand All @@ -111,71 +193,84 @@ def memfind_command (debugger, command, result, dict):
# result.SetStatus (lldb.eReturnStatusFailed)
# print >>result, "error: option parsing failed" # returning a string is the same as returning an error whose description is the string
# return
memfind (debugger.GetSelectedTarget(), options, args, result)

memfind(debugger.GetSelectedTarget(), options, args, result)


def print_error(str, show_usage, result):
print >>result, str
if show_usage:
print >>result, create_memfind_options().format_help()

def memfind (target, options, args, result):

def memfind(target, options, args, result):
num_args = len(args)
start_addr = 0
if num_args == 1:
if options.size > 0:
print_error ("error: --size must be specified if there is no ENDADDR argument", True, result)
print_error(
"error: --size must be specified if there is no ENDADDR argument",
True,
result)
return
start_addr = int(args[0], 0)
elif num_args == 2:
if options.size != 0:
print_error ("error: --size can't be specified with an ENDADDR argument", True, result)
print_error(
"error: --size can't be specified with an ENDADDR argument",
True,
result)
return
start_addr = int(args[0], 0)
end_addr = int(args[1], 0)
if start_addr >= end_addr:
print_error ("error: inavlid memory range [%#x - %#x)" % (start_addr, end_addr), True, result)
print_error(
"error: inavlid memory range [%#x - %#x)" %
(start_addr, end_addr), True, result)
return
options.size = end_addr - start_addr
else:
print_error ("error: memfind takes 1 or 2 arguments", True, result)
print_error("error: memfind takes 1 or 2 arguments", True, result)
return

if not options.data:
print >>result, 'error: no data specified to search for'
return

if not target:
print >>result, 'error: invalid target'
return
process = target.process
if not process:
print >>result, 'error: invalid process'
return

error = lldb.SBError()
bytes = process.ReadMemory (start_addr, options.size, error)
bytes = process.ReadMemory(start_addr, options.size, error)
if error.Success():
num_matches = 0
print >>result, "Searching memory range [%#x - %#x) for" % (start_addr, end_addr),
print >>result, "Searching memory range [%#x - %#x) for" % (
start_addr, end_addr),
for byte in options.data:
print >>result, '%2.2x' % ord(byte),
print >>result

match_index = string.find(bytes, options.data)
while match_index != -1:
num_matches = num_matches + 1
print >>result, '%#x: %#x + %u' % (start_addr + match_index, start_addr, match_index)
print >>result, '%#x: %#x + %u' % (start_addr +
match_index, start_addr, match_index)
match_index = string.find(bytes, options.data, match_index + 1)

if num_matches == 0:
print >>result, "error: no matches found"
else:
print >>result, 'error: %s' % (error.GetCString())


if __name__ == '__main__':
print 'error: this script is designed to be used within the embedded script interpreter in LLDB'
elif getattr(lldb, 'debugger', None):
memfind_command.__doc__ = create_memfind_options().format_help()
lldb.debugger.HandleCommand('command script add -f memory.memfind_command memfind')
lldb.debugger.HandleCommand(
'command script add -f memory.memfind_command memfind')
print '"memfind" command installed, use the "--help" option for detailed help'
Loading