[Lldb-commits] [lldb] r225578 - Hoist the RegisterNumber class out of RegisterContextLLDB and make

Jason Molenda jmolenda at apple.com
Fri Jan 9 20:01:03 PST 2015


Author: jmolenda
Date: Fri Jan  9 22:01:03 2015
New Revision: 225578

URL: http://llvm.org/viewvc/llvm-project?rev=225578&view=rev
Log:
Hoist the RegisterNumber class out of RegisterContextLLDB and make
it more generally available. 

Add checks to UnwindAssembly_x86::AugmentUnwindPlanFromCallSite() so
that it won't try to augment an UnwindPlan that already describes
the function epilogue.

Add a test case for backtracing out of _sigtramp on Darwin systems.
This could probably be adapted to test the same thing on linux/bsd but 
the function names of sigtramp and kill are probably platform
specific and I'm not sure what they should be.

Added:
    lldb/trunk/source/Utility/RegisterNumber.cpp
    lldb/trunk/test/functionalities/unwind/sigtramp/
    lldb/trunk/test/functionalities/unwind/sigtramp/Makefile
    lldb/trunk/test/functionalities/unwind/sigtramp/TestSigtrampUnwind.py
    lldb/trunk/test/functionalities/unwind/sigtramp/main.c
Modified:
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
    lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=225578&r1=225577&r2=225578&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Fri Jan  9 22:01:03 2015
@@ -745,6 +745,7 @@
 		AF1729D7182C907200E0AB97 /* HistoryUnwind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF1729D5182C907200E0AB97 /* HistoryUnwind.cpp */; };
 		AF1F7B07189C904B0087DB9C /* AppleGetPendingItemsHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF1F7B05189C904B0087DB9C /* AppleGetPendingItemsHandler.cpp */; };
 		AF1F7B08189C904B0087DB9C /* AppleGetPendingItemsHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = AF1F7B06189C904B0087DB9C /* AppleGetPendingItemsHandler.h */; };
+		AF1FA88A1A60A69500272AFC /* RegisterNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF1FA8891A60A69500272AFC /* RegisterNumber.cpp */; };
 		AF23B4DB19009C66003E2A58 /* FreeBSDSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF23B4D919009C66003E2A58 /* FreeBSDSignals.cpp */; };
 		AF254E31170CCC33007AE5C9 /* PlatformDarwinKernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF254E2F170CCC33007AE5C9 /* PlatformDarwinKernel.cpp */; };
 		AF254E32170CCC33007AE5C9 /* PlatformDarwinKernel.h in Headers */ = {isa = PBXBuildFile; fileRef = AF254E30170CCC33007AE5C9 /* PlatformDarwinKernel.h */; };
@@ -2200,6 +2201,7 @@
 		AF1729D5182C907200E0AB97 /* HistoryUnwind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HistoryUnwind.cpp; path = Utility/HistoryUnwind.cpp; sourceTree = "<group>"; };
 		AF1F7B05189C904B0087DB9C /* AppleGetPendingItemsHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleGetPendingItemsHandler.cpp; sourceTree = "<group>"; };
 		AF1F7B06189C904B0087DB9C /* AppleGetPendingItemsHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleGetPendingItemsHandler.h; sourceTree = "<group>"; };
+		AF1FA8891A60A69500272AFC /* RegisterNumber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterNumber.cpp; path = source/Utility/RegisterNumber.cpp; sourceTree = "<group>"; };
 		AF23B4D919009C66003E2A58 /* FreeBSDSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FreeBSDSignals.cpp; path = Utility/FreeBSDSignals.cpp; sourceTree = "<group>"; };
 		AF23B4DA19009C66003E2A58 /* FreeBSDSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FreeBSDSignals.h; path = Utility/FreeBSDSignals.h; sourceTree = "<group>"; };
 		AF254E2F170CCC33007AE5C9 /* PlatformDarwinKernel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformDarwinKernel.cpp; sourceTree = "<group>"; };
@@ -3069,6 +3071,7 @@
 				94EBAC8313D9EE26009BA64E /* PythonPointer.h */,
 				94BA8B6E176F8CA0005A91B5 /* Range.h */,
 				94BA8B6C176F8C9B005A91B5 /* Range.cpp */,
