Skip to content

[LLDB] Refactored CPlusPlusLanguage::MethodName to break lldb-server dependencies #132274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 9, 2025

Conversation

slydiman
Copy link
Contributor

@slydiman slydiman commented Mar 20, 2025

This patch addresses the issue #129543.
After this patch the size of lldb-server is reduced by 9MB.

Co-authored-by: @bulbazord Alex Langford

@slydiman slydiman added the lldb label Mar 20, 2025
@slydiman slydiman requested review from bulbazord and labath March 20, 2025 19:11
@slydiman slydiman requested a review from JDevlieghere as a code owner March 20, 2025 19:11
@llvmbot
Copy link
Member

llvmbot commented Mar 20, 2025

@llvm/pr-subscribers-lldb

Author: Dmitry Vasilyev (slydiman)

Changes

This patch addresses the issue #129543.

lldb/source/Core/Module.cpp uses few static helpers and the class CPlusPlusLanguage::MethodName from the CPlusPlusLanguage plug-in. The CPlusPlusLanguage plug-in depends on other plug-ins. This causes many plugins linking, including TypeSystemClang and a lot of clang code.

After this patch the size of lldb-server is reduced by 9MB.


Full diff: https://github.com/llvm/llvm-project/pull/132274.diff

3 Files Affected:

  • (modified) lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt (+1)
  • (modified) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp (-264)
  • (added) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguageMethod.cpp (+279)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index ccdc4d0ae99b3..5b866ee8edc02 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -2,6 +2,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
   BlockPointer.cpp
   Coroutines.cpp
   CPlusPlusLanguage.cpp
+  CPlusPlusLanguageMethod.cpp
   CPlusPlusNameParser.cpp
   CxxStringTypes.cpp
   GenericBitset.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 4b045d12ad494..2696fa87fafbf 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -36,7 +36,6 @@
 #include "lldb/ValueObject/ValueObjectVariable.h"
 
 #include "BlockPointer.h"
-#include "CPlusPlusNameParser.h"
 #include "Coroutines.h"
 #include "CxxStringTypes.h"
 #include "Generic.h"
@@ -44,7 +43,6 @@
 #include "LibCxxAtomic.h"
 #include "LibCxxVariant.h"
 #include "LibStdcpp.h"
-#include "MSVCUndecoratedNameParser.h"
 #include "lldb/lldb-enumerations.h"
 
 using namespace lldb;
@@ -106,74 +104,6 @@ Language *CPlusPlusLanguage::CreateInstance(lldb::LanguageType language) {
   return nullptr;
 }
 
-void CPlusPlusLanguage::MethodName::Clear() {
-  m_full.Clear();
-  m_basename = llvm::StringRef();
-  m_context = llvm::StringRef();
-  m_arguments = llvm::StringRef();
-  m_qualifiers = llvm::StringRef();
-  m_return_type = llvm::StringRef();
-  m_parsed = false;
-  m_parse_error = false;
-}
-
-static bool ReverseFindMatchingChars(const llvm::StringRef &s,
-                                     const llvm::StringRef &left_right_chars,
-                                     size_t &left_pos, size_t &right_pos,
-                                     size_t pos = llvm::StringRef::npos) {
-  assert(left_right_chars.size() == 2);
-  left_pos = llvm::StringRef::npos;
-  const char left_char = left_right_chars[0];
-  const char right_char = left_right_chars[1];
-  pos = s.find_last_of(left_right_chars, pos);
-  if (pos == llvm::StringRef::npos || s[pos] == left_char)
-    return false;
-  right_pos = pos;
-  uint32_t depth = 1;
-  while (pos > 0 && depth > 0) {
-    pos = s.find_last_of(left_right_chars, pos);
-    if (pos == llvm::StringRef::npos)
-      return false;
-    if (s[pos] == left_char) {
-      if (--depth == 0) {
-        left_pos = pos;
-        return left_pos < right_pos;
-      }
-    } else if (s[pos] == right_char) {
-      ++depth;
-    }
-  }
-  return false;
-}
-
-static bool IsTrivialBasename(const llvm::StringRef &basename) {
-  // Check that the basename matches with the following regular expression
-  // "^~?([A-Za-z_][A-Za-z_0-9]*)$" We are using a hand written implementation
-  // because it is significantly more efficient then using the general purpose
-  // regular expression library.
-  size_t idx = 0;
-  if (basename.starts_with('~'))
-    idx = 1;
-
-  if (basename.size() <= idx)
-    return false; // Empty string or "~"
-
-  if (!std::isalpha(basename[idx]) && basename[idx] != '_')
-    return false; // First character (after removing the possible '~'') isn't in
-                  // [A-Za-z_]
-
-  // Read all characters matching [A-Za-z_0-9]
-  ++idx;
-  while (idx < basename.size()) {
-    if (!std::isalnum(basename[idx]) && basename[idx] != '_')
-      break;
-    ++idx;
-  }
-
-  // We processed all characters. It is a vaild basename.
-  return idx == basename.size();
-}
-
 /// Writes out the function name in 'full_name' to 'out_stream'
 /// but replaces each argument type with the variable name
 /// and the corresponding pretty-printed value
@@ -208,206 +138,12 @@ static bool PrettyPrintFunctionNameWithArgs(Stream &out_stream,
   return true;
 }
 
-bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
-  // This method tries to parse simple method definitions which are presumably
-  // most comman in user programs. Definitions that can be parsed by this
-  // function don't have return types and templates in the name.
-  // A::B::C::fun(std::vector<T> &) const
-  size_t arg_start, arg_end;
-  llvm::StringRef full(m_full.GetCString());
-  llvm::StringRef parens("()", 2);
-  if (ReverseFindMatchingChars(full, parens, arg_start, arg_end)) {
-    m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
-    if (arg_end + 1 < full.size())
-      m_qualifiers = full.substr(arg_end + 1).ltrim();
-
-    if (arg_start == 0)
-      return false;
-    size_t basename_end = arg_start;
-    size_t context_start = 0;
-    size_t context_end = full.rfind(':', basename_end);
-    if (context_end == llvm::StringRef::npos)
-      m_basename = full.substr(0, basename_end);
-    else {
-      if (context_start < context_end)
-        m_context = full.substr(context_start, context_end - 1 - context_start);
-      const size_t basename_begin = context_end + 1;
-      m_basename = full.substr(basename_begin, basename_end - basename_begin);
-    }
-
-    if (IsTrivialBasename(m_basename)) {
-      return true;
-    } else {
-      // The C++ basename doesn't match our regular expressions so this can't
-      // be a valid C++ method, clear everything out and indicate an error
-      m_context = llvm::StringRef();
-      m_basename = llvm::StringRef();
-      m_arguments = llvm::StringRef();
-      m_qualifiers = llvm::StringRef();
-      m_return_type = llvm::StringRef();
-      return false;
-    }
-  }
-  return false;
-}
-
-void CPlusPlusLanguage::MethodName::Parse() {
-  if (!m_parsed && m_full) {
-    if (TrySimplifiedParse()) {
-      m_parse_error = false;
-    } else {
-      CPlusPlusNameParser parser(m_full.GetStringRef());
-      if (auto function = parser.ParseAsFunctionDefinition()) {
-        m_basename = function->name.basename;
-        m_context = function->name.context;
-        m_arguments = function->arguments;
-        m_qualifiers = function->qualifiers;
-        m_return_type = function->return_type;
-        m_parse_error = false;
-      } else {
-        m_parse_error = true;
-      }
-    }
-    m_parsed = true;
-  }
-}
-
-llvm::StringRef CPlusPlusLanguage::MethodName::GetBasename() {
-  if (!m_parsed)
-    Parse();
-  return m_basename;
-}
-
-llvm::StringRef CPlusPlusLanguage::MethodName::GetContext() {
-  if (!m_parsed)
-    Parse();
-  return m_context;
-}
-
-llvm::StringRef CPlusPlusLanguage::MethodName::GetArguments() {
-  if (!m_parsed)
-    Parse();
-  return m_arguments;
-}
-
-llvm::StringRef CPlusPlusLanguage::MethodName::GetQualifiers() {
-  if (!m_parsed)
-    Parse();
-  return m_qualifiers;
-}
-
-llvm::StringRef CPlusPlusLanguage::MethodName::GetReturnType() {
-  if (!m_parsed)
-    Parse();
-  return m_return_type;
-}
-
-std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
-  if (!m_parsed)
-    Parse();
-  if (m_context.empty())
-    return std::string(m_basename);
-
-  std::string res;
-  res += m_context;
-  res += "::";
-  res += m_basename;
-  return res;
-}
-
-llvm::StringRef
-CPlusPlusLanguage::MethodName::GetBasenameNoTemplateParameters() {
-  llvm::StringRef basename = GetBasename();
-  size_t arg_start, arg_end;
-  llvm::StringRef parens("<>", 2);
-  if (ReverseFindMatchingChars(basename, parens, arg_start, arg_end))
-    return basename.substr(0, arg_start);
-
-  return basename;
-}
-
-bool CPlusPlusLanguage::MethodName::ContainsPath(llvm::StringRef path) {
-  if (!m_parsed)
-    Parse();
-
-  // If we can't parse the incoming name, then just check that it contains path.
-  if (m_parse_error)
-    return m_full.GetStringRef().contains(path);
-
-  llvm::StringRef identifier;
-  llvm::StringRef context;
-  std::string path_str = path.str();
-  bool success = CPlusPlusLanguage::ExtractContextAndIdentifier(
-      path_str.c_str(), context, identifier);
-  if (!success)
-    return m_full.GetStringRef().contains(path);
-
-  // Basename may include template arguments.
-  // E.g.,
-  // GetBaseName(): func<int>
-  // identifier   : func
-  //
-  // ...but we still want to account for identifiers with template parameter
-  // lists, e.g., when users set breakpoints on template specializations.
-  //
-  // E.g.,
-  // GetBaseName(): func<uint32_t>
-  // identifier   : func<int32_t*>
-  //
-  // Try to match the basename with or without template parameters.
-  if (GetBasename() != identifier &&
-      GetBasenameNoTemplateParameters() != identifier)
-    return false;
-
-  // Incoming path only had an identifier, so we match.
-  if (context.empty())
-    return true;
-  // Incoming path has context but this method does not, no match.
-  if (m_context.empty())
-    return false;
-
-  llvm::StringRef haystack = m_context;
-  if (!haystack.consume_back(context))
-    return false;
-  if (haystack.empty() || !isalnum(haystack.back()))
-    return true;
-
-  return false;
-}
-
-bool CPlusPlusLanguage::IsCPPMangledName(llvm::StringRef name) {
-  // FIXME!! we should really run through all the known C++ Language plugins
-  // and ask each one if this is a C++ mangled name
-
-  Mangled::ManglingScheme scheme = Mangled::GetManglingScheme(name);
-
-  if (scheme == Mangled::eManglingSchemeNone)
-    return false;
-
-  return true;
-}
-
 bool CPlusPlusLanguage::DemangledNameContainsPath(llvm::StringRef path,
                                                   ConstString demangled) const {
   MethodName demangled_name(demangled);
   return demangled_name.ContainsPath(path);
 }
 
