[Lldb-commits] [lldb] 38dfb23 - [lldb] Support debugging utility functions

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Wed Feb 24 11:36:09 PST 2021


Author: Jonas Devlieghere
Date: 2021-02-24T11:36:01-08:00
New Revision: 38dfb235db19caa1aaa58c1c8153a7464b932087

URL: https://github.com/llvm/llvm-project/commit/38dfb235db19caa1aaa58c1c8153a7464b932087
DIFF: https://github.com/llvm/llvm-project/commit/38dfb235db19caa1aaa58c1c8153a7464b932087.diff

LOG: [lldb] Support debugging utility functions

LLDB uses utility functions to run code in the inferior for its own
internal purposes, such as reading classes from the Objective-C runtime
for example. Because these expressions should be transparent to the
user, we ignore breakpoints and unwind the stack on errors, which
makes them hard to debug.

This patch adds a new setting target.debug-utility-expression that, when
enabled, changes these options to facilitate debugging. It enables
breakpoints, disables unwinding and writes out the utility function
source code to disk so it shows up in the source view.

Differential revision: https://reviews.llvm.org/D97249

Added: 
    

Modified: 
    lldb/include/lldb/Expression/UtilityFunction.h
    lldb/include/lldb/Target/Target.h
    lldb/source/Expression/FunctionCaller.cpp
    lldb/source/Expression/UtilityFunction.cpp
    lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
    lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
    lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
    lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
    lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
    lldb/source/Target/Target.cpp
    lldb/source/Target/TargetProperties.td

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Expression/UtilityFunction.h b/lldb/include/lldb/Expression/UtilityFunction.h
index 99fb32153aa2..6b558b20e212 100644
--- a/lldb/include/lldb/Expression/UtilityFunction.h
+++ b/lldb/include/lldb/Expression/UtilityFunction.h
@@ -42,8 +42,11 @@ class UtilityFunction : public Expression {
   ///
   /// \param[in] name
   ///     The name of the function, as used in the text.
+  ///
+  /// \param[in] enable_debugging
+  ///     Enable debugging of this function.
   UtilityFunction(ExecutionContextScope &exe_scope, std::string text,
-                  std::string name);
+                  std::string name, bool enable_debugging);
 
   ~UtilityFunction() override;
 

diff  --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 69baefb964b0..f35f4e9a44f1 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -227,6 +227,10 @@ class TargetProperties : public Properties {
 
   void UpdateLaunchInfoFromProperties();
 
+  void SetDebugUtilityExpression(bool debug);
+
+  bool GetDebugUtilityExpression() const;
+
 private:
   // Callbacks for m_launch_info.
   void Arg0ValueChangedCallback();

diff  --git a/lldb/source/Expression/FunctionCaller.cpp b/lldb/source/Expression/FunctionCaller.cpp
index f0abdb7534bf..5f1eb24a905a 100644
--- a/lldb/source/Expression/FunctionCaller.cpp
+++ b/lldb/source/Expression/FunctionCaller.cpp
@@ -317,12 +317,16 @@ lldb::ExpressionResults FunctionCaller::ExecuteFunction(
   lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
 
   // FunctionCaller::ExecuteFunction execution is always just to get the
-  // result. Do make sure we ignore breakpoints, unwind on error, and don't try
-  // to debug it.
+  // result. Unless explicitly asked for, ignore breakpoints and unwind on
+  // error.
+  const bool enable_debugging =
+      exe_ctx.GetTargetPtr() &&
+      exe_ctx.GetTargetPtr()->GetDebugUtilityExpression();
   EvaluateExpressionOptions real_options = options;
-  real_options.SetDebug(false);
-  real_options.SetUnwindOnError(true);
-  real_options.SetIgnoreBreakpoints(true);
+  real_options.SetDebug(false); // This halts the expression for debugging.
+  real_options.SetGenerateDebugInfo(enable_debugging);
+  real_options.SetUnwindOnError(!enable_debugging);
+  real_options.SetIgnoreBreakpoints(!enable_debugging);
 
   lldb::addr_t args_addr;
 

diff  --git a/lldb/source/Expression/UtilityFunction.cpp b/lldb/source/Expression/UtilityFunction.cpp
index 128db0ccbc3e..7ad25f5aa7fe 100644
--- a/lldb/source/Expression/UtilityFunction.cpp
+++ b/lldb/source/Expression/UtilityFunction.cpp
@@ -41,7 +41,8 @@ char UtilityFunction::ID;
 /// \param[in] name
 ///     The name of the function, as used in the text.
 UtilityFunction::UtilityFunction(ExecutionContextScope &exe_scope,
-                                 std::string text, std::string name)
+                                 std::string text, std::string name,
+                                 bool enable_debugging)
     : Expression(exe_scope), m_execution_unit_sp(), m_jit_module_wp(),
       m_function_text(std::move(text)), m_function_name(std::move(name)) {}
 

diff  --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
index 180e08b03c93..59a2e8795260 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
@@ -31,6 +31,7 @@
 using namespace lldb_private;
 
 #define PREFIX_NAME "<lldb wrapper prefix>"
+#define SUFFIX_NAME "<lldb wrapper suffix>"
 
 const llvm::StringRef ClangExpressionSourceCode::g_prefix_file_name = PREFIX_NAME;
 
@@ -73,6 +74,9 @@ extern "C"
 }
 )";
 
