Add an lldb wrapper script that implements gdb-compatible commands on top
authorAdrian Prantl <aprantl@apple.com>
Fri, 6 Sep 2013 18:10:44 +0000 (18:10 +0000)
committerAdrian Prantl <aprantl@apple.com>
Fri, 6 Sep 2013 18:10:44 +0000 (18:10 +0000)
of lldb. This will be the new default method for executing the tests in
this repository on Darwin.
There is also a related patch for llvm/utils/test_debuginfo.pl coming.

I also relaxed some of the checks to work with both gdb's and lldb's
output.

llvm-svn: 190185

debuginfo-tests/aggregate-indirect-arg.cpp
debuginfo-tests/llgdb.py [new file with mode: 0644]
debuginfo-tests/nested-struct.cpp
debuginfo-tests/sret.cpp

index f6b01b2..26c5714 100644 (file)
@@ -5,9 +5,9 @@
 // DEBUGGER: break 22
 // DEBUGGER: r
 // DEBUGGER: p v
-// CHECK: $1 = {
-// CHECK:  Data = 0x0, 
-// CHECK:  Kind = 2142
+// CHECK: ${{[0-9]+}} = {
+// CHECK-NEXT:  Data = 0x0{{,|(0+$)}}
+// CHECK-NEXT:  Kind = 2142
 
 class SVal {
 public:
diff --git a/debuginfo-tests/llgdb.py b/debuginfo-tests/llgdb.py
new file mode 100644 (file)
index 0000000..bfa5fb1
--- /dev/null
@@ -0,0 +1,137 @@
+#!/bin/env python
+"""
+A gdb-compatible frontend for lldb that implements just enough
+commands to run the tests in the debuginfo-tests repository with lldb.
+"""
+
+# ----------------------------------------------------------------------
+# Auto-detect lldb python module.
+import commands, platform, os,  sys
+try:
+    # Just try for LLDB in case PYTHONPATH is already correctly setup.
+    import lldb
+except ImportError:
+    lldb_python_dirs = list()
+    # lldb is not in the PYTHONPATH, try some defaults for the current platform.
+    platform_system = platform.system()
+    if platform_system == 'Darwin':
+        # 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')
+    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:
+                    import lldb
+                except ImportError:
+                    pass
+                else:
+                    print 'imported lldb from: "%s"' % (lldb_python_dir)
+                    success = True
+                    break
+    if not success:
+        print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
+        sys.exit(1)
+# ----------------------------------------------------------------------
+
+# Command line option handling.
+import argparse
+parser = argparse.ArgumentParser(description=__doc__)
+parser.add_argument('--quiet', '-q', action="store_true", help='ignored')
+parser.add_argument('-batch', action="store_true",
+                    help='exit after processing comand line')
+parser.add_argument('-n', action="store_true", help='ignore .lldb file')
+parser.add_argument('-x', dest='script', type=file, help='execute commands from file')
+parser.add_argument("target", help="the program to debug")
+args = parser.parse_args()
+
+
+# Create a new debugger instance.
+debugger = lldb.SBDebugger.Create()
+debugger.SkipLLDBInitFiles(args.n)
+
+# Don't return from lldb function calls until the process stops.
+debugger.SetAsync(False)
+
+# Create a target from a file and arch.
+target = debugger.CreateTargetWithFileAndArch(args.target, lldb.LLDB_ARCH_DEFAULT)
+
+if not target:
+    print "Could not create target", args.target
+    sys.exit(1)
+
+if not args.script:
+    print "Interactive mode is not implemented."
+    sys.exit(1)
+
+import re
+for command in args.script:
+    # Strip newline and whitespaces and split into words.
+    cmd = command[:-1].strip().split()
+    if not cmd:
+        continue
+
+    print '> %s'% command
+
+    try:
+        if re.match('^r|(run)$', cmd[0]):
+            error = lldb.SBError()
+            launchinfo = lldb.SBLaunchInfo([])
+            launchinfo.SetWorkingDirectory(os.getcwd())
+            process = target.Launch(launchinfo, error)
+            if not process or error.fail:
+                print error
+                state = process.GetState()
+                print "State = %d" % state
+                print "Could not launch process."
+                sys.exit(1)
+
+        elif re.match('^b|(break)$', cmd[0]) and len(cmd) == 2:
+            if re.match('[0-9]+', cmd[1]):
+                # b line
+                mainfile = target.FindFunctions('main')[0].compile_unit.file
+                print target.BreakpointCreateByLocation(mainfile, int(cmd[1]))
+            else:
+                # b file:line
+                file, line = cmd.split(':')
+                print target.BreakpointCreateByLocation(file, int(line))
+
+        elif re.match('^ptype$', cmd[0]) and len(cmd) == 2:
+            # GDB's ptype has multiple incarnations depending on its
+            # argument (global variable, function, type).  The definition
+            # here is for looking up the signature of a function and only
+            # if that fails it looks for a type with that name.
+            # Type lookup in LLDB would be "image lookup --type".
+            for elem in target.FindFunctions(cmd[1]):
+                print elem.function.type
+                continue
+            print target.FindFirstType(cmd[1])
+
+        elif re.match('^po$', cmd[0]) and len(cmd) > 1:
+            opts = lldb.SBExpressionOptions()
+            opts.SetFetchDynamicValue(True)
+            opts.SetCoerceResultToId(True)
+            print target.EvaluateExpression(' '.join(cmd[1:]), opts)
+
+        elif re.match('^p|(print)$', cmd[0]) and len(cmd) > 1:
+            opts = lldb.SBExpressionOptions()
+            print target.EvaluateExpression(' '.join(cmd[1:]), opts)
+
+        elif re.match('^q|(quit)$', cmd[0]):
+            sys.exit(0)
+
+        else:
+            print debugger.HandleCommand(' '.join(cmd))
+
+    except SystemExit, e: raise e
+    except:
+        print 'Could not handle the command "%s"' % ' '.join(cmd)
+
index 5a626c5..22f2344 100644 (file)
@@ -6,7 +6,7 @@
 // gdb crashes in such cases.
 
 // DEBUGGER: ptype foo
-// CHECK: type = int (void)
+// CHECK: int (void)
 
 int foo() {
   struct Local {
index 1903cdd..6405bde 100644 (file)
@@ -5,9 +5,10 @@
 // DEBUGGER: break 62
 // DEBUGGER: r
 // DEBUGGER: p a
-// CHECK: $1 = {
-// CHECK:  _vptr$A =
-// CHECK:  m_int = 12
+// CHECK: ${{[0-9]+}} = {
+// LLDB does not print artificial members.
+// CHECK-NEXT:  {{(_vptr\$A =)|(m_int = 12)}}
+// CHECK-NEXT:  {{(m_int = 12)|(})}}
 
 class A
 {