-bool CPlusPlusLanguage::ExtractContextAndIdentifier(
-    const char *name, llvm::StringRef &context, llvm::StringRef &identifier) {
-  if (MSVCUndecoratedNameParser::IsMSVCUndecoratedName(name))
-    return MSVCUndecoratedNameParser::ExtractContextAndIdentifier(name, context,
-                                                                  identifier);
-
-  CPlusPlusNameParser parser(name);
-  if (auto full_name = parser.ParseAsFullName()) {
-    identifier = full_name->basename;
-    context = full_name->context;
-    return true;
-  }
-  return false;
-}
-
 namespace {
 class NodeAllocator {
   llvm::BumpPtrAllocator Alloc;
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguageMethod.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguageMethod.cpp
new file mode 100644
index 0000000000000..cd22b784de019
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguageMethod.cpp
@@ -0,0 +1,279 @@
+//===-- CPlusPlusLanguageMethod.cpp ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CPlusPlusLanguage.h"
+
+#include "lldb/Core/Mangled.h"
+
+#include "CPlusPlusNameParser.h"
+#include "MSVCUndecoratedNameParser.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void CPlusPlusLanguage::MethodName::Clear() {
+  m_full.Clear();
+  m_basename = llvm::StringRef();
+  m_context = llvm::StringRef();
+  m_arguments = llvm::StringRef();
+  m_qualifiers = llvm::StringRef();
+  m_return_type = llvm::StringRef();
+  m_parsed = false;
+  m_parse_error = false;
+}
+
+static bool ReverseFindMatchingChars(const llvm::StringRef &s,
+                                     const llvm::StringRef &left_right_chars,
+                                     size_t &left_pos, size_t &right_pos,
+                                     size_t pos = llvm::StringRef::npos) {
+  assert(left_right_chars.size() == 2);
+  left_pos = llvm::StringRef::npos;
+  const char left_char = left_right_chars[0];
+  const char right_char = left_right_chars[1];
+  pos = s.find_last_of(left_right_chars, pos);
+  if (pos == llvm::StringRef::npos || s[pos] == left_char)
+    return false;
+  right_pos = pos;
+  uint32_t depth = 1;
+  while (pos > 0 && depth > 0) {
+    pos = s.find_last_of(left_right_chars, pos);
+    if (pos == llvm::StringRef::npos)
+      return false;
+    if (s[pos] == left_char) {
+      if (--depth == 0) {
+        left_pos = pos;
+        return left_pos < right_pos;
+      }
+    } else if (s[pos] == right_char) {
+      ++depth;
+    }
+  }
+  return false;
+}
+
+static bool IsTrivialBasename(const llvm::StringRef &basename) {
+  // Check that the basename matches with the following regular expression
+  // "^~?([A-Za-z_][A-Za-z_0-9]*)$" We are using a hand written implementation
+  // because it is significantly more efficient then using the general purpose
+  // regular expression library.
+  size_t idx = 0;
+  if (basename.starts_with('~'))
+    idx = 1;
+
+  if (basename.size() <= idx)
+    return false; // Empty string or "~"
+
+  if (!std::isalpha(basename[idx]) && basename[idx] != '_')
+    return false; // First character (after removing the possible '~'') isn't in
+                  // [A-Za-z_]
+
+  // Read all characters matching [A-Za-z_0-9]
+  ++idx;
+  while (idx < basename.size()) {
+    if (!std::isalnum(basename[idx]) && basename[idx] != '_')
+      break;
+    ++idx;
+  }
+
+  // We processed all characters. It is a vaild basename.
+  return idx == basename.size();
+}
+
+bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
+  // This method tries to parse simple method definitions which are presumably
+  // most comman in user programs. Definitions that can be parsed by this
+  // function don't have return types and templates in the name.
+  // A::B::C::fun(std::vector<T> &) const
+  size_t arg_start, arg_end;
+  llvm::StringRef full(m_full.GetCString());
+  llvm::StringRef parens("()", 2);
+  if (ReverseFindMatchingChars(full, parens, arg_start, arg_end)) {
+    m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
+    if (arg_end + 1 < full.size())
+      m_qualifiers = full.substr(arg_end + 1).ltrim();
+
+    if (arg_start == 0)
+      return false;
+    size_t basename_end = arg_start;
+    size_t context_start = 0;
+    size_t context_end = full.rfind(':', basename_end);
+    if (context_end == llvm::StringRef::npos)
+      m_basename = full.substr(0, basename_end);
+    else {
+      if (context_start < context_end)
+        m_context = full.substr(context_start, context_end - 1 - context_start);
+      const size_t basename_begin = context_end + 1;
+      m_basename = full.substr(basename_begin, basename_end - basename_begin);
+    }
+
+    if (IsTrivialBasename(m_basename)) {
+      return true;
+    } else {
+      // The C++ basename doesn't match our regular expressions so this can't
+      // be a valid C++ method, clear everything out and indicate an error
+      m_context = llvm::StringRef();
+      m_basename = llvm::StringRef();
+      m_arguments = llvm::StringRef();
+      m_qualifiers = llvm::StringRef();
+      m_return_type = llvm::StringRef();
+      return false;
+    }
+  }
+  return false;
+}
+
+void CPlusPlusLanguage::MethodName::Parse() {
+  if (!m_parsed && m_full) {
+    if (TrySimplifiedParse()) {
+      m_parse_error = false;
+    } else {
+      CPlusPlusNameParser parser(m_full.GetStringRef());
+      if (auto function = parser.ParseAsFunctionDefinition()) {
+        m_basename = function->name.basename;
+        m_context = function->name.context;
+        m_arguments = function->arguments;
+        m_qualifiers = function->qualifiers;
+        m_return_type = function->return_type;
+        m_parse_error = false;
+      } else {
+        m_parse_error = true;
+      }
+    }
+    m_parsed = true;
+  }
+}
+
+llvm::StringRef CPlusPlusLanguage::MethodName::GetBasename() {
+  if (!m_parsed)
+    Parse();
+  return m_basename;
+}
+
+llvm::StringRef CPlusPlusLanguage::MethodName::GetContext() {
+  if (!m_parsed)
+    Parse();
+  return m_context;
+}
+
+llvm::StringRef CPlusPlusLanguage::MethodName::GetArguments() {
+  if (!m_parsed)
+    Parse();
+  return m_arguments;
+}
+
+llvm::StringRef CPlusPlusLanguage::MethodName::GetQualifiers() {
+  if (!m_parsed)
+    Parse();
+  return m_qualifiers;
+}
+
+llvm::StringRef CPlusPlusLanguage::MethodName::GetReturnType() {
+  if (!m_parsed)
+    Parse();
+  return m_return_type;
+}
+
+std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
+  if (!m_parsed)
+    Parse();
+  if (m_context.empty())
+    return std::string(m_basename);
+
+  std::string res;
+  res += m_context;
+  res += "::";
+  res += m_basename;
+  return res;
+}
+
+llvm::StringRef
+CPlusPlusLanguage::MethodName::GetBasenameNoTemplateParameters() {
+  llvm::StringRef basename = GetBasename();
+  size_t arg_start, arg_end;
+  llvm::StringRef parens("<>", 2);
+  if (ReverseFindMatchingChars(basename, parens, arg_start, arg_end))
+    return basename.substr(0, arg_start);
+
+  return basename;
+}
+
+bool CPlusPlusLanguage::MethodName::ContainsPath(llvm::StringRef path) {
+  if (!m_parsed)
+    Parse();
+
+  // If we can't parse the incoming name, then just check that it contains path.
+  if (m_parse_error)
+    return m_full.GetStringRef().contains(path);
+
+  llvm::StringRef identifier;
+  llvm::StringRef context;
+  std::string path_str = path.str();
+  bool success = CPlusPlusLanguage::ExtractContextAndIdentifier(
+      path_str.c_str(), context, identifier);
+  if (!success)
+    return m_full.GetStringRef().contains(path);
+
+  // Basename may include template arguments.
+  // E.g.,
+  // GetBaseName(): func<int>
+  // identifier   : func
+  //
+  // ...but we still want to account for identifiers with template parameter
+  // lists, e.g., when users set breakpoints on template specializations.
+  //
+  // E.g.,
+  // GetBaseName(): func<uint32_t>
+  // identifier   : func<int32_t*>
+  //
+  // Try to match the basename with or without template parameters.
+  if (GetBasename() != identifier &&
+      GetBasenameNoTemplateParameters() != identifier)
+    return false;
+
+  // Incoming path only had an identifier, so we match.
+  if (context.empty())
+    return true;
+  // Incoming path has context but this method does not, no match.
+  if (m_context.empty())
+    return false;
+
+  llvm::StringRef haystack = m_context;
+  if (!haystack.consume_back(context))
+    return false;
+  if (haystack.empty() || !isalnum(haystack.back()))
+    return true;
+
+  return false;
+}
+
+bool CPlusPlusLanguage::IsCPPMangledName(llvm::StringRef name) {
+  // FIXME!! we should really run through all the known C++ Language plugins
+  // and ask each one if this is a C++ mangled name
+
+  Mangled::ManglingScheme scheme = Mangled::GetManglingScheme(name);
+
+  if (scheme == Mangled::eManglingSchemeNone)
+    return false;
+
+  return true;
+}
+
+bool CPlusPlusLanguage::ExtractContextAndIdentifier(
+    const char *name, llvm::StringRef &context, llvm::StringRef &identifier) {
+  if (MSVCUndecoratedNameParser::IsMSVCUndecoratedName(name))
+    return MSVCUndecoratedNameParser::ExtractContextAndIdentifier(name, context,
+                                                                  identifier);
+
+  CPlusPlusNameParser parser(name);
+  if (auto full_name = parser.ParseAsFullName()) {
+    identifier = full_name->basename;
+    context = full_name->context;
+    return true;
+  }
+  return false;
+}

