[Lldb-commits] [lldb] r244190 - Second part of indicating when the user is stopped in optimized code.

Jason Molenda jmolenda at apple.com
Wed Aug 5 20:27:10 PDT 2015


Author: jmolenda
Date: Wed Aug  5 22:27:10 2015
New Revision: 244190

URL: http://llvm.org/viewvc/llvm-project?rev=244190&view=rev
Log:
Second part of indicating when the user is stopped in optimized code.

The first part was in r243508 -- the extent of the UI changes in that
patchset was to add "[opt]" to the frame-format when a stack frame was
built with optimized code.

In this change, when a stack frame built with optimization is selected,
a message will be printed to the async output channel --

opt1.c was compiled with optimization - stepping may behave oddly; variables may not be available.

The warning will be only be printed once per source file in a debug session.
These warnings may be disabled by

settings set target.process.optimization-warnings false

Internally, a new Process::PrintWarning() method has been added for
warnings that we want to print only once to the user.  It takes a type
of warning (currently only eWarningsOptimization) and an object
pointer (CompileUnit*) - the warning will only be printed once for a
given object pointer value.

This is a bit of a prototype of this change -  I think we will be
tweaking it more in the future.  But I wanted to land this and see
how it goes.  Advanced users will find these warnings unnecessary
noise and will quickly disable them - but anyone who maintains a 
debugger knows that debugging optimized code, without realizing it,
is a constant source of confusion and frustation for more typical
debugger users.  

I imagine there will be more of these "warn once per whatever" style
warnings that we will want to add in the future and we'll need to 
come up with a better way for enabling/disabling them.  But I'm not
srue what form that warning settings should take and I didn't want
to code up something that we regret later, so for now I just added
another process setting for this one warning.

<rdar://problem/19281172> 


Modified:
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/include/lldb/Target/Thread.h
    lldb/trunk/source/Target/Process.cpp
    lldb/trunk/source/Target/Thread.cpp

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=244190&r1=244189&r2=244190&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Wed Aug  5 22:27:10 2015
@@ -19,6 +19,7 @@
 #include <list>
 #include <iosfwd>
 #include <vector>
+#include <unordered_set>
 
 // Other libraries and framework includes
 // Project includes
@@ -103,6 +104,9 @@ public:
     void
     SetDetachKeepsStopped (bool keep_stopped);
 
+    bool
+    GetWarningsOptimization () const;
+
 protected:
 
     static void
@@ -766,6 +770,14 @@ public:
         eBroadcastInternalStateControlPause = (1<<1),
         eBroadcastInternalStateControlResume = (1<<2)
     };
+
+    //------------------------------------------------------------------
+    /// Process warning types.
+    //------------------------------------------------------------------
+    enum Warnings
+    {
+        eWarningsOptimization = 1
+    };
     
     typedef Range<lldb::addr_t, lldb::addr_t> LoadRange;
     // We use a read/write lock to allow on or more clients to
@@ -1939,6 +1951,33 @@ public:
         return StructuredData::ObjectSP();
     }
 
+    //------------------------------------------------------------------
+    /// Print a user-visible warning one time per Process
+    ///
+    /// A facility for printing a warning to the user once per repeat_key.
+    ///
+    /// warning_type is from the Process::Warnings enums.
+    /// repeat_key is a pointer value that will be used to ensure that the
+    /// warning message is not printed multiple times.  For instance, with a
+    /// warning about a function being optimized, you can pass the CompileUnit
+    /// pointer to have the warning issued for only the first function in a
+    /// CU, or the Function pointer to have it issued once for every function,
+    /// or a Module pointer to have it issued once per Module.
+    ///
+    /// @param [in] warning_type
+    ///     One of the types defined in Process::Warnings.
+    ///
+    /// @param [in] repeat_key
+    ///     A pointer value used to ensure that the warning is only printed once.
+    ///     May be nullptr, indicating that the warning is printed unconditionally
+    ///     every time.
+    ///
+    /// @param [in] fmt
+    ///     printf style format string
+    //------------------------------------------------------------------
+    void
+    PrintWarning (uint64_t warning_type, void *repeat_key, const char *fmt, ...) __attribute__((format(printf, 4, 5)));
+
 protected:
     
     void