+				AF1FA8891A60A69500272AFC /* RegisterNumber.cpp */,
 				B2462249141AE62200F3D409 /* Utils.h */,
 			);
 			name = Utility;
@@ -5568,6 +5571,7 @@
 				94F48F251A01C687005C0EC6 /* StringPrinter.cpp in Sources */,
 				94094C6B163B6F840083A547 /* ValueObjectCast.cpp in Sources */,
 				AF9107EF168570D200DBCD3C /* RegisterContextDarwin_arm64.cpp in Sources */,
+				AF1FA88A1A60A69500272AFC /* RegisterNumber.cpp in Sources */,
 				94CB255B16B069770059775D /* CXXFormatterFunctions.cpp in Sources */,
 				94CB255C16B069770059775D /* DataVisualization.cpp in Sources */,
 				94CD705016F8DF1C00CF1E42 /* LibCxxList.cpp in Sources */,

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h?rev=225578&r1=225577&r2=225578&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h Fri Jan  9 22:01:03 2015
@@ -16,6 +16,7 @@
 #include "lldb/Target/RegisterContext.h"
 #include "lldb/Symbol/UnwindPlan.h"
 #include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Utility/RegisterNumber.h"
 #include "UnwindLLDB.h"
 
 namespace lldb_private {
@@ -86,165 +87,6 @@ public:
 
 private:
 
-    //--------------------------------------------------------------------
-    /// A convenience class for RegisterContextLLDB which can convert between
-    /// different register kinds.
-    ///
-    /// This ends up being a common operation in RegisterContextLLDB as we try
-    /// to bridge between the different register numbering systems -- having a
-    /// simple object to enclose all of that conversion, and cache results so
-    /// we don't re-fetch, simplifies the code significantly.
-    //--------------------------------------------------------------------
-    class RegisterNumber {
-    public:
-        RegisterNumber (lldb_private::Thread &thread, lldb::RegisterKind kind, uint32_t num) :
-            m_reg_ctx_sp (thread.GetRegisterContext()),
-            m_regnum (num),
-            m_kind (kind),
-            m_kind_regnum_map (),
-            m_name ("")
-        {
-            if (m_reg_ctx_sp.get())
-            {
-                const lldb_private::RegisterInfo *reginfo = m_reg_ctx_sp->GetRegisterInfoAtIndex (GetAsKind (lldb::eRegisterKindLLDB));
-                if (reginfo && reginfo->name)
-                {
-                    m_name = reginfo->name;
-                }
-            }
-        }
-
-        // This constructor plus the init() method below allow for the placeholder
-        // creation of an invalid object initially, possibly to be filled in.  It
-        // would be more consistent to have three Set* methods to set the three
-        // data that the object needs.
-        RegisterNumber () :
-            m_reg_ctx_sp(),
-            m_regnum (LLDB_INVALID_REGNUM),
-            m_kind (lldb::kNumRegisterKinds),
-            m_kind_regnum_map (),
-            m_name (nullptr)
-        {
-        }
-
-        void
-        init (lldb_private::Thread &thread, lldb::RegisterKind kind, uint32_t num)
-        {
-            m_reg_ctx_sp = thread.GetRegisterContext();
-            m_regnum = num;
-            m_kind = kind;
-            if (m_reg_ctx_sp.get())
-            {
-                const lldb_private::RegisterInfo *reginfo = m_reg_ctx_sp->GetRegisterInfoAtIndex (GetAsKind (lldb::eRegisterKindLLDB));
-                if (reginfo && reginfo->name)
-                {
-                    m_name = reginfo->name;
-                }
-            }
-        }
-
-        const RegisterNumber &
-        operator = (const RegisterNumber &rhs)
-        {
-            m_reg_ctx_sp = rhs.m_reg_ctx_sp;
-            m_regnum = rhs.m_regnum;
-            m_kind = rhs.m_kind;
-            for (auto it : rhs.m_kind_regnum_map)
-                m_kind_regnum_map[it.first] = it.second;
-            m_name = rhs.m_name;
-            return *this;
-        }
-
-        bool
-        operator == (RegisterNumber &rhs)
-        {
-            if (IsValid() != rhs.IsValid())
-                return false;
-
-            if (m_kind == rhs.m_kind)
-            {
-                if (m_regnum == rhs.m_regnum)
-                    return true;
-                else
-                    return false;
-            }
-
-            uint32_t rhs_regnum = rhs.GetAsKind (m_kind);
-            if (rhs_regnum != LLDB_INVALID_REGNUM)
-            {
-                if (m_regnum == rhs_regnum)
-                    return true;
-                else
-                    return false;
-            }
-            uint32_t lhs_regnum = GetAsKind (rhs.m_kind);
-            {
-                if (lhs_regnum == rhs.m_regnum)
-                    return true;
-                else 
-                    return false;
-            }
-            return false;
-        }
-
-        bool
-        IsValid () const
-        {
-            return m_regnum != LLDB_INVALID_REGNUM;
-        }
-
-        uint32_t
-        GetAsKind (lldb::RegisterKind kind)
-        {
-            if (m_regnum == LLDB_INVALID_REGNUM)
-                return LLDB_INVALID_REGNUM;
-
-            if (kind == m_kind)
-                return m_regnum;
-
-            Collection::iterator iter = m_kind_regnum_map.find (kind);
-            if (iter != m_kind_regnum_map.end())
-            {
-                return iter->second;
-            }
-            uint32_t output_regnum = LLDB_INVALID_REGNUM;
-            if (m_reg_ctx_sp 
-                && m_reg_ctx_sp->ConvertBetweenRegisterKinds (m_kind, m_regnum, kind, output_regnum)
-                && output_regnum != LLDB_INVALID_REGNUM)
-            {
-                m_kind_regnum_map[kind] = output_regnum;
-            }
-            return output_regnum;
-        }
-
-        uint32_t
-        GetRegisterNumber () const
-        {
-            return m_regnum;
-        }
-
-        lldb::RegisterKind
-        GetRegisterKind () const
-        {
-            return m_kind;
-        }
-
-        const char *
-        GetName ()
-        {
-            return m_name;
-        }
-
-    private:
-        typedef std::map<lldb::RegisterKind, uint32_t> Collection; 
-
-        lldb::RegisterContextSP m_reg_ctx_sp;
-        uint32_t                m_regnum;
-        lldb::RegisterKind      m_kind;
-        Collection              m_kind_regnum_map;
-        const char              *m_name;
-    };
-
     enum FrameType
     {
         eNormalFrame,

Modified: lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp?rev=225578&r1=225577&r2=225578&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp (original)
+++ lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp Fri Jan  9 22:01:03 2015
@@ -23,6 +23,7 @@
 #include "lldb/Target/Thread.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/UnwindAssembly.h"
+#include "lldb/Utility/RegisterNumber.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -955,7 +956,9 @@ AssemblyParse_x86::augment_unwind_plan_f
         // If we already have one row for this instruction, we can continue.
         while (row_id < unwind_plan.GetRowCount()
                && unwind_plan.GetRowAtIndex (row_id)->GetOffset() <= offset)
+        {
             row_id++;
+        }
         UnwindPlan::RowSP original_row = unwind_plan.GetRowAtIndex (row_id - 1);
         if (original_row->GetOffset() == offset)
         {
@@ -1262,9 +1265,71 @@ UnwindAssembly_x86::GetNonCallSiteUnwind
 bool
 UnwindAssembly_x86::AugmentUnwindPlanFromCallSite (AddressRange& func, Thread& thread, UnwindPlan& unwind_plan)
 {
-    ExecutionContext exe_ctx (thread.shared_from_this());
-    AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func);
-    return asm_parse.augment_unwind_plan_from_call_site (func, unwind_plan);
+    bool do_augment_unwindplan = true;
+
+    UnwindPlan::RowSP first_row = unwind_plan.GetRowForFunctionOffset (0);
+    UnwindPlan::RowSP last_row = unwind_plan.GetRowForFunctionOffset (-1);
+    
+    // If the UnwindPlan correctly describes the prologue and the epilogue, then
+    // we shouldn't do any augmentation (and risk messing up correct unwind instructions)
+
+    // See if the first row (which should be the register state on function entry)
+    // and the last row (which should be the register state on function exit) match.
+
+    if (first_row != last_row && first_row->GetOffset() != last_row->GetOffset())
+    {
+        RegisterNumber sp_regnum (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+
+        // The first & last row have the same CFA register
+        // and the same CFA offset value
+        // and the CFA register is esp/rsp (the stack pointer).
+
+        // We're checking that both of them have an unwind rule like "CFA=esp+4" or CFA+rsp+8".
+
+        if (first_row->GetCFAType() == last_row->GetCFAType()
+            && first_row->GetCFAType() == UnwindPlan::Row::CFAType::CFAIsRegisterPlusOffset
+            && first_row->GetCFARegister() == last_row->GetCFARegister()
+            && first_row->GetCFAOffset() == last_row->GetCFAOffset()
+            && RegisterNumber (thread, unwind_plan.GetRegisterKind(), first_row->GetCFARegister()) == sp_regnum)
+        {
+            RegisterNumber pc_regnum (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+
+            // Get the register locations for eip/rip from the first & last rows.
+            // Are they both CFA plus an offset?  Is it the same offset?
+
+            UnwindPlan::Row::RegisterLocation first_row_pc_loc;
+            UnwindPlan::Row::RegisterLocation last_row_pc_loc;
+            if (first_row->GetRegisterInfo (pc_regnum.GetAsKind (unwind_plan.GetRegisterKind()), first_row_pc_loc)
+                && last_row->GetRegisterInfo (pc_regnum.GetAsKind (unwind_plan.GetRegisterKind()), last_row_pc_loc))
+            {
+                if (first_row_pc_loc.IsAtCFAPlusOffset() 
+                    && last_row_pc_loc.IsAtCFAPlusOffset()
+                    && first_row_pc_loc.GetOffset() == last_row_pc_loc.GetOffset())
+                {
+            
+                    // One last sanity check:  Is the unwind rule for getting the caller pc value
+                    // "deref the CFA-4" or "deref the CFA-8"? 
+
+                    // If so, we have an UnwindPlan that already describes the epilogue and we don't need
+                    // to modify it at all.
+
+                    if (first_row_pc_loc.GetOffset() == -4 || first_row_pc_loc.GetOffset() == -8)
+                    {
+                        do_augment_unwindplan = false;
+                    }
+                }
+            }
+        }
+    }
+
+    if (do_augment_unwindplan)
+    {
+        ExecutionContext exe_ctx (thread.shared_from_this());
+        AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func);
+        return asm_parse.augment_unwind_plan_from_call_site (func, unwind_plan);
+    }
+    
+    return false;
 }
 
 bool

Added: lldb/trunk/source/Utility/RegisterNumber.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/RegisterNumber.cpp?rev=225578&view=auto
==============================================================================
--- lldb/trunk/source/Utility/RegisterNumber.cpp (added)
+++ lldb/trunk/source/Utility/RegisterNumber.cpp Fri Jan  9 22:01:03 2015
@@ -0,0 +1,151 @@
+//===--------------------- RegisterNumber.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/Utility/RegisterNumber.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/RegisterContext.h"
+
+using namespace lldb_private;
+
+
+RegisterNumber::RegisterNumber (lldb_private::Thread &thread, lldb::RegisterKind kind, uint32_t num) :
+    m_reg_ctx_sp (thread.GetRegisterContext()),
+    m_regnum (num),
+    m_kind (kind),
+    m_kind_regnum_map (),
+    m_name ("")
+{
+    if (m_reg_ctx_sp.get())
+    {
+        const lldb_private::RegisterInfo *reginfo = m_reg_ctx_sp->GetRegisterInfoAtIndex (GetAsKind (lldb::eRegisterKindLLDB));
+        if (reginfo && reginfo->name)
+        {
+            m_name = reginfo->name;
+        }
+    }
+}
+
+RegisterNumber::RegisterNumber () :
+    m_reg_ctx_sp(),
+    m_regnum (LLDB_INVALID_REGNUM),
+    m_kind (lldb::kNumRegisterKinds),
+    m_kind_regnum_map (),
+    m_name (nullptr)
+{
+}
+
+void
+RegisterNumber::init (lldb_private::Thread &thread, lldb::RegisterKind kind, uint32_t num)
+{
+    m_reg_ctx_sp = thread.GetRegisterContext();
+    m_regnum = num;
+    m_kind = kind;
+    if (m_reg_ctx_sp.get())
+    {
+        const lldb_private::RegisterInfo *reginfo = m_reg_ctx_sp->GetRegisterInfoAtIndex (GetAsKind (lldb::eRegisterKindLLDB));
+        if (reginfo && reginfo->name)
+        {
+            m_name = reginfo->name;
+        }
+    }
+}
+
+const RegisterNumber &
+RegisterNumber::operator = (const RegisterNumber &rhs)
+{
+    m_reg_ctx_sp = rhs.m_reg_ctx_sp;
+    m_regnum = rhs.m_regnum;
+    m_kind = rhs.m_kind;
+    for (auto it : rhs.m_kind_regnum_map)
+        m_kind_regnum_map[it.first] = it.second;
+    m_name = rhs.m_name;
+    return *this;
+}
+
+bool
+RegisterNumber::operator == (RegisterNumber &rhs)
+{
+    if (IsValid() != rhs.IsValid())
+        return false;
+
+    if (m_kind == rhs.m_kind)
+    {
+        if (m_regnum == rhs.m_regnum)
+            return true;
+        else
+            return false;
+    }
+
+    uint32_t rhs_regnum = rhs.GetAsKind (m_kind);
+    if (rhs_regnum != LLDB_INVALID_REGNUM)
+    {
+        if (m_regnum == rhs_regnum)
+            return true;
+        else
+            return false;
+    }
+    uint32_t lhs_regnum = GetAsKind (rhs.m_kind);
+    {
+        if (lhs_regnum == rhs.m_regnum)
+            return true;
+        else 
+            return false;
+    }
+    return false;
+}
+
+bool
+RegisterNumber::IsValid () const
+{
+    return m_reg_ctx_sp.get()
+        && m_kind != lldb::kNumRegisterKinds 
+        && m_regnum != LLDB_INVALID_REGNUM;
+}
+
+uint32_t
+RegisterNumber::GetAsKind (lldb::RegisterKind kind)
+{
+    if (m_regnum == LLDB_INVALID_REGNUM)
+        return LLDB_INVALID_REGNUM;
+
+    if (kind == m_kind)
+        return m_regnum;
+
+    Collection::iterator iter = m_kind_regnum_map.find (kind);
+    if (iter != m_kind_regnum_map.end())
+    {
+        return iter->second;
+    }
+    uint32_t output_regnum = LLDB_INVALID_REGNUM;
+    if (m_reg_ctx_sp 
+        && m_reg_ctx_sp->ConvertBetweenRegisterKinds (m_kind, m_regnum, kind, output_regnum)
+        && output_regnum != LLDB_INVALID_REGNUM)
+    {
+        m_kind_regnum_map[kind] = output_regnum;
+    }
+    return output_regnum;
+}
+
+uint32_t
+RegisterNumber::GetRegisterNumber () const
+{
+    return m_regnum;
+}
+
+lldb::RegisterKind
+RegisterNumber::GetRegisterKind () const
+{
+    return m_kind;
+}
+
+const char *
+RegisterNumber::GetName ()
+{
+    return m_name;
+}

Added: lldb/trunk/test/functionalities/unwind/sigtramp/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/unwind/sigtramp/Makefile?rev=225578&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/unwind/sigtramp/Makefile (added)
+++ lldb/trunk/test/functionalities/unwind/sigtramp/Makefile Fri Jan  9 22:01:03 2015
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/functionalities/unwind/sigtramp/TestSigtrampUnwind.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/unwind/sigtramp/TestSigtrampUnwind.py?rev=225578&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/unwind/sigtramp/TestSigtrampUnwind.py (added)
+++ lldb/trunk/test/functionalities/unwind/sigtramp/TestSigtrampUnwind.py Fri Jan  9 22:01:03 2015
@@ -0,0 +1,94 @@
+"""
+Test that we can backtrace correctly with 'sigtramp' functions on the stack
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+
+class SigtrampUnwind(TestBase):
+    mydir = TestBase.compute_mydir(__file__)
+
+    # On different platforms the "_sigtramp" and "__kill" frames are likely to be different.
+    # This test could probably be adapted to run on linux/*bsd easily enough.
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @dsym_test
+    def test_with_dsym (self):
+        """Test that we can backtrace correctly with _sigtramp on the stack"""
+        self.buildDsym()
+        self.setTearDownCleanup()
+        self.sigtramp_unwind_tests()
+
+    @dwarf_test
+    def test_with_dwarf (self):
+        """Test that we can backtrace correctly with _sigtramp on the stack"""
+        self.buildDwarf()
+        self.setTearDownCleanup()
+        self.sigtramp_unwind_tests()
+
+    def sigtramp_unwind_tests (self):
+        exe = os.path.join(os.getcwd(), "a.out")
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+
+
+        lldbutil.run_break_set_by_file_and_line (self, "main.c", line_number('main.c', '// Set breakpoint here'), num_expected_locations=1)
+
+        process = target.LaunchSimple (None, None, self.get_process_working_directory())
+
+        if not process:
+            self.fail("SBTarget.Launch() failed")
+
+        if process.GetState() != lldb.eStateStopped:
+            self.fail("Process should be in the 'stopped' state, "
+                      "instead the actual state is: '%s'" %
+                      lldbutil.state_type_to_str(process.GetState()))
+
+        self.expect("pro handle  -n false -p true -s false SIGUSR1", "Have lldb pass SIGUSR1 signals",
+            substrs = ["SIGUSR1", "true", "false", "false"])
+
+        lldbutil.run_break_set_by_symbol (self, "handler", num_expected_locations=1, module_name="a.out")
+
+        self.runCmd("continue")
+
+        thread = process.GetThreadAtIndex(0)
+
+        found_handler = False
+        found_sigtramp = False
+        found_kill = False
+        found_main = False
+
+        for f in thread.frames:
+            if f.GetFunctionName() == "handler":
+                found_handler = True
+            if f.GetFunctionName() == "_sigtramp":
+                found_sigtramp = True
+            if f.GetFunctionName() == "__kill":
+                found_kill = True
+            if f.GetFunctionName() == "main":
+                found_main = True
+
+        if self.TraceOn():
+            print "Backtrace once we're stopped:"
+            for f in thread.frames:
+                print "  %d %s" % (f.GetFrameID(), f.GetFunctionName())
+
+        if found_handler == False:
+            self.fail("Unable to find handler() in backtrace.")
+
+        if found_sigtramp == False:
+            self.fail("Unable to find _sigtramp() in backtrace.")
+
+        if found_kill == False:
+            self.fail("Unable to find kill() in backtrace.")
+
+        if found_main == False:
+            self.fail("Unable to find main() in backtrace.")
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/functionalities/unwind/sigtramp/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/unwind/sigtramp/main.c?rev=225578&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/unwind/sigtramp/main.c (added)
+++ lldb/trunk/test/functionalities/unwind/sigtramp/main.c Fri Jan  9 22:01:03 2015
@@ -0,0 +1,27 @@
+#include <stdlib.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+void handler (int in)
+{
+    puts ("in handler routine");
+    while (1)
+        ;
+}
+
+void
+foo ()
+{
+    puts ("in foo ()");
+    kill (getpid(), SIGUSR1);
+}
+int main ()
+{
+    puts ("in main");           // Set breakpoint here
+    signal (SIGUSR1, handler);
+    puts ("signal handler set up");
+    foo();
+    puts ("exiting");
+    return 0;
+}





More information about the lldb-commits mailing list