@slydiman
Copy link
Contributor Author

After this patch and #131645 the size of lldb-server is reduced from 47MB to 8MB.

@JDevlieghere
Copy link
Member

The patch looks fine but I'm not sure how this actually addresses the issue. I don't think Module should depend on any partiuclar language plugin directly. Can we solve this problem by moving the functionality of that function (Module::LookupInfo::LookupInfo) into the plugin and have Module dispatch this through the usual language plugin mechanism?

@slydiman
Copy link
Contributor Author

I don't think Module should depend on any partiuclar language plugin directly. Can we solve this problem by moving the functionality of that function (Module::LookupInfo::LookupInfo) into the plugin and have Module dispatch this through the usual language plugin mechanism?

CPlusPlusLanguage::IsCPPMangledName() contains the following comment:

  // FIXME!! we should really run through all the known C++ Language plugins
  // and ask each one if this is a C++ mangled name

But I think it is out of scope of this NFC patch.
Note Module::LookupInfo::LookupInfo uses also few ObjCLanguage static helpers. I don't see how Module::LookupInfo::LookupInfo can be moved into a plugin (which one exactly?) I would prefer to move these helpers to Core sources or to a separated library.

@labath
Copy link
Collaborator

labath commented Mar 21, 2025

What kind of a build (OS, compiler, etc.) is this exactly? The fact that moving the functions to a different compile unit actually makes a difference, makes me think that your linker is treating each CU as a monolith, which is definitely not a way to make small binaries. With -ffunction-sections, the linker should be able to pick up just the functions that are required.

@slydiman
Copy link
Contributor Author

slydiman commented Mar 21, 2025

What kind of a build (OS, compiler, etc.) is this exactly?

I used the latest clang from mainline on Windows x86 and Linux x86 hosts. lldb-server is built for Linux Aarch64.

cmake --build . --target install-lldb-server

As I mentioned here #129543 (comment)
lldb-server does not depend on the plugin TypeSystemClang and clang code, but it is linked. The size of the binary will be reduced if TypeSystemClang.cpp is just empty. And there is no any link errors. Actually it is enough to move out only the one static helper CPlusPlusLanguage::IsCPPMangledName() but I have moved all code used by Module.cpp to be sure. So -ffunction-sections works but with some conditions.

@labath
Copy link
Collaborator

labath commented Mar 21, 2025

