blob: afc04471deed352af06bb9f8de2b6fa31b922b30 [file] [log] [blame]
#!/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
#
# This script collect debugging information using LLDB. This script is
# used by TEST=dbg in llvm testsuite to measure quality of debug info in
# optimized builds.
#
# Usage:
# export PYTHONPATH=...
# ./CollectDebugInfUsingLLDB.py program bp_file out_file
# program - Executable program with debug info.
# bp_file - Simple text file listing breakpoints.
# <absolute file name> <line number>
# out_file - Output file where the debug info will be emitted.
# ----------------------------------------------------------------------
import lldb
import os
import sys
import time
# AlreadyPrintedValues - A place to keep track of recursive values.
AlreadyPrintedValues = {}
# ISAlreadyPrinted - Return true if value is already printed.
def IsAlreadyPrinted(value_name):
if AlreadyPrintedValues.get(value_name) is None:
AlreadyPrintedValues[value_name] = 1
return False
return True
# print_var_value - Print a variable's value.
def print_var_value(v, file, frame):
if v.IsValid() == False:
return
if IsAlreadyPrinted(v.GetName()):
return
total_children = v.GetNumChildren()
if total_children > 0:
c = 0
while c < total_children:
child = v.GetChildAtIndex(c)
if child is None:
file.write("None")
else:
if (child.GetName()) is None:
file.write("None")
else:
file.write(child.GetName())
file.write("=")
print_var_value(child, file, frame)
file.write(",")
c = c + 1
else:
if v.GetValue(frame) is None:
file.write("None")
else:
file.write(v.GetValue(frame))
def disable_bp(thread):
# disable this thread.
count = thread.GetStopReasonDataCount()
bid = 0
tid = 0
for i in range(count):
id = thread.GetStopReasonDataAtIndex(i)
bp = target.FindBreakpointByID(id)
if bp.IsValid():
if bp.IsEnabled() == True:
bid = bp.GetID()
tid = bp.GetThreadID()
bp.SetEnabled(False)
# print " disabled [", str(bp.GetThreadID()), ":", str(bp.GetID()), "]"
else:
bp_loc = bp.FindLocationByID(thread.GetStopReasonDataAtIndex(i + 1))
if bp_loc.IsValid():
bid = bp_loc.GetBreakPoint().GetID()
tid = bp_loc.ThreadGetID()
bp_loc.SetEnabled(False)
# print " disabled [", str(bp.GetThreadID()), ":", str(bp.GetID()), "]"
# print_vars - Print variable values in output file.
def print_vars(tag, vars, fname, line, file, frame, target, thread):
bid = 0
tid = 0
count = thread.GetStopReasonDataCount()
# print "count = ",count
for i in range(count):
# print "i =", i
id = thread.GetStopReasonDataAtIndex(i)
bp = target.FindBreakpointByID(id)
if bp.IsValid():
bid = bp.GetID()
tid = bp.GetThreadID()
# print "bp is valid", bid, tid
for j in range(vars.GetSize()):
v = vars.GetValueAtIndex(j)
if v.GetName() is not None:
file.write(tag)
file.write(fname)
file.write(":")
file.write(str(line))
file.write(" ")
file.write(str(tid))
file.write(":")
file.write(str(bid))
file.write(" ")
file.write(v.GetName())
file.write(" ")
AlreadyPrintedValues.clear()
print_var_value(v, file, frame)
file.write("\n")
# set_breakpoints_old - set breakpoints as listed in input file.
def set_breakpoints_old(target, breakpoint_filename, file):
f = open(breakpoint_filename, "r")
lines = f.readlines()
for l in range(len(lines)):
c = lines[l].split()
# print "setting break point - ", c
bp = target.BreakpointCreateByLocation(str(c[0]), int(c[1]))
file.write("#Breakpoint ")
file.write(str(c[0]))
file.write(":")
file.write(str(c[1]))
file.write(" ")
file.write(str(bp.GetThreadID()))
file.write(":")
file.write(str(bp.GetID()))
file.write("\n")
f.close()
# stopeed_at_breakpoint - Return True if process is stopeed at a
# set_breakpoints - set breakpoints as listed in input file.
def set_breakpoints(target, breakpoint_filename, file):
f = open(breakpoint_filename, "r")
lines = f.readlines()
for l in range(len(lines)):
l2 = len(lines[l])
l3 = l2 - 1
# print "setting break point - ", lines[l][0:l3]
bp = target.BreakpointCreateByName(str(lines[l][0:l3]))
# print "setting break point - ", lines[l][0:l3],
# print " [", str(bp.GetThreadID()), ":", str(bp.GetID()), "]"
file.write("#Breakpoint ")
file.write(str(1))
file.write(":")
file.write(str(2))
file.write(" ")
file.write(str(bp.GetThreadID()))
file.write(":")
file.write(str(bp.GetID()))
file.write(" ")
file.write(str(lines[l][0:l3]))
file.write("\n")
f.close()
# stopeed_at_breakpoint - Return True if process is stopeed at a
# breakpoint.
def stopped_at_breakpoint(process):
# print "stopped"
if process.IsValid():
# print "stopped process"
state = process.GetState()
# print "stopped process", state
if state == lldb.eStateStopped:
# print "stopped process state is stopped"
thread = process.GetThreadAtIndex(0)
if thread.IsValid():
# print "thread is valid"
if thread.GetStopReason() == lldb.eStopReasonBreakpoint:
# print "thread stopped at breakpoint"
return True
return False
# 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
# print "Creating a target for '%s'" % sys.argv[1]
target = debugger.CreateTargetWithFileAndArch(sys.argv[1], lldb.LLDB_ARCH_DEFAULT)
if target.IsValid():
# print "target is valid"
file = open(str(sys.argv[3]), "w")
set_breakpoints(target, sys.argv[2], file)
# Launch the process. Since we specified synchronous mode, we won't return
# from this function until we hit the breakpoint at main
sberror = lldb.SBError()
process = target.LaunchSimple(None, None, None)
# Make sure the launch went ok
while stopped_at_breakpoint(process):
# print "stopped at a bp"
thread = process.GetThreadAtIndex(0)
# print "num of frames ", thread.GetNumFrames()
frame = thread.GetFrameAtIndex(0)
if not frame.IsValid():
for fi in range(thread.GetNumFrames()):
# print "checking frame no : ", fi
frame = thread.GetFrameAtIndex(fi)
if frame.IsValid():
fi = thread.GetNumFrames()
if frame.IsValid():
# #Print some simple frame info
##print frame
# print "frame is valid"
function = frame.GetFunction()
if function.IsValid():
fname = function.GetMangledName()
if fname is None:
fname = function.GetName()
# print "function : ",fname
line = frame.GetLineEntry().GetLine()
vars = frame.GetVariables(1, 0, 0, 0)
print_vars("#Argument ", vars, fname, line, file, frame, target, thread)
# vars = frame.GetVariables(0,1,0,0)
# print_vars ("#Variables ", vars, fname, line, file, frame, target, thread)
disable_bp(thread)
process.Continue()
file.close()
lldb.SBDebugger.Terminate()