@@ -3243,6 +3282,8 @@ protected:
     // Type definitions
     //------------------------------------------------------------------
     typedef std::map<lldb::LanguageType, lldb::LanguageRuntimeSP> LanguageRuntimeCollection;
+    typedef std::unordered_set<void *> WarningsPointerSet;
+    typedef std::map<uint64_t, WarningsPointerSet> WarningsCollection;
 
     struct PreResumeCallbackAndBaton
     {
@@ -3322,6 +3363,7 @@ protected:
     std::map<lldb::addr_t,lldb::addr_t> m_resolved_indirect_addresses;
     bool m_destroy_in_process;
     bool m_can_interpret_function_calls; // Some targets, e.g the OSX kernel, don't support the ability to modify the stack.
+    WarningsCollection          m_warnings_issued;  // A set of object pointers which have already had warnings printed
     
     enum {
         eCanJITDontKnow= 0,

Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=244190&r1=244189&r2=244190&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Wed Aug  5 22:27:10 2015
@@ -495,11 +495,7 @@ public:
     }
 
     lldb::StackFrameSP
-    GetSelectedFrame ()
-    {
-        lldb::StackFrameListSP stack_frame_list_sp(GetStackFrameList());
-        return stack_frame_list_sp->GetFrameAtIndex (stack_frame_list_sp->GetSelectedFrameIndex());
-    }
+    GetSelectedFrame ();
 
     uint32_t
     SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast = false);
@@ -1328,6 +1324,9 @@ protected:
     GetStackFrameList ();
     
 
+    void
+    FunctionOptimizationWarning (lldb_private::StackFrame *frame);
+
     //------------------------------------------------------------------
     // Classes that inherit from Process can see and modify these
     //------------------------------------------------------------------

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=244190&r1=244189&r2=244190&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Wed Aug  5 22:27:10 2015
@@ -115,6 +115,7 @@ g_properties[] =
     { "stop-on-sharedlibrary-events" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, stop when a shared library is loaded or unloaded." },
     { "detach-keeps-stopped" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, detach will attempt to keep the process stopped." },
     { "memory-cache-line-size" , OptionValue::eTypeUInt64, false, 512, NULL, NULL, "The memory cache line size" },
+    { "optimization-warnings" , OptionValue::eTypeBoolean, false, true, NULL, NULL, "If true, warn when stopped in code that is optimized where stepping and variable availability may not behave as expected." },
     {  NULL                  , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL  }
 };
 
@@ -126,7 +127,8 @@ enum {
     ePropertyPythonOSPluginPath,
     ePropertyStopOnSharedLibraryEvents,
     ePropertyDetachKeepsStopped,
-    ePropertyMemCacheLineSize
+    ePropertyMemCacheLineSize,
+    ePropertyWarningOptimization
 };
 
 ProcessProperties::ProcessProperties (lldb_private::Process *process) :
@@ -263,6 +265,13 @@ ProcessProperties::SetDetachKeepsStopped
     m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, stop);
 }
 