Okay, and what are those conditions? We could come up with a reasonable way to split this file in two (though I think it'd be better to do what Jonas suggested), but I don't think we can/should rely on those conditions continuing to hold in the face of future changes, if we don't know what they are. And we can't continue splitting files just because someone's compiler/linker makes better code that way.

@slydiman
Copy link
Contributor Author

Okay, and what are those conditions?

I don't know. Probably code fragmentation within CU or number of references makes the linker to link the entire CU.

someone's compiler/linker

Note it is mainline clang/lld.

Moving all code used by Module.cpp to a separated module ensures that there is no unused code in the final binary.

@slydiman
Copy link
Contributor Author

@labath Note I have synced with mainline and something changed. Moving out only 1 function CPlusPlusLanguage::IsCPPMangledName() is not enough anymore to reduce the size of lldb-server. But this patch works fine because moves all code used by Module.cpp. The size of Linux AArch64 lldb-server is 17MB before this patch and 8MB after this patch.

@labath
Copy link
Collaborator

labath commented Mar 25, 2025

Moving out only 1 function CPlusPlusLanguage::IsCPPMangledName() is not enough anymore to reduce the size of lldb-server. But this patch works fine because moves all code used by Module.cpp.

I still don't think we should be doing this, and this is the reason why. It's not a good solution if random perturbations in unrelated code can cause this to work or not.

Note it is mainline clang/lld.

All the more reason to get to the bottom of this. Either we find a bug in the compiler/linker (and make it better for everyone), or we learn what is the property that makes this work (and then we can try to find a way to make it work reliably).

@slydiman
Copy link
Contributor Author

slydiman commented Mar 25, 2025

@labath What do you suggest for a solution? Reducing lldb-server size from 17MB to 8MB is the significant reason to do something. It work reliably if all plug-in code used from the core directly is moved to a separated module. We can even create a subclass CPlusPlusLanguage::Helpers or such.

@labath
Copy link
Collaborator

labath commented Mar 25, 2025

@slydiman
Copy link
Contributor Author

slydiman commented Mar 25, 2025

Note -ffunction-sections -fdata-sections are added in HandleLLVMOptions.cmake and -Wl,--gc-sections is added in AddLLVM.cmake by default. But unused functions will be kept anyway if they contain linker gc roots.
A lot of functions in CPlusPlusLanguage.cpp contain static variables like

CPlusPlusLanguage::GetHardcodedSummaries() {
  static llvm::once_flag g_initialize;

These functions depend on BlockPointer.cpp, BlockPointer.cpp depends on TypeSystemClang.cpp, etc.
How to reproduce:

  1. Build lldb-server (Linux AArch64). The size is 17MB.
  2. Comment out all code in CPlusPlusLanguage.cpp from the line 1532 to the end. lldb-server size is 8MB. So some unused functions were linked and have huge dependencies.
  3. Uncomment the function CPlusPlusLanguage::GetHardcodedSummaries() with static g_formatters and 3 lambdas. lldb-server size is 17MB.
  4. Comment out the 3rd lambda in this function where BlockPointerSummaryProvider is used. lldb-server size is 8MB again.

To avoid changes that may bring the problem back, I suggest to place moved functions to a subclass.

@bulbazord
Copy link
Member

I'm similarly confused about how moving these method definitions into a separate CU makes a difference. +1 to Jonas's suggestion, properly refactoring Module to use language plugins.

For reference, I attempted this a few years ago (albeit on Apple's swift fork) and had trouble getting it working. You can take a look at my attempt here: swiftlang#3240

@slydiman
Copy link
Contributor Author

slydiman commented Mar 25, 2025

I'm similarly confused about how moving these method definitions into a separate CU makes a difference.

Please note Module.cpp uses only few functions which have no extra dependencies. After this patch the new CU CPlusPlusLanguageMethod.cpp with only necessary functions is linked. The rest CPlusPlusLanguage.cpp is not linked at all.
Module.cpp depends on new CPlusPlusLanguageMethod.cpp but nothing depends on updated CPlusPlusLanguage.cpp

@slydiman
Copy link
Contributor Author

slydiman commented Mar 25, 2025

@bulbazord

swiftlang#3240

Looks good.

SwiftLanguageRuntime::MethodName::Parse(). Specifically, as it parses a name, there are some codepaths that cause it to think some names are valid swift method names.

It seems one solution might be to sort language plugins.
But I don't see any profit in enumerating language plugins and then sorting known plugins anyway.
It is possible to add a method for requesting a language plugin significance for sorting.
But it looks like unnecessary complication, IMHO.
Probably the hardcoded and sorted list of language plugins is simple and balanced solution.

@labath
Copy link
Collaborator

labath commented Mar 26, 2025

Note -ffunction-sections -fdata-sections are added in HandleLLVMOptions.cmake and -Wl,--gc-sections is added in AddLLVM.cmake by default. But unused functions will be kept anyway if they contain linker gc roots. A lot of functions in CPlusPlusLanguage.cpp contain static variables like

CPlusPlusLanguage::GetHardcodedSummaries() {
  static llvm::once_flag g_initialize;

I don't think it's as simple as that. I don't see a reason for an function-local static to be a gc root. In fact, when I look at your example (thank you for that), I see that none of the code in BlockPointer.cpp is actually present in the final binary, despite it obviously being somehow implicated in the size increase.

That said, all of this gives me an idea for a plausible explanation: AIUI, linking basically works in two stages. First, you determine which object files are going to be a part of the link. This part works at object file level, and doesn't do any reachability analysis -- if we see an undefined symbol, we pull in the object which defines it.

In the second stage (if --gc-sections is used), we remove any sections/functions which are not reachable from a gc root. Function-local statics should not be a gc root, but file-level globals definitely are. So any code that is reachable from global initializer is kept, even though the file containing the initializer was only referenced through dead code.

Global variables are banned by the coding standards, but I wouldn't be surprised if there were still some around that cause this.

@slydiman
Copy link
Contributor Author

slydiman commented Mar 26, 2025

Global variables are banned by the coding standards, but I wouldn't be surprised if there were still some around that cause this.

TypeSystemClang.cpp contains global char TypeSystemClang::ID; and its constructor is GC root.

The dependencies chain looks like Module.cpp -> CPlusPlusLanguage::ExtractContextAndIdentifier() -> CPlusPlusLanguage.cpp -> CPlusPlusLanguage::GetHardcodedSummaries() -> BlockPointerSummaryProvider -> BlockPointer.cpp -> TypeSystemClang::ID

GC can remove unused CPlusPlusLanguage::GetHardcodedSummaries(), but TypeSystemClang and its dependencies will be kept.

@slydiman
Copy link
Contributor Author

@labath
The repro above shows that CPlusPlusLanguage::GetHardcodedSummaries() causes to link TypeSystemClang and other dependencies. But --print-gc-sections and llvm-objdump --all-headers --demangle lldb-server shows that GetHardcodedSummaries is missing in the final binary. The linker removes unused functions like GetHardcodedSummaries, but the dependencies are linked because of global variables like TypeSystemClang::ID.

So, this patch solves the specific issue by breaking the dependency chain.
Or we should refactor all global variables in all dependencies (lldb, llvm, clang).
Note we have found at least 90 extra gc roots.

@igorkudrin
Copy link
Collaborator

igorkudrin commented Mar 27, 2025

Global variables are banned by the coding standards, but I wouldn't be surprised if there were still some around that cause this.

Despite being banned, global variables with non-trivial constructors are still widely used for command line options.

@labath
Copy link
Collaborator

labath commented Mar 31, 2025

Global variables are banned by the coding standards, but I wouldn't be surprised if there were still some around that cause this.

TypeSystemClang.cpp contains global char TypeSystemClang::ID; and its constructor is GC root.

Constructor of what? The ID static member? It's initialized to zero (by the linker) so it does not have one. TypeSystemClang has a constructor, but it's not a GC root, unless someone actually declares a global variable of that type (and I really hope that's not the case).

Here's a test case that shows that a static member does not prevent a class from being GC-ed:

$ head a.h a.cc c.h c.cc m.cc
==> a.h <==
#include "c.h"
const void *i();
const void *f(Big *);


==> a.cc <==
#include "c.h"

const void *i() { return &Big::ID; }
const void *f(Big *b) { return b->fr(); }

==> c.h <==
#define MUL(x) X(x##q) X(x##w) X(x##e) X(x##r) X(x##t) X(x##y) X(x##u) X(x##i)

class Big {
public:
  static char ID;
#define X(x) virtual const void *x();
  MUL(f);
#undef X
};

==> c.cc <==
#include "c.h"

char Big::ID;
#define X(x) const void *Big::x() { return __PRETTY_FUNCTION__; }
MUL(f);

==> m.cc <==
#include "a.h"

extern "C" void _start() {
#ifdef BIG
  Big big;
  f(&big);
#endif
  i();
}
$ g++ m.cc a.cc c.cc -DBIG -o big.out -nostdlib -fno-rtti -ffunction-sections -fdata-sections -Wl,--gc-sections
$ g++ m.cc a.cc c.cc  -o small.out -nostdlib -fno-rtti -ffunction-sections -fdata-sections -Wl,--gc-sections
$ g++ m.cc a.cc c.cc  -o small-nogc.out -nostdlib -fno-rtti -ffunction-sections -fdata-sections 
$ ls -l *.out
-rwxrwx--- 1 14424 Mar 31 12:17 big.out
-rwxrwx--- 1 14424 Mar 31 12:17 small-nogc.out
-rwxrwx--- 1 13808 Mar 31 12:17 small.out
$ nm small.out | grep _ZN3Big
0000000000004000 B _ZN3Big2IDE
$ nm big.out | grep _ZN3Big
0000000000001092 T _ZN3Big2feEv
0000000000001100 T _ZN3Big2fiEv
0000000000001066 T _ZN3Big2fqEv
00000000000010a8 T _ZN3Big2frEv
00000000000010be T _ZN3Big2ftEv
00000000000010ea T _ZN3Big2fuEv
000000000000107c T _ZN3Big2fwEv
00000000000010d4 T _ZN3Big2fyEv
0000000000004000 B _ZN3Big2IDE

I think there's something else happening here.

Global variables are banned by the coding standards, but I wouldn't be surprised if there were still some around that cause this.

Despite being banned, global variables with non-trivial constructors are still widely used for command line options.

That's true, but the command line library is a low level library in llvm, and it doesn't have any dependencies on the rest of llvm, let alone lldb. So, while these globals may cause us to link in some code that we theoretically do not need, I doubt they're responsible for the majority of the bloat.

@slydiman
Copy link
Contributor Author

I think there's something else happening here.

Ok, it seems the dependency chain is longer:
Module.cpp -> CPlusPlusLanguage::ExtractContextAndIdentifier() ->
CPlusPlusLanguage.cpp ->
BlockPointer.cpp ->
TypeSystemClang.cpp - >
ClangUserExpression.cpp ->
ClangExpressionParser.cpp -> clang::CreateLLVMCodeGen() -> llvm-project/clang/lib/CodeGen/ModuleBuilder.cpp -> ...

Note the function clang::CreateLLVMCodeGen() is missing in the final binary (GC-ed).
We still don't know for sure what the GC root is. It is somewhere in the middle of clang, and I think it is already out of scope.

But we need to somehow break the dependency chain for lldb-server.
We have 2 options:

@slydiman
Copy link
Contributor Author

slydiman commented Apr 1, 2025

@labath

GC roots are

  • llvm/lib/Transforms/Utils/Debugify.cpp: global variables RegisterPass<PassName> -> callDefaultCtor<PassName>()
  • llvm/lib/CodeGen/RegAllocBasic.cpp: global variable basicRegAlloc -> createBasicRegisterAllocator()
  • llvm/lib/CodeGen/RegAllocGreedy.cpp: global variable greedyRegAlloc -> createGreedyRegisterAllocator()
  • etc.

Thanks to @igorkudrin

I think it is out of scope. We must break the dependency chain inside lldb.

@labath
Copy link
Collaborator

labath commented Apr 2, 2025

Okay. The last comment makes sense to me. Thank you for getting to the bottom of this. I fully agree this should be resolved in lldb as lldb-server has no good reason to depend on this code in the first place.

So as far as I am concerned (I can't speak about others), I think something like this could work under two conditions:

  • we make some effort to me this look like other code. What I mainly mean is, each of our cpp files has a header which declares the things defined in that cpp file. I think we should create a matching .h file for the code you're moving here. I guess that means changing MethodName from a nested class to a top-level entity.
  • you don't get to cry foul if some future change causes lldb-server to become large again. Parts of lldb (including the code you're just moving) still depend on clang, so it's possible that a perfectly reasonable change will cause these things to get pulled in again. I don't think it's likely to happen, as this code is pretty stable and isolated, but still... It also doesn't mean you can't complain if someone introduces a new plugin dependency (in fact, I encourage you to do that). However, I don't think it's reasonable to hold up changes to code which is within its right to depend on clang, just because it makes lldb-server larger due to these unresolved dependencies.

That said, I would much very much prefer to resolve this in a proper way, by removing the (direct) dependency on the C++ language plugin. It sounds like swiftlang#3240 is not far from working. As far as I am concerned (I again don't speak for others), the plugin ordering thing could be handled by making sure the plugins are registered in the right order (in cmake).

@slydiman slydiman force-pushed the lldb-server-reduce-size2 branch from cc89498 to 09f889f Compare April 5, 2025 05:55
@slydiman slydiman changed the title [LLDB][NFC] Move CPlusPlusLanguage methods used in Core/Module.cpp to a separated module to break lldb-server dependencies [LLDB] Refactored CPlusPlusLanguage::MethodName to break lldb-server dependencies Apr 5, 2025
@slydiman
Copy link
Contributor Author

slydiman commented Apr 5, 2025

Disabling asserts locally solved the problem with LLVM_DUMP_METHOD. This patch works again.
I have refactored CPlusPlusLanguage::MethodName and RichManglingContext.
I got the lldb-server size 6MB. Please review. Thanks

…dependencies

This patch addresses the issue llvm#129543.
After this patch the size of lldb-server is reduced by 9MB.

Co-authored-by: @bulbazord Alex Langford
@slydiman slydiman force-pushed the lldb-server-reduce-size2 branch from 09f889f to 40d69ed Compare April 5, 2025 06:27
Copy link
Collaborator

@labath labath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the version a lot, but I'd like to leave to final approval to @bulbazord and/or @JDevlieghere.

Comment on lines 229 to 235
if (ObjCLanguage::IsPossibleObjCMethodName(name.GetCString())) {
func_name_type = eFunctionNameTypeFull;
}

if (ObjCLanguage::IsPossibleObjCSelector(name.GetCString())) {
func_name_type |= eFunctionNameTypeSelector;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comes from Alex's patch. Updated.

@slydiman
Copy link
Contributor Author

slydiman commented Apr 8, 2025

Maybe rename CPlusPlusLanguage::CPPMethodName to CPlusPlusLanguage::CxxMethodName?
Any preferences?

Copy link
Member

@JDevlieghere JDevlieghere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for bearing with us. This LGTM modulo inline comments.

@@ -246,6 +246,8 @@ class Mangled {
/// for s, otherwise the enumerator for the mangling scheme detected.
static Mangled::ManglingScheme GetManglingScheme(llvm::StringRef const name);

static bool IsCPPMangledName(llvm::StringRef name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about calling this IsMangledName and. dropping the CPP/Cxx part altogether? Confusingly the implementation isn't actually checking if the mangling scheme is Itanium, so. this will fire too for Rust and Swift. Maybe something (like Rust) is relying on that, I don't know.

Suggested change
static bool IsCPPMangledName(llvm::StringRef name);
static bool IsMangledName(llvm::StringRef name);

That would also provide some parity with this oddly named helper function:

static inline bool cstring_is_mangled(llvm::StringRef s) {
  return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone;
}

The current name makes it look like it should really belong in the C++ language plugin, where it was previously.

Comment on lines -74 to -75
lldbPluginCPlusPlusLanguage
lldbPluginObjCLanguage
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can now add NO_PLUGIN_DEPENDENCIES to add_lldb_library above and resolve the FIXME. 🥳

Added NO_PLUGIN_DEPENDENCIES.
@slydiman slydiman force-pushed the lldb-server-reduce-size2 branch from 72702af to e43c31e Compare April 8, 2025 19:15
@slydiman slydiman merged commit fbc6241 into llvm:main Apr 9, 2025
10 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Apr 9, 2025

LLVM Buildbot has detected a new failure on builder lldb-aarch64-windows running on linaro-armv8-windows-msvc-05 while building lldb at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/141/builds/7726

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: lang/cpp/default-template-args/TestDefaultTemplateArgs.py (786 of 2113)
PASS: lldb-api :: lang/cpp/dereferencing_references/TestCPPDereferencingReferences.py (787 of 2113)
PASS: lldb-api :: lang/cpp/dynamic-value-same-basename/TestDynamicValueSameBase.py (788 of 2113)
PASS: lldb-api :: lang/cpp/diamond/TestCppDiamond.py (789 of 2113)
PASS: lldb-api :: lang/cpp/dynamic-value/TestCppValueCast.py (790 of 2113)
UNSUPPORTED: lldb-api :: lang/cpp/dynamic-value/TestDynamicValue.py (791 of 2113)
PASS: lldb-api :: lang/cpp/elaborated-types/TestElaboratedTypes.py (792 of 2113)
UNSUPPORTED: lldb-api :: lang/cpp/enum_types/TestCPP11EnumTypes.py (793 of 2113)
PASS: lldb-api :: lang/cpp/enum_promotion/TestCPPEnumPromotion.py (794 of 2113)
UNSUPPORTED: lldb-api :: lang/cpp/exceptions/TestCPPExceptionBreakpoints.py (795 of 2113)
FAIL: lldb-api :: lang/cpp/extern_c/TestExternCSymbols.py (796 of 2113)
******************** TEST 'lldb-api :: lang/cpp/extern_c/TestExternCSymbols.py' FAILED ********************
Script:
--
C:/Users/tcwg/scoop/apps/python/current/python.exe C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/llvm-project/lldb\test\API\dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./lib --env LLVM_INCLUDE_DIR=C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/include --env LLVM_TOOLS_DIR=C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin --arch aarch64 --build-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/lldb-test-build.noindex --lldb-module-cache-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/lldb-test-build.noindex/module-cache-lldb\lldb-api --clang-module-cache-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/lldb-test-build.noindex/module-cache-clang\lldb-api --executable C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin/lldb.exe --compiler C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin/clang.exe --dsymutil C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin/dsymutil.exe --make C:/Users/tcwg/scoop/shims/make.exe --llvm-tools-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin --lldb-obj-root C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/tools/lldb --lldb-libs-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./lib --skip-category=watchpoint C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\test\API\lang\cpp\extern_c -p TestExternCSymbols.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision fbc6241d3af45d74ac8e8d3728a57435aab1d5ec)
  clang revision fbc6241d3af45d74ac8e8d3728a57435aab1d5ec
  llvm revision fbc6241d3af45d74ac8e8d3728a57435aab1d5ec
Skipping the following test categories: ['watchpoint', 'libc++', 'libstdcxx', 'dwo', 'dsym', 'gmodules', 'debugserver', 'objc', 'fork', 'pexpect']


--
Command Output (stderr):
--
UNSUPPORTED: LLDB (C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\bin\clang.exe-aarch64) :: test_dsym (lldbsuite.test.lldbtest.TestExternCSymbols.test_dsym) (test case does not fall in any category of interest for this run) 

FAIL: LLDB (C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\bin\clang.exe-aarch64) :: test_dwarf (lldbsuite.test.lldbtest.TestExternCSymbols.test_dwarf)

UNSUPPORTED: LLDB (C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\bin\clang.exe-aarch64) :: test_dwo (lldbsuite.test.lldbtest.TestExternCSymbols.test_dwo) (test case does not fall in any category of interest for this run) 

======================================================================

FAIL: test_dwarf (lldbsuite.test.lldbtest.TestExternCSymbols.test_dwarf)

----------------------------------------------------------------------

Traceback (most recent call last):

  File "C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\packages\Python\lldbsuite\test\lldbtest.py", line 1804, in test_method

    return attrvalue(self)

           ^^^^^^^^^^^^^^^


DavidSpickett added a commit that referenced this pull request Apr 9, 2025
…-server dependencies" (#134995)

Reverts #132274

Broke a test on LLDB Widows on Arm:
https://lab.llvm.org/buildbot/#/builders/141/builds/7726
```
FAIL: test_dwarf (lldbsuite.test.lldbtest.TestExternCSymbols.test_dwarf)
<...>
    self.assertTrue(self.res.Succeeded(), msg + output)

AssertionError: False is not true : Command 'expression -- foo()' did not return successfully

Error output:

error: Couldn't look up symbols:

  int foo(void)

Hint: The expression tried to call a function that is not present in the target, perhaps because it was optimized out by the compiler.
```
@DavidSpickett
Copy link
Collaborator

The above failure is legit, this is the relevant bit of the log:

FAIL: test_dwarf (lldbsuite.test.lldbtest.TestExternCSymbols.test_dwarf)

----------------------------------------------------------------------

Traceback (most recent call last):

  File "C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\packages\Python\lldbsuite\test\lldbtest.py", line 1804, in test_method

    return attrvalue(self)

           ^^^^^^^^^^^^^^^

  File "C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\packages\Python\lldbsuite\test\lldbinline.py", line 122, in _test

    self.do_test()

  File "C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\packages\Python\lldbsuite\test\lldbinline.py", line 152, in do_test

    parser.handle_breakpoint(self, bp_id)

  File "C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\packages\Python\lldbsuite\test\lldbinline.py", line 82, in handle_breakpoint

    test.execute_user_command(breakpoint["command"])

  File "C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\packages\Python\lldbsuite\test\lldbinline.py", line 125, in execute_user_command

    exec(__command, globals(), locals())

  File "<string>", line 1, in <module>

  File "C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\packages\Python\lldbsuite\test\lldbtest.py", line 2406, in expect

    self.runCmd(

  File "C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\packages\Python\lldbsuite\test\lldbtest.py", line 1005, in runCmd

    self.assertTrue(self.res.Succeeded(), msg + output)

AssertionError: False is not true : Command 'expression -- foo()' did not return successfully

Error output:

error: Couldn't look up symbols:

  int foo(void)

Hint: The expression tried to call a function that is not present in the target, perhaps because it was optimized out by the compiler.

No idea why at the moment, I have some other issues to deal with before I can look into it.

@Michael137
Copy link
Member

FYI, this also broke the TestObjCBreakpoints.py test on arm64 macOS:

FAIL: LLDB (/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang-arm64) :: test_break_dwarf (TestObjCBreakpoints.TestObjCBreakpoints)
UNSUPPORTED: LLDB (/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang-arm64) :: test_break_dwo (TestObjCBreakpoints.TestObjCBreakpoints) (test case does not fall in any category of interest for this run) 
Restore dir to: /Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/tools/lldb/test
======================================================================
FAIL: test_break_dsym (TestObjCBreakpoints.TestObjCBreakpoints)
   Test setting Objective-C specific breakpoints (DWARF in .o files).
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1804, in test_method
    return attrvalue(self)
  File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/breakpoint/objc/TestObjCBreakpoints.py", line 21, in test_break
    self.check_objc_breakpoints(False)
  File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/breakpoint/objc/TestObjCBreakpoints.py", line 100, in check_objc_breakpoints
    self.assertGreaterEqual(
AssertionError: 10 not greater than or equal to 87 : Make sure we get at least the same amount of breakpoints if not more when setting by name "count"
Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang
======================================================================
FAIL: test_break_dwarf (TestObjCBreakpoints.TestObjCBreakpoints)
   Test setting Objective-C specific breakpoints (DWARF in .o files).
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1804, in test_method
    return attrvalue(self)
  File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/breakpoint/objc/TestObjCBreakpoints.py", line 21, in test_break
    self.check_objc_breakpoints(False)
  File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/breakpoint/objc/TestObjCBreakpoints.py", line 100, in check_objc_breakpoints
    self.assertGreaterEqual(
AssertionError: 10 not greater than or equal to 86 : Make sure we get at least the same amount of breakpoints if not more when setting by name "count"
Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang
----------------------------------------------------------------------
Ran 3 tests in 1.064s

@slydiman
Copy link
Contributor Author

slydiman commented Apr 9, 2025

I'm looking on it.

llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Apr 9, 2025
… break lldb-server dependencies" (#134995)

Reverts llvm/llvm-project#132274

Broke a test on LLDB Widows on Arm:
https://lab.llvm.org/buildbot/#/builders/141/builds/7726
```
FAIL: test_dwarf (lldbsuite.test.lldbtest.TestExternCSymbols.test_dwarf)
<...>
    self.assertTrue(self.res.Succeeded(), msg + output)

AssertionError: False is not true : Command 'expression -- foo()' did not return successfully

Error output:

error: Couldn't look up symbols:

  int foo(void)

Hint: The expression tried to call a function that is not present in the target, perhaps because it was optimized out by the compiler.
```
slydiman added a commit to slydiman/llvm-project that referenced this pull request Apr 9, 2025
slydiman added a commit to slydiman/llvm-project that referenced this pull request Apr 9, 2025
slydiman added a commit to slydiman/llvm-project that referenced this pull request Apr 9, 2025
…-server dependencies

The original PR is llvm#132274.

Co-authored-by: @bulbazord Alex Langford
slydiman added a commit to slydiman/llvm-project that referenced this pull request Apr 10, 2025
…-server dependencies

The original PR is llvm#132274.

Co-authored-by: @bulbazord Alex Langford
AllinLeeYL pushed a commit to AllinLeeYL/llvm-project that referenced this pull request Apr 10, 2025
…-server dependencies" (llvm#134995)

Reverts llvm#132274

Broke a test on LLDB Widows on Arm:
https://lab.llvm.org/buildbot/#/builders/141/builds/7726
```
FAIL: test_dwarf (lldbsuite.test.lldbtest.TestExternCSymbols.test_dwarf)
<...>
    self.assertTrue(self.res.Succeeded(), msg + output)

AssertionError: False is not true : Command 'expression -- foo()' did not return successfully

Error output:

error: Couldn't look up symbols:

  int foo(void)

Hint: The expression tried to call a function that is not present in the target, perhaps because it was optimized out by the compiler.
```
slydiman added a commit that referenced this pull request Apr 14, 2025
…-server dependencies (#135033)

The original PR is #132274.

Co-authored-by: @bulbazord Alex Langford
var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
…dependencies (llvm#132274)

This patch addresses the issue llvm#129543.
After this patch the size of lldb-server is reduced by 9MB.

Co-authored-by: @bulbazord Alex Langford
var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
…-server dependencies" (llvm#134995)

Reverts llvm#132274

Broke a test on LLDB Widows on Arm:
https://lab.llvm.org/buildbot/#/builders/141/builds/7726
```
FAIL: test_dwarf (lldbsuite.test.lldbtest.TestExternCSymbols.test_dwarf)
<...>
    self.assertTrue(self.res.Succeeded(), msg + output)

AssertionError: False is not true : Command 'expression -- foo()' did not return successfully

Error output:

error: Couldn't look up symbols:

  int foo(void)

Hint: The expression tried to call a function that is not present in the target, perhaps because it was optimized out by the compiler.
```
var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
…-server dependencies (llvm#135033)

The original PR is llvm#132274.

Co-authored-by: @bulbazord Alex Langford
@slydiman slydiman deleted the lldb-server-reduce-size2 branch April 18, 2025 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants