Index: include/lldb/API/SBDefines.h =================================================================== --- include/lldb/API/SBDefines.h +++ include/lldb/API/SBDefines.h @@ -85,6 +85,7 @@ class LLDB_API SBValue; class LLDB_API SBValueList; class LLDB_API SBWatchpoint; +class LLDB_API SBUnixSignals; } Index: include/lldb/API/SBProcess.h =================================================================== --- include/lldb/API/SBProcess.h +++ include/lldb/API/SBProcess.h @@ -221,6 +221,9 @@ lldb::SBError Signal (int signal); + lldb::SBUnixSignals + GetUnixSignals(); + void SendAsyncInterrupt(); Index: include/lldb/API/SBUnixSignals.h =================================================================== --- /dev/null +++ include/lldb/API/SBUnixSignals.h @@ -0,0 +1,84 @@ +//===-- SBUnixSignals.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SBUnixSignals_h_ +#define LLDB_SBUnixSignals_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBUnixSignals { +public: + SBUnixSignals (); + + SBUnixSignals (const lldb::SBUnixSignals &rhs); + + ~SBUnixSignals(); + + const SBUnixSignals & + operator =(const lldb::SBUnixSignals &rhs); + + void + Clear (); + + bool + IsValid () const; + + const char * + GetSignalAsCString (int32_t signo) const; + + int32_t + GetSignalNumberFromName (const char *name) const; + + bool + GetShouldSuppress (int32_t signo) const; + + bool + SetShouldSuppress (int32_t signo, + bool value); + + bool + GetShouldStop (int32_t signo) const; + + bool + SetShouldStop (int32_t signo, + bool value); + + bool + GetShouldNotify (int32_t signo) const; + + bool + SetShouldNotify (int32_t signo, bool value); + + int32_t + GetNumSignals () const; + + int32_t + GetSignalAtIndex (int32_t index) const; + +protected: + friend class SBProcess; + + SBUnixSignals (lldb::ProcessSP &process_sp); + + lldb::ProcessSP + GetSP() const; + + void + SetSP (const lldb::ProcessSP &process_sp); + +private: + lldb::ProcessWP m_opaque_wp; +}; + + +} // namespace lldb + +#endif // LLDB_SBUnixSignals_h_ Index: include/lldb/lldb-defines.h =================================================================== --- include/lldb/lldb-defines.h +++ include/lldb/lldb-defines.h @@ -24,6 +24,10 @@ #define LLDB_API #endif +#if !defined(INT32_MAX) + #define INT32_MAX 2147483647 +#endif + #if !defined(UINT32_MAX) #define UINT32_MAX 4294967295U #endif Index: include/lldb/lldb-forward.h =================================================================== --- include/lldb/lldb-forward.h +++ include/lldb/lldb-forward.h @@ -249,6 +249,7 @@ class TypeNameSpecifierImpl; class TypePair; class UUID; +class UnixSignals; class Unwind; class UnwindAssembly; class UnwindPlan; Index: scripts/Python/build-swig-Python.sh =================================================================== --- scripts/Python/build-swig-Python.sh +++ scripts/Python/build-swig-Python.sh @@ -122,7 +122,8 @@ " ${SRC_ROOT}/include/lldb/API/SBTypeSynthetic.h"\ " ${SRC_ROOT}/include/lldb/API/SBValue.h"\ " ${SRC_ROOT}/include/lldb/API/SBValueList.h"\ -" ${SRC_ROOT}/include/lldb/API/SBWatchpoint.h" +" ${SRC_ROOT}/include/lldb/API/SBWatchpoint.h"\ +" ${SRC_ROOT}/include/lldb/API/SBUnixSignals.h" INTERFACE_FILES="${SRC_ROOT}/scripts/Python/interface/SBAddress.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBBlock.i"\ @@ -169,7 +170,8 @@ " ${SRC_ROOT}/scripts/Python/interface/SBTypeSynthetic.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBValue.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBValueList.i"\ -" ${SRC_ROOT}/scripts/Python/interface/SBWatchpoint.i" +" ${SRC_ROOT}/scripts/Python/interface/SBWatchpoint.i"\ +" ${SRC_ROOT}/scripts/Python/interface/SBUnixSignals.i" if [ $Debug -eq 1 ] then Index: scripts/Python/interface/SBProcess.i =================================================================== --- scripts/Python/interface/SBProcess.i +++ scripts/Python/interface/SBProcess.i @@ -240,6 +240,9 @@ lldb::SBError Signal (int signal); + lldb::SBUnixSignals + GetUnixSignals(); + %feature("docstring", " Returns a stop id that will increase every time the process executes. If include_expression_stops is true, then stops caused by expression evaluation Index: scripts/Python/interface/SBUnixSignals.i =================================================================== --- /dev/null +++ scripts/Python/interface/SBUnixSignals.i @@ -0,0 +1,74 @@ +//===-- SWIG Interface for SBProcess ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +namespace lldb { + +%feature("docstring", +"Allows you to manipulate LLDB's signal disposition" +) SBUnixSignals; +class SBUnixSignals +{ +public: + SBUnixSignals (); + + SBUnixSignals (const lldb::SBUnixSignals &rhs); + + ~SBUnixSignals(); + + void + Clear (); + + bool + IsValid () const; + + const char * + GetSignalAsCString (int32_t signo) const; + + int32_t + GetSignalNumberFromName (const char *name) const; + + bool + GetShouldSuppress (int32_t signo) const; + + bool + SetShouldSuppress (int32_t signo, + bool value); + + bool + GetShouldStop (int32_t signo) const; + + bool + SetShouldStop (int32_t signo, + bool value); + + bool + GetShouldNotify (int32_t signo) const; + + bool + SetShouldNotify (int32_t signo, bool value); + + int32_t + GetNumSignals () const; + + int32_t + GetSignalAtIndex (int32_t index) const; + + %pythoncode %{ + def get_unix_signals_list(self): + signals = [] + for idx in range(0, self.GetNumSignals()): + signals.append(self.GetSignalAtIndex(sig)) + return signals + + __swig_getmethods__["signals"] = get_unix_signals_list + if _newclass: threads = property(get_unix_signals_list, None, doc='''A read only property that returns a list() of valid signal numbers for this platform.''') + %} +}; + +} // namespace lldb Index: scripts/lldb.swig =================================================================== --- scripts/lldb.swig +++ scripts/lldb.swig @@ -102,6 +102,7 @@ #include "lldb/API/SBValue.h" #include "lldb/API/SBValueList.h" #include "lldb/API/SBWatchpoint.h" +#include "lldb/API/SBUnixSignals.h" #include "../scripts/Python/python-swigsafecast.swig" @@ -109,6 +110,9 @@ /* Various liblldb typedefs that SWIG needs to know about. */ #define __extension__ /* Undefine GCC keyword to make Swig happy when processing glibc's stdint.h. */ +/* The ISO C99 standard specifies that in C++ implementations limit macros such + as INT32_MAX should only be defined if __STDC_LIMIT_MACROS is. */ +#define __STDC_LIMIT_MACROS %include "stdint.i" %include "lldb/lldb-defines.h" %include "lldb/lldb-enumerations.h" @@ -169,6 +173,7 @@ %include "./Python/interface/SBValue.i" %include "./Python/interface/SBValueList.i" %include "./Python/interface/SBWatchpoint.i" +%include "./Python/interface/SBUnixSignals.i" %include "./Python/python-extensions.swig" Index: source/API/CMakeLists.txt =================================================================== --- source/API/CMakeLists.txt +++ source/API/CMakeLists.txt @@ -51,4 +51,5 @@ SBValue.cpp SBValueList.cpp SBWatchpoint.cpp + SBUnixSignals.cpp ) Index: source/API/SBProcess.cpp =================================================================== --- source/API/SBProcess.cpp +++ source/API/SBProcess.cpp @@ -40,6 +40,7 @@ #include "lldb/API/SBThread.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStringList.h" +#include "lldb/API/SBUnixSignals.h" using namespace lldb; using namespace lldb_private; @@ -893,6 +894,19 @@ return sb_error; } +SBUnixSignals +SBProcess::GetUnixSignals() +{ + SBUnixSignals sb_unix_signals; + ProcessSP process_sp(GetSP()); + if (process_sp) + { + sb_unix_signals.SetSP(process_sp); + } + + return sb_unix_signals; +} + void SBProcess::SendAsyncInterrupt () { Index: source/API/SBUnixSignals.cpp =================================================================== --- /dev/null +++ source/API/SBUnixSignals.cpp @@ -0,0 +1,199 @@ +//===-- SBUnixSignals.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-defines.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/UnixSignals.h" +#include "lldb/Core/Log.h" + +#include "lldb/API/SBUnixSignals.h" + +using namespace lldb; +using namespace lldb_private; + +SBUnixSignals::SBUnixSignals () +{} + +SBUnixSignals::SBUnixSignals (const SBUnixSignals &rhs) : + m_opaque_wp(rhs.m_opaque_wp) +{ +} + +SBUnixSignals::SBUnixSignals (ProcessSP &process_sp) : + m_opaque_wp(process_sp) +{ +} + +const SBUnixSignals& +SBUnixSignals::operator = (const SBUnixSignals& rhs) +{ + if (this != &rhs) + m_opaque_wp = rhs.m_opaque_wp; + return *this; +} + +SBUnixSignals::~SBUnixSignals() +{ +} + +ProcessSP +SBUnixSignals::GetSP() const +{ + return m_opaque_wp.lock(); +} + +void +SBUnixSignals::SetSP (const ProcessSP &process_sp) +{ + m_opaque_wp = process_sp; +} + +void +SBUnixSignals::Clear () +{ + m_opaque_wp.reset(); +} + +bool +SBUnixSignals::IsValid() const +{ + return (bool) GetSP(); +} + +const char * +SBUnixSignals::GetSignalAsCString (int32_t signo) const +{ + ProcessSP process_sp(GetSP()); + if (process_sp) return process_sp->GetUnixSignals().GetSignalAsCString(signo); + return NULL; +} + +int32_t +SBUnixSignals::GetSignalNumberFromName (const char *name) const +{ + ProcessSP process_sp(GetSP()); + if (process_sp) return process_sp->GetUnixSignals().GetSignalNumberFromName(name); + return -1; +} + +bool +SBUnixSignals::GetShouldSuppress (int32_t signo) const +{ + ProcessSP process_sp(GetSP()); + if (process_sp) return process_sp->GetUnixSignals().GetShouldSuppress(signo); + return false; +} + +bool +SBUnixSignals::SetShouldSuppress (int32_t signo, bool value) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + ProcessSP process_sp(GetSP()); + + if (log) + { + log->Printf ("SBUnixSignals(%p)::SetShouldSuppress (signo=%d, value=%d)", + static_cast(process_sp.get()), + signo, + value); + } + + if (process_sp) return process_sp->GetUnixSignals().SetShouldSuppress(signo, value); + return false; +} + +bool +SBUnixSignals::GetShouldStop (int32_t signo) const +{ + ProcessSP process_sp(GetSP()); + if (process_sp) return process_sp->GetUnixSignals().GetShouldStop(signo); + return false; +} + +bool +SBUnixSignals::SetShouldStop (int32_t signo, bool value) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + ProcessSP process_sp(GetSP()); + + if (log) + { + log->Printf ("SBUnixSignals(%p)::SetShouldStop (signo=%d, value=%d)", + static_cast(process_sp.get()), + signo, + value); + } + + if (process_sp) return process_sp->GetUnixSignals().SetShouldStop(signo, value); + return false; +} + +bool +SBUnixSignals::GetShouldNotify (int32_t signo) const +{ + ProcessSP process_sp(GetSP()); + if (process_sp) return process_sp->GetUnixSignals().GetShouldNotify(signo); + return false; +} + +bool +SBUnixSignals::SetShouldNotify (int32_t signo, bool value) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + ProcessSP process_sp(GetSP()); + + if (log) + { + log->Printf ("SBUnixSignals(%p)::SetShouldNotify (signo=%d, value=%d)", + static_cast(process_sp.get()), + signo, + value); + } + + if (process_sp) return process_sp->GetUnixSignals().SetShouldNotify(signo, value); + return false; +} + +int32_t +SBUnixSignals::GetNumSignals () const +{ + if (auto process_sp = GetSP()) + { + // only valid while we hold process_sp + UnixSignals *unix_signals_ptr = &process_sp->GetUnixSignals(); + int32_t num_signals = 0; + for (int32_t signo = unix_signals_ptr->GetFirstSignalNumber(); + signo != LLDB_INVALID_SIGNAL_NUMBER; + signo = unix_signals_ptr->GetNextSignalNumber(signo)) + { + num_signals++; + } + return num_signals; + } + return LLDB_INVALID_SIGNAL_NUMBER; +} + +int32_t +SBUnixSignals::GetSignalAtIndex (int32_t index) const +{ + if (auto process_sp = GetSP()) + { + // only valid while we hold process_sp + UnixSignals *unix_signals_ptr = &process_sp->GetUnixSignals(); + int32_t idx = 0; + for (int32_t signo = unix_signals_ptr->GetFirstSignalNumber(); + signo != LLDB_INVALID_SIGNAL_NUMBER; + signo = unix_signals_ptr->GetNextSignalNumber(signo)) + { + if (index == idx) return signo; + idx++; + } + } + return LLDB_INVALID_SIGNAL_NUMBER; +} Index: test/python_api/signals/Makefile =================================================================== --- /dev/null +++ test/python_api/signals/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules Index: test/python_api/signals/TestSignalsAPI.py =================================================================== --- /dev/null +++ test/python_api/signals/TestSignalsAPI.py @@ -0,0 +1,49 @@ +""" +Test SBProcess APIs, including ReadMemory(), WriteMemory(), and others. +""" + +import os, time +import unittest2 +import lldb +from lldbutil import get_stopped_thread, state_type_to_str +from lldbtest import * + +class SignalsAPITestCase(TestBase): + mydir = os.path.join("python_api", "signals") + + @python_api_test + def test_ignore_signal(self): + """Test Python SBUnixSignals.Suppress/Stop/Notify() API.""" + self.buildDefault() + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + line = line_number("main.cpp", "// Set break point at this line and setup signal ignores.") + breakpoint = target.BreakpointCreateByLocation("main.cpp", line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") + + unix_signals = process.GetUnixSignals() + sigint = unix_signals.GetSignalNumberFromName("SIGINT") + unix_signals.SetShouldSuppress(sigint, True) + unix_signals.SetShouldStop(sigint, False) + unix_signals.SetShouldNotify(sigint, False) + + process.Continue() + self.assertTrue(process.state == lldb.eStateExited, "The process should have exited") + self.assertTrue(process.GetExitStatus() == 0, "The process should have returned 0") + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Index: test/python_api/signals/main.cpp =================================================================== --- /dev/null +++ test/python_api/signals/main.cpp @@ -0,0 +1,20 @@ +//===-- 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 +#include +#include +#include + +// This simple program is to test the lldb Python API related to process. + +int main (int argc, char const *argv[]) +{ + kill(getpid(), SIGINT); // Set break point at this line and setup signal ignores. + return 0; +}