summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohnny Chen <johnny.chen@apple.com>2011-05-12 00:32:41 +0000
committerJohnny Chen <johnny.chen@apple.com>2011-05-12 00:32:41 +0000
commitad7372c5382cb37ce9f289d706ce6ba25c71262e (patch)
tree638f910b91580e150352a6d5ccc0b41273ff9e65
parent2da484f225181d6301db2034c2e4526ef14aa7c8 (diff)
downloadbcm5719-llvm-ad7372c5382cb37ce9f289d706ce6ba25c71262e.tar.gz
bcm5719-llvm-ad7372c5382cb37ce9f289d706ce6ba25c71262e.zip
Add two utility functions:
o get_parent_frame(frame) o get_args_as_string(frame) to lldbutil.py and create TestFrameUtils.py to exercise the utils. Plus re-arrange the test/python_api/lldbutil to have three directories for testing iteration, process stack traces, and the just added frame utils. llvm-svn: 131213
-rw-r--r--lldb/test/lldbutil.py31
-rw-r--r--lldb/test/python_api/lldbutil/frame/Makefile6
-rw-r--r--lldb/test/python_api/lldbutil/frame/TestFrameUtils.py62
-rw-r--r--lldb/test/python_api/lldbutil/frame/main.c47
-rw-r--r--lldb/test/python_api/lldbutil/iter/Makefile (renamed from lldb/test/python_api/lldbutil/Makefile)2
-rw-r--r--lldb/test/python_api/lldbutil/iter/TestLLDBIterator.py (renamed from lldb/test/python_api/lldbutil/TestLLDBIterator.py)2
-rw-r--r--lldb/test/python_api/lldbutil/iter/TestRegistersIterator.py (renamed from lldb/test/python_api/lldbutil/TestRegistersIterator.py)2
-rw-r--r--lldb/test/python_api/lldbutil/iter/main.cpp (renamed from lldb/test/python_api/lldbutil/main.cpp)0
-rw-r--r--lldb/test/python_api/lldbutil/process/Makefile6
-rw-r--r--lldb/test/python_api/lldbutil/process/TestPrintStackTraces.py (renamed from lldb/test/python_api/lldbutil/TestPrintStackTraces.py)2
-rw-r--r--lldb/test/python_api/lldbutil/process/main.cpp128
11 files changed, 284 insertions, 4 deletions
diff --git a/lldb/test/lldbutil.py b/lldb/test/lldbutil.py
index da5ecc3e736..04f98be6b2d 100644
--- a/lldb/test/lldbutil.py
+++ b/lldb/test/lldbutil.py
@@ -409,6 +409,37 @@ def print_stacktraces(process, string_buffer = False):
# Utility functions related to Frames
# ===================================
+def get_parent_frame(frame):
+ """
+ Returns the parent frame of the input frame object; None if not available.
+ """
+ thread = frame.GetThread()
+ parent_found = False
+ for f in thread:
+ if parent_found:
+ return f
+ if f.GetFrameID() == frame.GetFrameID():
+ parent_found = True
+
+ # If we reach here, no parent has been found, return None.
+ return None
+
+def get_args_as_string(frame):
+ """
+ Returns the args of the input frame object as a string.
+ """
+ # arguments => True
+ # locals => False
+ # statics => False
+ # in_scope_only => True
+ vars = frame.GetVariables(True, False, False, True) # type of SBValueList
+ args = [] # list of strings
+ for var in vars:
+ args.append("(%s)%s=%s" % (var.GetTypeName(),
+ var.GetName(),
+ var.GetValue(frame)))
+ return "%s(%s)" % (frame.GetFunction().GetName(), ", ".join(args))
+
def print_registers(frame, string_buffer = False):
"""Prints all the register sets of the frame."""
diff --git a/lldb/test/python_api/lldbutil/frame/Makefile b/lldb/test/python_api/lldbutil/frame/Makefile
new file mode 100644
index 00000000000..69b74b5d753
--- /dev/null
+++ b/lldb/test/python_api/lldbutil/frame/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+MAKE_DSYM :=NO
+
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/python_api/lldbutil/frame/TestFrameUtils.py b/lldb/test/python_api/lldbutil/frame/TestFrameUtils.py
new file mode 100644
index 00000000000..cd4ba09fac1
--- /dev/null
+++ b/lldb/test/python_api/lldbutil/frame/TestFrameUtils.py
@@ -0,0 +1,62 @@
+"""
+Test utility functions for the frame object.
+"""
+
+import os
+import unittest2
+import lldb
+from lldbtest import *
+
+class FrameUtilsTestCase(TestBase):
+
+ mydir = "python_api/lldbutil/frame"
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line number to break inside main().
+ self.line = line_number('main.c',
+ "// Find the line number here.")
+
+ def test_frame_utils(self):
+ """Test utility functions for the frame object."""
+ self.buildDefault(dictionary={'C_SOURCES': 'main.c'})
+ self.frame_utils()
+
+ def frame_utils(self):
+ exe = os.path.join(os.getcwd(), "a.out")
+
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target.IsValid(), VALID_TARGET)
+
+ breakpoint = target.BreakpointCreateByLocation("main.c", self.line)
+ self.assertTrue(breakpoint.IsValid(), VALID_BREAKPOINT)
+
+ # Now launch the process, and do not stop at entry point.
+ self.process = target.LaunchSimple(None, None, os.getcwd())
+
+ if not self.process.IsValid():
+ self.fail("SBTarget.LaunchProcess() failed")
+ self.assertTrue(self.process.GetState() == lldb.eStateStopped,
+ PROCESS_STOPPED)
+
+ import lldbutil
+ thread = lldbutil.get_stopped_thread(self.process, lldb.eStopReasonBreakpoint)
+ frame0 = thread.GetFrameAtIndex(0)
+ frame1 = thread.GetFrameAtIndex(1)
+ parent = lldbutil.get_parent_frame(frame0)
+ self.assertTrue(parent.IsValid() and parent.GetFrameID() == frame1.GetFrameID())
+ frame0_args = lldbutil.get_args_as_string(frame0)
+ parent_args = lldbutil.get_args_as_string(parent)
+ self.assertTrue(frame0_args and parent_args)
+ if self.TraceOn():
+ lldbutil.print_stacktrace(thread)
+ print "Current frame: %s" % frame0_args
+ print "Parent frame: %s" % parent_args
+
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
diff --git a/lldb/test/python_api/lldbutil/frame/main.c b/lldb/test/python_api/lldbutil/frame/main.c
new file mode 100644
index 00000000000..e6eeef5b46d
--- /dev/null
+++ b/lldb/test/python_api/lldbutil/frame/main.c
@@ -0,0 +1,47 @@
+//===-- main.c --------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <stdio.h>
+
+int a(int);
+int b(int);
+int c(int);
+
+int a(int val)
+{
+ if (val <= 1)
+ return b(val);
+ else if (val >= 3)
+ return c(val);
+
+ return val;
+}
+
+int b(int val)
+{
+ return c(val);
+}
+
+int c(int val)
+{
+ return val + 3; // Find the line number here.
+}
+
+int main (int argc, char const *argv[])
+{
+ int A1 = a(1); // a(1) -> b(1) -> c(1)
+ printf("a(1) returns %d\n", A1);
+
+ int B2 = b(2); // b(2) -> c(2)
+ printf("b(2) returns %d\n", B2);
+
+ int A3 = a(3); // a(3) -> c(3)
+ printf("a(3) returns %d\n", A3);
+
+ return 0;
+}
diff --git a/lldb/test/python_api/lldbutil/Makefile b/lldb/test/python_api/lldbutil/iter/Makefile
index 86af2f4bc70..312d3fec3e1 100644
--- a/lldb/test/python_api/lldbutil/Makefile
+++ b/lldb/test/python_api/lldbutil/iter/Makefile
@@ -1,4 +1,4 @@
-LEVEL = ../../make
+LEVEL = ../../../make
CXX_SOURCES := main.cpp
MAKE_DSYM :=NO
diff --git a/lldb/test/python_api/lldbutil/TestLLDBIterator.py b/lldb/test/python_api/lldbutil/iter/TestLLDBIterator.py
index 51e852e9644..568048b0cdf 100644
--- a/lldb/test/python_api/lldbutil/TestLLDBIterator.py
+++ b/lldb/test/python_api/lldbutil/iter/TestLLDBIterator.py
@@ -10,7 +10,7 @@ from lldbtest import *
class LLDBIteratorTestCase(TestBase):
- mydir = "python_api/lldbutil"
+ mydir = "python_api/lldbutil/iter"
def setUp(self):
# Call super's setUp().
diff --git a/lldb/test/python_api/lldbutil/TestRegistersIterator.py b/lldb/test/python_api/lldbutil/iter/TestRegistersIterator.py
index ade237ebcad..bd20b7e7e05 100644
--- a/lldb/test/python_api/lldbutil/TestRegistersIterator.py
+++ b/lldb/test/python_api/lldbutil/iter/TestRegistersIterator.py
@@ -10,7 +10,7 @@ from lldbtest import *
class RegistersIteratorTestCase(TestBase):
- mydir = "python_api/lldbutil"
+ mydir = "python_api/lldbutil/iter"
def setUp(self):
# Call super's setUp().
diff --git a/lldb/test/python_api/lldbutil/main.cpp b/lldb/test/python_api/lldbutil/iter/main.cpp
index c7dcba4884c..c7dcba4884c 100644
--- a/lldb/test/python_api/lldbutil/main.cpp
+++ b/lldb/test/python_api/lldbutil/iter/main.cpp
diff --git a/lldb/test/python_api/lldbutil/process/Makefile b/lldb/test/python_api/lldbutil/process/Makefile
new file mode 100644
index 00000000000..312d3fec3e1
--- /dev/null
+++ b/lldb/test/python_api/lldbutil/process/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+MAKE_DSYM :=NO
+
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/python_api/lldbutil/TestPrintStackTraces.py b/lldb/test/python_api/lldbutil/process/TestPrintStackTraces.py
index cdd8c41b1b2..32ff8acf406 100644
--- a/lldb/test/python_api/lldbutil/TestPrintStackTraces.py
+++ b/lldb/test/python_api/lldbutil/process/TestPrintStackTraces.py
@@ -10,7 +10,7 @@ from lldbtest import *
class ThreadsStackTracesTestCase(TestBase):
- mydir = "python_api/lldbutil"
+ mydir = "python_api/lldbutil/process"
def setUp(self):
# Call super's setUp().
diff --git a/lldb/test/python_api/lldbutil/process/main.cpp b/lldb/test/python_api/lldbutil/process/main.cpp
new file mode 100644
index 00000000000..c7dcba4884c
--- /dev/null
+++ b/lldb/test/python_api/lldbutil/process/main.cpp
@@ -0,0 +1,128 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C includes
+#include <pthread.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+pthread_t g_thread_1 = NULL;
+pthread_t g_thread_2 = NULL;
+pthread_t g_thread_3 = NULL;
+
+typedef enum {
+ eGet,
+ eAssign,
+ eClearBits
+} MaskAction;
+
+uint32_t mask_access (MaskAction action, uint32_t mask = 0);
+
+uint32_t
+mask_access (MaskAction action, uint32_t mask)
+{
+ static pthread_mutex_t g_mask_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static uint32_t g_mask = 0;
+ ::pthread_mutex_lock (&g_mask_mutex);
+ switch (action)
+ {
+ case eGet:
+ break;
+
+ case eAssign:
+ g_mask |= mask;
+ break;
+
+ case eClearBits:
+ g_mask &= ~mask;
+ break;
+ }
+ uint32_t new_mask = g_mask;
+ ::pthread_mutex_unlock (&g_mask_mutex);
+ return new_mask;
+}
+
+void *
+thread_func (void *arg)
+{
+ uint32_t thread_index = *((uint32_t *)arg);
+ uint32_t thread_mask = (1u << (thread_index));
+ printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index);
+
+ while (mask_access(eGet) & thread_mask)
+ {
+ // random micro second sleep from zero to 3 seconds
+ int usec = ::rand() % 3000000;
+ printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec);
+ ::usleep (usec);
+ printf ("%s (thread = %u) after usleep ...\n", __FUNCTION__, thread_index); // Set break point at this line.
+ }
+ printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index);
+ return NULL;
+}
+
+
+int main (int argc, char const *argv[])
+{
+ int err;
+ void *thread_result = NULL;
+ uint32_t thread_index_1 = 1;
+ uint32_t thread_index_2 = 2;
+ uint32_t thread_index_3 = 3;
+ uint32_t thread_mask_1 = (1u << thread_index_1);
+ uint32_t thread_mask_2 = (1u << thread_index_2);
+ uint32_t thread_mask_3 = (1u << thread_index_3);
+
+ // Make a mask that will keep all threads alive
+ mask_access (eAssign, thread_mask_1 | thread_mask_2 | thread_mask_3); // And that line.
+
+ // Create 3 threads
+ err = ::pthread_create (&g_thread_1, NULL, thread_func, &thread_index_1);
+ err = ::pthread_create (&g_thread_2, NULL, thread_func, &thread_index_2);
+ err = ::pthread_create (&g_thread_3, NULL, thread_func, &thread_index_3);
+
+ char line[64];
+ while (mask_access(eGet) != 0)
+ {
+ printf ("Enter thread index to kill or ENTER for all:\n");
+ fflush (stdout);
+ // Kill threads by index, or ENTER for all threads
+
+ if (fgets (line, sizeof(line), stdin))
+ {
+ if (line[0] == '\n' || line[0] == '\r' || line[0] == '\0')
+ {
+ printf ("Exiting all threads...\n");
+ break;
+ }
+ int32_t index = strtoul (line, NULL, 0);
+ switch (index)
+ {
+ case 1: mask_access (eClearBits, thread_mask_1); break;
+ case 2: mask_access (eClearBits, thread_mask_2); break;
+ case 3: mask_access (eClearBits, thread_mask_3); break;
+ }
+ continue;
+ }
+
+ break;
+ }
+
+ // Clear all thread bits to they all exit
+ mask_access (eClearBits, UINT32_MAX);
+
+ // Join all of our threads
+ err = ::pthread_join (g_thread_1, &thread_result);
+ err = ::pthread_join (g_thread_2, &thread_result);
+ err = ::pthread_join (g_thread_3, &thread_result);
+
+ return 0;
+}
OpenPOWER on IntegriCloud