[Lldb-commits] [lldb] r182428 - Added a test case that verifies that LLDB can debug across a process exec'ing itself into a new program. This currently is only enabled for Darwin since we exec from 64 bit to 32 bit and vice versa for 'x86_64' targets.
Greg Clayton
gclayton at apple.com
Tue May 21 14:55:59 PDT 2013
Author: gclayton
Date: Tue May 21 16:55:59 2013
New Revision: 182428
URL: http://llvm.org/viewvc/llvm-project?rev=182428&view=rev
Log:
Added a test case that verifies that LLDB can debug across a process exec'ing itself into a new program. This currently is only enabled for Darwin since we exec from 64 bit to 32 bit and vice versa for 'x86_64' targets.
This can easily be adapted for linux and other platforms, but I didn't want to break any buildbots by assuming it will work.
Added:
lldb/trunk/test/functionalities/exec/
lldb/trunk/test/functionalities/exec/Makefile
lldb/trunk/test/functionalities/exec/TestExec.py
lldb/trunk/test/functionalities/exec/main.cpp
Modified:
lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
lldb/trunk/source/Target/Process.cpp
lldb/trunk/source/Target/Thread.cpp
lldb/trunk/source/Utility/StringExtractor.h
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=182428&r1=182427&r2=182428&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Tue May 21 16:55:59 2013
@@ -1005,15 +1005,6 @@ ProcessGDBRemote::DidAttach ()
DidLaunchOrAttach ();
}
-void
-ProcessGDBRemote::DoDidExec ()
-{
- // The process exec'ed itself, figure out the dynamic loader, etc...
- BuildDynamicRegisterInfo (true);
- m_gdb_comm.ResetDiscoverableSettings();
-}
-
-
Error
ProcessGDBRemote::WillResume ()
@@ -1354,15 +1345,8 @@ ProcessGDBRemote::SetThreadStopInfo (Str
// register info before we lookup and threads and populate the expedited
// register values so we need to know this right away so we can cleanup
// and update our registers.
- const bool did_exec = stop_packet.GetStringRef().find(";reason:exec;") != std::string::npos;
-
- if (did_exec)
- {
- m_thread_list_real.Clear();
- m_thread_list.Clear();
- }
-
- if (GetStopID() == 0 || did_exec)
+ const uint32_t stop_id = GetStopID();
+ if (stop_id == 0)
{
// Our first stop, make sure we have a process ID, and also make
// sure we know about our registers
@@ -1519,6 +1503,7 @@ ProcessGDBRemote::SetThreadStopInfo (Str
else
{
bool handled = false;
+ bool did_exec = false;
if (!reason.empty())
{
if (reason.compare("trace") == 0)
@@ -1566,6 +1551,7 @@ ProcessGDBRemote::SetThreadStopInfo (Str
}
else if (reason.compare("exec") == 0)
{
+ did_exec = true;
thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp));
handled = true;
}
@@ -1898,6 +1884,26 @@ ProcessGDBRemote::DoDestroy ()
return error;
}
+void
+ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)
+{
+ lldb_private::Mutex::Locker locker (m_last_stop_packet_mutex);
+ const bool did_exec = response.GetStringRef().find(";reason:exec;") != std::string::npos;
+ if (did_exec)
+ {
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf ("ProcessGDBRemote::SetLastStopPacket () - detected exec");
+
+ m_thread_list_real.Clear();
+ m_thread_list.Clear();
+ BuildDynamicRegisterInfo (true);
+ m_gdb_comm.ResetDiscoverableSettings();
+ }
+ m_last_stop_packet = response;
+}
+
+
//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=182428&r1=182427&r2=182428&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Tue May 21 16:55:59 2013
@@ -114,9 +114,6 @@ public:
virtual void
DidAttach ();
- virtual void
- DoDidExec ();
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -289,11 +286,7 @@ protected:
BuildDynamicRegisterInfo (bool force);
void
- SetLastStopPacket (const StringExtractorGDBRemote &response)
- {
- lldb_private::Mutex::Locker locker (m_last_stop_packet_mutex);
- m_last_stop_packet = response;
- }
+ SetLastStopPacket (const StringExtractorGDBRemote &response);
//------------------------------------------------------------------
/// Broadcaster event bits definitions.
Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=182428&r1=182427&r2=182428&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Tue May 21 16:55:59 2013
@@ -5588,8 +5588,6 @@ Process::DidExec ()
m_allocated_memory_cache.Clear();
m_language_runtimes.clear();
m_thread_list.DiscardThreadPlans();
- m_thread_list.Clear();
- m_thread_list_real.Clear();
m_memory_cache.Clear(true);
DoDidExec();
CompleteAttach ();
Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=182428&r1=182427&r2=182428&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Tue May 21 16:55:59 2013
@@ -442,6 +442,9 @@ Thread::SetStopInfo (const lldb::StopInf
m_stop_info_stop_id = process_sp->GetStopID();
else
m_stop_info_stop_id = UINT32_MAX;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf("%p: tid = 0x%llx: stop info = %s (stop_id = %u)\n", this, GetID(), stop_info_sp ? stop_info_sp->GetDescription() : "<NULL>", m_stop_info_stop_id);
}
void
Modified: lldb/trunk/source/Utility/StringExtractor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/StringExtractor.h?rev=182428&r1=182427&r2=182428&view=diff
==============================================================================
--- lldb/trunk/source/Utility/StringExtractor.h (original)
+++ lldb/trunk/source/Utility/StringExtractor.h Tue May 21 16:55:59 2013
@@ -73,6 +73,12 @@ public:
return m_packet;
}
+ const std::string &
+ GetStringRef () const
+ {
+ return m_packet;
+ }
+
bool
Empty()
{
Added: lldb/trunk/test/functionalities/exec/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/exec/Makefile?rev=182428&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/exec/Makefile (added)
+++ lldb/trunk/test/functionalities/exec/Makefile Tue May 21 16:55:59 2013
@@ -0,0 +1,5 @@
+LEVEL = ../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
Added: lldb/trunk/test/functionalities/exec/TestExec.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/exec/TestExec.py?rev=182428&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/exec/TestExec.py (added)
+++ lldb/trunk/test/functionalities/exec/TestExec.py Tue May 21 16:55:59 2013
@@ -0,0 +1,121 @@
+"""
+Test some lldb command abbreviations.
+"""
+import commands
+import lldb
+import os
+import time
+import unittest2
+from lldbtest import *
+import lldbutil
+
+def execute_command (command):
+ print '%% %s' % (command)
+ (exit_status, output) = commands.getstatusoutput (command)
+ if output:
+ print output
+ print 'status = %u' % (exit_status)
+ return exit_status
+
+class ExecTestCase(TestBase):
+
+ mydir = os.path.join("functionalities", "exec")
+
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dsym_test
+ def test_with_dsym (self):
+ if self.getArchitecture() == 'x86_64':
+ source = os.path.join (os.getcwd(), "main.cpp")
+ o_file = os.path.join (os.getcwd(), "main.o")
+ execute_command ("'%s' -g -O0 -arch i386 -arch x86_64 '%s' -c -o '%s'" % (os.environ["CC"], source, o_file))
+ execute_command ("'%s' -g -O0 -arch i386 -arch x86_64 '%s'" % (os.environ["CC"], o_file))
+ else:
+ self.buildDsym()
+ self.do_test ()
+
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dwarf_test
+ def test_with_dwarf (self):
+ if self.getArchitecture() == 'x86_64':
+ source = os.path.join (os.getcwd(), "main.cpp")
+ o_file = os.path.join (os.getcwd(), "main.o")
+ dsym_path = os.path.join (os.getcwd(), "a.out.dSYM")
+ execute_command ("'%s' -g -O0 -arch i386 -arch x86_64 '%s' -c -o '%s'" % (os.environ["CC"], source, o_file))
+ execute_command ("'%s' -g -O0 -arch i386 -arch x86_64 '%s'" % (os.environ["CC"], o_file))
+ execute_command ("rm -rf '%s'" % (dsym_path))
+ else:
+ self.buildDwarf()
+ self.do_test ()
+
+ def do_test (self):
+ exe = os.path.join (os.getcwd(), "a.out")
+
+ # Create the target
+ target = self.dbg.CreateTarget(exe)
+
+ print target
+ # Create any breakpoints we need
+ breakpoint = target.BreakpointCreateBySourceRegex ('Set breakpoint 1 here', lldb.SBFileSpec ("main.cpp", False))
+ print breakpoint
+ self.assertTrue(breakpoint, VALID_BREAKPOINT)
+
+ # Launch the process
+ process = target.LaunchSimple(None, None, os.getcwd())
+ self.assertTrue(process, PROCESS_IS_VALID)
+
+ for i in range(6):
+ # The stop reason of the thread should be breakpoint.
+ self.assertTrue(process.GetState() == lldb.eStateStopped,
+ STOPPED_DUE_TO_BREAKPOINT)
+
+ thread = process.GetThreadAtIndex (0)
+
+ self.assertTrue (thread.IsValid(),
+ "Process stopped at 'main' should have a valid thread");
+
+ stop_reason = thread.GetStopReason()
+
+ print 'stop_reason = %u' % (stop_reason)
+
+ print thread
+ for frame in thread:
+ print frame
+
+ self.assertTrue (stop_reason == lldb.eStopReasonBreakpoint,
+ "Thread in process stopped in 'main' should have a stop reason of eStopReasonBreakpoint");
+
+ # Run and we should stop due to exec
+ process.Continue()
+
+ print process
+ self.assertTrue(process.GetState() == lldb.eStateStopped,
+ "Process should be stopped at __dyld_start")
+
+ thread = process.GetThreadAtIndex (0)
+
+ self.assertTrue (thread.IsValid(),
+ "Process stopped at exec should have a valid thread");
+
+ print thread
+ for frame in thread:
+ print frame
+
+ stop_reason = thread.GetStopReason()
+
+ print 'stop_reason = %u' % (stop_reason)
+
+ self.assertTrue (stop_reason == lldb.eStopReasonExec,
+ "Thread in process stopped on exec should have a stop reason of eStopReasonExec");
+
+ # Run and we should stop at breakpoint in main after exec
+ process.Continue()
+
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
+
Added: lldb/trunk/test/functionalities/exec/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/exec/main.cpp?rev=182428&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/exec/main.cpp (added)
+++ lldb/trunk/test/functionalities/exec/main.cpp Tue May 21 16:55:59 2013
@@ -0,0 +1,94 @@
+#include <errno.h>
+#include <mach/mach.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <spawn.h>
+#include <unistd.h>
+
+static void
+exit_with_errno (int err, const char *prefix)
+{
+ if (err)
+ {
+ fprintf (stderr,
+ "%s%s",
+ prefix ? prefix : "",
+ strerror(err));
+ exit (err);
+ }
+}
+
+static pid_t
+spawn_process (const char **argv,
+ const char **envp,
+ cpu_type_t cpu_type,
+ int &err)
+{
+ pid_t pid = 0;
+
+ const posix_spawn_file_actions_t *file_actions = NULL;
+ posix_spawnattr_t attr;
+ err = posix_spawnattr_init (&attr);
+ if (err)
+ return pid;
+
+ short flags = POSIX_SPAWN_SETEXEC | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
+ err = posix_spawnattr_setflags (&attr, flags);
+ if (err == 0)
+ {
+ // Use the default signal masks
+ sigset_t no_signals;
+ sigset_t all_signals;
+ sigemptyset (&no_signals);
+ sigfillset (&all_signals);
+ posix_spawnattr_setsigmask(&attr, &no_signals);
+ posix_spawnattr_setsigdefault(&attr, &all_signals);
+
+ if (cpu_type != 0)
+ {
+ size_t ocount = 0;
+ err = posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount);
+ }
+
+ if (err == 0)
+ {
+ err = posix_spawn (&pid,
+ argv[0],
+ file_actions,
+ &attr,
+ (char * const *)argv,
+ (char * const *)envp);
+ }
+
+ posix_spawnattr_destroy(&attr);
+ }
+ return pid;
+}
+
+int
+main (int argc, char const **argv)
+{
+ printf ("pid %i: Pointer size is %zu.\n", getpid(), sizeof(void *));
+ int err = 0; // Set breakpoint 1 here
+#if defined (__x86_64__)
+ if (sizeof(void *) == 8)
+ {
+ spawn_process (argv, NULL, CPU_TYPE_I386, err);
+ if (err)
+ exit_with_errno (err, "posix_spawn i386 error");
+ }
+ else
+ {
+ spawn_process (argv, NULL, CPU_TYPE_X86_64, err);
+ if (err)
+ exit_with_errno (err, "posix_spawn x86_64 error");
+ }
+#else
+ spawn_process (argv, NULL, 0, err);
+ if (err)
+ exit_with_errno (err, "posix_spawn x86_64 error");
+#endif
+ return 0;
+}
More information about the lldb-commits
mailing list