summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Target/Process.h42
-rw-r--r--lldb/include/lldb/Target/Thread.h9
-rw-r--r--lldb/source/Target/Process.cpp56
-rw-r--r--lldb/source/Target/Thread.cpp28
4 files changed, 129 insertions, 6 deletions
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index b9c93bb5d53..fb981f18597 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -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,
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index fa2a8510cd9..1b20b83eda1 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -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
//------------------------------------------------------------------
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 9594a8ae434..adc393fae67 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -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 (bool stop)
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, Listener &listener, const UnixSignalsSP &unix_s
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 &module_list)
}
}
+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)
{
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index b939aeb09b0..0327fe70a29 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -360,12 +360,22 @@ Thread::BroadcastSelectedFrameChange(StackID &new_frame_id)
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_t frame_idx, bool broadcast)
GetStackFrameList()->SetSelectedFrame(frame_sp.get());
if (broadcast)
BroadcastSelectedFrameChange(frame_sp->GetStackID());
+ FunctionOptimizationWarning (frame_sp.get());
return true;
}
else
@@ -403,6 +414,7 @@ Thread::SetSelectedFrameByIndexNoisily (uint32_t frame_idx, Stream &output_strea
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 (uint32_t frame_idx, Stream &output_strea
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 ()
OpenPOWER on IntegriCloud