[Lldb-commits] [lldb] r245838 - Make TestCreateDuringInstructionStep linux-specific
Pavel Labath via lldb-commits
lldb-commits at lists.llvm.org
Mon Aug 24 06:23:48 PDT 2015
Author: labath
Date: Mon Aug 24 08:23:48 2015
New Revision: 245838
URL: http://llvm.org/viewvc/llvm-project?rev=245838&view=rev
Log:
Make TestCreateDuringInstructionStep linux-specific
Summary:
There were a number of issues about the way I have designed this test originally:
- it relied on single-stepping through large parts of code, which was slow and unreliable
- the threading libraries interfered with the exact thing we wanted to test
For this reason, I have rewritted the test using low-level linux api, which allows the test to be
much more focused. The functionality for other platforms will need to be tested separately.
Reviewers: tberghammer
Subscribers: tberghammer, danalbert, srhines, lldb-commits
Differential Revision: http://reviews.llvm.org/D12280
Added:
lldb/trunk/test/linux/thread/
lldb/trunk/test/linux/thread/create_during_instruction_step/
lldb/trunk/test/linux/thread/create_during_instruction_step/Makefile
- copied, changed from r245831, lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile
lldb/trunk/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py
- copied, changed from r245831, lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py
lldb/trunk/test/linux/thread/create_during_instruction_step/main.cpp
Removed:
lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile
lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py
lldb/trunk/test/functionalities/thread/create_during_instruction_step/main.cpp
Removed: lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile?rev=245837&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile (original)
+++ lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile (removed)
@@ -1,5 +0,0 @@
-LEVEL = ../../../make
-
-CXX_SOURCES := main.cpp
-ENABLE_THREADS := YES
-include $(LEVEL)/Makefile.rules
Removed: lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py?rev=245837&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py (original)
+++ lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py (removed)
@@ -1,91 +0,0 @@
-"""
-This tests that we do not lose control of the inferior, while doing an instruction-level step
-over a thread creation instruction.
-"""
-
-import os
-import unittest2
-import lldb
-from lldbtest import *
-import lldbutil
-
-class CreateDuringInstructionStepTestCase(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
- # Find the line numbers to break and continue.
- self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
-
- @dsym_test
- def test_step_inst_with_dsym(self):
- self.buildDsym(dictionary=self.getBuildFlags())
- self.create_during_step_inst_test()
-
- @dwarf_test
- @skipIfTargetAndroid(archs=['aarch64'])
- @expectedFailureAndroid("llvm.org/pr23944", archs=['aarch64']) # We are unable to step through std::thread::_M_start_thread
- def test_step_inst_with_dwarf(self):
- self.buildDwarf(dictionary=self.getBuildFlags())
- self.create_during_step_inst_test()
-
- def create_during_step_inst_test(self):
- exe = os.path.join(os.getcwd(), "a.out")
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target and target.IsValid(), "Target is valid")
-
- # This should create a breakpoint in the stepping thread.
- self.bp_num = lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=-1)
-
- # Run the program.
- process = target.LaunchSimple(None, None, self.get_process_working_directory())
- self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
-
- # The stop reason of the thread should be breakpoint.
- self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- self.assertEqual(lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint).IsValid(), 1,
- STOPPED_DUE_TO_BREAKPOINT)
-
- # Get the number of threads
- num_threads = process.GetNumThreads()
-
- # Make sure we see only one threads
- self.assertEqual(num_threads, 1, 'Number of expected threads and actual threads do not match.')
-
- thread = process.GetThreadAtIndex(0)
- self.assertTrue(thread and thread.IsValid(), "Thread is valid")
-
- # Keep stepping until we see the thread creation
- while process.GetNumThreads() < 2:
- # This skips some functions we have trouble stepping into. Testing stepping
- # through these is not the purpose of this test. We just want to find the
- # instruction, which creates the thread.
- if thread.GetFrameAtIndex(0).GetFunctionName() in [
- '__sync_fetch_and_add_4', # Android arm: unable to set a breakpoint for software single-step
- 'pthread_mutex_lock', # Android arm: function contains atomic instruction sequences
- 'pthread_mutex_unlock' # Android arm: function contains atomic instruction sequences
- ]:
- thread.StepOut()
- else:
- thread.StepInstruction(False)
- self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- self.assertEqual(thread.GetStopReason(), lldb.eStopReasonPlanComplete, "Step operation succeeded")
- if self.TraceOn():
- self.runCmd("disassemble --pc")
-
- if self.TraceOn():
- self.runCmd("thread list")
-
- # We have successfully caught thread creation. Now just run to completion
- process.Continue()
-
- # At this point, the inferior process should have exited.
- self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED)
-
-if __name__ == '__main__':
- import atexit
- lldb.SBDebugger.Initialize()
- atexit.register(lambda: lldb.SBDebugger.Terminate())
- unittest2.main()
Removed: lldb/trunk/test/functionalities/thread/create_during_instruction_step/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/create_during_instruction_step/main.cpp?rev=245837&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/thread/create_during_instruction_step/main.cpp (original)
+++ lldb/trunk/test/functionalities/thread/create_during_instruction_step/main.cpp (removed)
@@ -1,36 +0,0 @@
-//===-- main.cpp ------------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <atomic>
-#include <thread>
-
-std::atomic<bool> flag(false);
-
-void do_nothing()
-{
- while (flag)
- ;
-}
-
-int main ()
-{
- // Instruction-level stepping over a creation of the first thread takes a very long time, so
- // we give the threading machinery a chance to initialize all its data structures.
- // This way, stepping over the second thread will be much faster.
- std::thread dummy(do_nothing);
- dummy.join();
-
- // Make sure the new thread does not exit before we get a chance to notice the main thread stopped
- flag = true;
-
- std::thread thread(do_nothing); // Set breakpoint here
- flag = false; // Release the new thread.
- thread.join();
- return 0;
-}
Copied: lldb/trunk/test/linux/thread/create_during_instruction_step/Makefile (from r245831, lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile)
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/linux/thread/create_during_instruction_step/Makefile?p2=lldb/trunk/test/linux/thread/create_during_instruction_step/Makefile&p1=lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile&r1=245831&r2=245838&rev=245838&view=diff
==============================================================================
(empty)
Copied: lldb/trunk/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py (from r245831, lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py)
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py?p2=lldb/trunk/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py&p1=lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py&r1=245831&r2=245838&rev=245838&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py (original)
+++ lldb/trunk/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py Mon Aug 24 08:23:48 2015
@@ -16,8 +16,6 @@ class CreateDuringInstructionStepTestCas
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
- # Find the line numbers to break and continue.
- self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
@dsym_test
def test_step_inst_with_dsym(self):
@@ -25,8 +23,6 @@ class CreateDuringInstructionStepTestCas
self.create_during_step_inst_test()
@dwarf_test
- @skipIfTargetAndroid(archs=['aarch64'])
- @expectedFailureAndroid("llvm.org/pr23944", archs=['aarch64']) # We are unable to step through std::thread::_M_start_thread
def test_step_inst_with_dwarf(self):
self.buildDwarf(dictionary=self.getBuildFlags())
self.create_during_step_inst_test()
@@ -37,7 +33,8 @@ class CreateDuringInstructionStepTestCas
self.assertTrue(target and target.IsValid(), "Target is valid")
# This should create a breakpoint in the stepping thread.
- self.bp_num = lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=-1)
+ breakpoint = target.BreakpointCreateByName("main")
+ self.assertTrue(breakpoint and breakpoint.IsValid(), "Breakpoint is valid")
# Run the program.
process = target.LaunchSimple(None, None, self.get_process_working_directory())
@@ -45,31 +42,19 @@ class CreateDuringInstructionStepTestCas
# The stop reason of the thread should be breakpoint.
self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- self.assertEqual(lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint).IsValid(), 1,
- STOPPED_DUE_TO_BREAKPOINT)
- # Get the number of threads
- num_threads = process.GetNumThreads()
+ threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint)
+ self.assertEquals(len(threads), 1, STOPPED_DUE_TO_BREAKPOINT)
- # Make sure we see only one threads
- self.assertEqual(num_threads, 1, 'Number of expected threads and actual threads do not match.')
-
- thread = process.GetThreadAtIndex(0)
+ thread = threads[0]
self.assertTrue(thread and thread.IsValid(), "Thread is valid")
+ # Make sure we see only one threads
+ self.assertEqual(process.GetNumThreads(), 1, 'Number of expected threads and actual threads do not match.')
+
# Keep stepping until we see the thread creation
while process.GetNumThreads() < 2:
- # This skips some functions we have trouble stepping into. Testing stepping
- # through these is not the purpose of this test. We just want to find the
- # instruction, which creates the thread.
- if thread.GetFrameAtIndex(0).GetFunctionName() in [
- '__sync_fetch_and_add_4', # Android arm: unable to set a breakpoint for software single-step
- 'pthread_mutex_lock', # Android arm: function contains atomic instruction sequences
- 'pthread_mutex_unlock' # Android arm: function contains atomic instruction sequences
- ]:
- thread.StepOut()
- else:
- thread.StepInstruction(False)
+ thread.StepInstruction(False)
self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
self.assertEqual(thread.GetStopReason(), lldb.eStopReasonPlanComplete, "Step operation succeeded")
if self.TraceOn():
Added: lldb/trunk/test/linux/thread/create_during_instruction_step/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/linux/thread/create_during_instruction_step/main.cpp?rev=245838&view=auto
==============================================================================
--- lldb/trunk/test/linux/thread/create_during_instruction_step/main.cpp (added)
+++ lldb/trunk/test/linux/thread/create_during_instruction_step/main.cpp Mon Aug 24 08:23:48 2015
@@ -0,0 +1,55 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// This file deliberately uses low level linux-specific API for thread creation because:
+// - instruction-stepping over thread creation using higher-level functions was very slow
+// - it was also unreliable due to single-stepping bugs unrelated to this test
+// - some threading libraries do not create or destroy threads when we would expect them to
+
+#include <sched.h>
+
+#include <atomic>
+#include <cstdio>
+
+enum { STACK_SIZE = 0x2000 };
+
+static uint8_t child_stack[STACK_SIZE];
+
+pid_t child_tid;
+
+std::atomic<bool> flag(false);
+
+int thread_main(void *)
+{
+ while (! flag) // Make sure the thread does not exit prematurely
+ ;
+
+ return 0;
+}
+
+int main ()
+{
+ int ret = clone(thread_main,
+ child_stack + STACK_SIZE/2, // Don't care whether the stack grows up or down,
+ // just point to the middle
+ CLONE_CHILD_CLEARTID | CLONE_FILES | CLONE_FS | CLONE_PARENT_SETTID | CLONE_SETTLS |
+ CLONE_SIGHAND | CLONE_SYSVSEM | CLONE_THREAD | CLONE_VM,
+ nullptr, // thread_main argument
+ &child_tid);
+
+ if (ret == -1)
+ {
+ perror("clone");
+ return 1;
+ }
+
+ flag = true;
+
+ return 0;
+}
More information about the lldb-commits
mailing list