+const char *ClangExpressionSourceCode::g_expression_suffix =
+    "\n;\n#line 1 \"" SUFFIX_NAME "\"\n";
+
 namespace {
 
 class AddMacroState {
@@ -180,7 +184,7 @@ lldb_private::ClangExpressionSourceCode::ClangExpressionSourceCode(
   // containing only the user expression. This will hide our wrapper code
   // from the user when we render diagnostics with Clang.
   m_start_marker = "#line 1 \"" + filename.str() + "\"\n";
-  m_end_marker = "\n;\n#line 1 \"<lldb wrapper suffix>\"\n";
+  m_end_marker = g_expression_suffix;
 }
 
 namespace {

diff  --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
index 9a54f0e3ad8d..54ae837fb30f 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
@@ -27,6 +27,7 @@ class ClangExpressionSourceCode : public ExpressionSourceCode {
   /// the user expression.
   static const llvm::StringRef g_prefix_file_name;
   static const char *g_expression_prefix;
+  static const char *g_expression_suffix;
 
   /// The possible ways an expression can be wrapped.
   enum class WrapKind {

diff  --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
index 9788a4e1c183..5d56bd7285f7 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
@@ -34,19 +34,36 @@ using namespace lldb_private;
 
 char ClangUtilityFunction::ID;
 
-/// Constructor
-///
-/// \param[in] text
-///     The text of the function.  Must be a full translation unit.
-///
-/// \param[in] name
-///     The name of the function, as used in the text.
 ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope,
-                                           std::string text, std::string name)
+                                           std::string text, std::string name,
+                                           bool enable_debugging)
     : UtilityFunction(
           exe_scope,
-          std::string(ClangExpressionSourceCode::g_expression_prefix) + text,
-          std::move(name)) {}
+          std::string(ClangExpressionSourceCode::g_expression_prefix) + text +
+              std::string(ClangExpressionSourceCode::g_expression_suffix),
+          std::move(name), enable_debugging) {
+  // Write the source code to a file so that LLDB's source manager can display
+  // it when debugging the code.
+  if (enable_debugging) {
+    int temp_fd = -1;
+    llvm::SmallString<128> result_path;
+    llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path);
+    if (temp_fd != -1) {
+      lldb_private::NativeFile file(temp_fd, File::eOpenOptionWrite, true);
+      text = "#line 1 \"" + std::string(result_path) + "\"\n" + text;
+      size_t bytes_written = text.size();
+      file.Write(text.c_str(), bytes_written);
+      if (bytes_written == text.size()) {
+        // If we successfully wrote the source to a temporary file, replace the
+        // function text with the next text containing the line directive.
+        m_function_text =
+            std::string(ClangExpressionSourceCode::g_expression_prefix) + text +
+            std::string(ClangExpressionSourceCode::g_expression_suffix);
+      }
+      file.Close();
+    }
+  }
+}
 
 ClangUtilityFunction::~ClangUtilityFunction() {}
 

diff  --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
index 7914e1406cd0..785f86e95711 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
@@ -48,8 +48,11 @@ class ClangUtilityFunction : public UtilityFunction {
   ///
   /// \param[in] name
   ///     The name of the function, as used in the text.
+  ///
+  /// \param[in] enable_debugging
+  ///     Enable debugging of this function.
   ClangUtilityFunction(ExecutionContextScope &exe_scope, std::string text,
-                       std::string name);
+                       std::string name, bool enable_debugging);
 
   ~ClangUtilityFunction() override;
 

diff  --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index e26515789d0f..c94cb8d16ee9 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -9718,7 +9718,8 @@ ScratchTypeSystemClang::CreateUtilityFunction(std::string text,
     return {};
 
   return std::make_unique<ClangUtilityFunction>(
-      *target_sp.get(), std::move(text), std::move(name));
+      *target_sp.get(), std::move(text), std::move(name),
+      target_sp->GetDebugUtilityExpression());
 }
 
 PersistentExpressionState *

diff  --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index da47d8eeac62..38e13e1287bf 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -4307,6 +4307,17 @@ void TargetProperties::DisableSTDIOValueChangedCallback() {
     m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDisableSTDIO);
 }
 
+bool TargetProperties::GetDebugUtilityExpression() const {
+  const uint32_t idx = ePropertyDebugUtilityExpression;
+  return m_collection_sp->GetPropertyAtIndexAsBoolean(
+      nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+}
+
+void TargetProperties::SetDebugUtilityExpression(bool debug) {
+  const uint32_t idx = ePropertyDebugUtilityExpression;
+  m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, debug);
+}
+
 // Target::TargetEventData
 
 Target::TargetEventData::TargetEventData(const lldb::TargetSP &target_sp)

diff  --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index 2d6a4358082a..030c0a7917e8 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -172,6 +172,9 @@ let Definition = "target" in {
   def AutoInstallMainExecutable: Property<"auto-install-main-executable", "Boolean">,
     DefaultTrue,
     Desc<"Always install the main executable when connected to a remote platform.">;
+  def DebugUtilityExpression: Property<"debug-utility-expression", "Boolean">,
+    DefaultFalse,
+    Desc<"Enable debugging of LLDB-internal utility expressions.">;
 }
 
 let Definition = "process_experimental" in {


        


More information about the lldb-commits mailing list