+bool
+ProcessProperties::GetWarningsOptimization () const
+{
+    const uint32_t idx = ePropertyWarningOptimization;
+    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
 void
 ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const
 {
@@ -755,6 +764,7 @@ Process::Process(Target &target, Listene
     m_last_broadcast_state (eStateInvalid),
     m_destroy_in_process (false),
     m_can_interpret_function_calls(false),
+    m_warnings_issued (),
     m_can_jit(eCanJITDontKnow)
 {
     CheckInWithManager ();
@@ -6542,6 +6552,50 @@ Process::ModulesDidLoad (ModuleList &mod
     }
 }
 
+void
+Process::PrintWarning (uint64_t warning_type, void *repeat_key, const char *fmt, ...)
+{
+    bool print_warning = true;
+
+    StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream();
+    if (stream_sp.get() == nullptr)
+        return;
+    if (warning_type == eWarningsOptimization
+        && GetWarningsOptimization() == false)
+    {
+        return;
+    }
+
+    if (repeat_key != nullptr)
+    {
+        WarningsCollection::iterator it = m_warnings_issued.find (warning_type);
+        if (it == m_warnings_issued.end())
+        {
+            m_warnings_issued[warning_type] = WarningsPointerSet();
+            m_warnings_issued[warning_type].insert (repeat_key);
+        }
+        else
+        {
+            if (it->second.find (repeat_key) != it->second.end())
+            {
+                print_warning = false;
+            }
+            else
+            {
+                it->second.insert (repeat_key);
+            }
+        }
+    }
+
+    if (print_warning)
+    {
+        va_list args;
+        va_start (args, fmt);
+        stream_sp->PrintfVarArg (fmt, args);
+        va_end (args);
+    }
+}
+
 ThreadCollectionSP
 Process::GetHistoryThreads(lldb::addr_t addr)
 {

Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=244190&r1=244189&r2=244190&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Wed Aug  5 22:27:10 2015
@@ -360,12 +360,22 @@ Thread::BroadcastSelectedFrameChange(Sta
         BroadcastEvent(eBroadcastBitSelectedFrameChanged, new ThreadEventData (this->shared_from_this(), new_frame_id));
 }
 
+lldb::StackFrameSP
+Thread::GetSelectedFrame()
+{
+    StackFrameListSP stack_frame_list_sp(GetStackFrameList());
+    StackFrameSP frame_sp = stack_frame_list_sp->GetFrameAtIndex (stack_frame_list_sp->GetSelectedFrameIndex());
+    FunctionOptimizationWarning (frame_sp.get());
+    return frame_sp;
+}
+
 uint32_t
 Thread::SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast)
 {
     uint32_t ret_value = GetStackFrameList()->SetSelectedFrame(frame);
     if (broadcast)
         BroadcastSelectedFrameChange(frame->GetStackID());
+    FunctionOptimizationWarning (frame);
     return ret_value;
 }
 
@@ -378,6 +388,7 @@ Thread::SetSelectedFrameByIndex (uint32_
         GetStackFrameList()->SetSelectedFrame(frame_sp.get());
         if (broadcast)
             BroadcastSelectedFrameChange(frame_sp->GetStackID());
+        FunctionOptimizationWarning (frame_sp.get());
         return true;
     }
     else
@@ -403,6 +414,7 @@ Thread::SetSelectedFrameByIndexNoisily (
 
             bool show_frame_info = true;
             bool show_source = !already_shown;
+            FunctionOptimizationWarning (frame_sp.get());
             return frame_sp->GetStatus (output_stream, show_frame_info, show_source);
         }
         return false;
@@ -411,6 +423,22 @@ Thread::SetSelectedFrameByIndexNoisily (
         return false;
 }
 
+void
+Thread::FunctionOptimizationWarning (StackFrame *frame)
+{
+    if (frame && frame->HasDebugInformation())
+    {
+        SymbolContext sc = frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextCompUnit);
+        if (sc.function && sc.function->GetIsOptimized() == true && sc.comp_unit)
+        {
+            if (sc.line_entry.file.GetFilename().IsEmpty() == false)
+            {
+                GetProcess()->PrintWarning (Process::Warnings::eWarningsOptimization, sc.comp_unit, "%s was compiled with optimization - stepping may behave oddly; variables may not be available.\n", sc.line_entry.file.GetFilename().GetCString());
+            }
+        }
+    }
+}
+
 
 lldb::StopInfoSP
 Thread::GetStopInfo ()




More information about the lldb-commits mailing list