spyffe updated this revision to Diff 99211.
spyffe added a comment.

Used `CFLAGS_EXTRAS` instead of `CFLAGS` at Greg Clayton's suggestion.


https://reviews.llvm.org/D33083

Files:
  include/lldb/Symbol/SymbolContext.h
  packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Makefile
  packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One.mk
  packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One/One.c
  packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One/One.h
  packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One/OneConstant.c
  
packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py
  packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two.mk
  packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two/Two.c
  packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two/Two.h
  packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two/TwoConstant.c
  packages/Python/lldbsuite/test/lang/c/conflicting-symbol/main.c
  source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
  source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
  source/Symbol/SymbolContext.cpp

Index: source/Symbol/SymbolContext.cpp
===================================================================
--- source/Symbol/SymbolContext.cpp
+++ source/Symbol/SymbolContext.cpp
@@ -799,6 +799,163 @@
   return true;
 }
 
+const Symbol *
+SymbolContext::FindBestGlobalDataSymbol(const ConstString &name, Status &error) {
+  error.Clear();
+  
+  if (!target_sp) {
+    return nullptr;
+  }
+  
+  Target &target = *target_sp;
+  Module *module = module_sp.get();
+  
+  auto ProcessMatches = [this, &name, &target, module]
+  (SymbolContextList &sc_list, Status &error) -> const Symbol* {
+    llvm::SmallVector<const Symbol *, 1> external_symbols;
+    llvm::SmallVector<const Symbol *, 1> internal_symbols;
+    const uint32_t matches = sc_list.GetSize();
+    for (uint32_t i = 0; i < matches; ++i) {
+      SymbolContext sym_ctx;
+      sc_list.GetContextAtIndex(i, sym_ctx);
+      if (sym_ctx.symbol) {
+        const Symbol *symbol = sym_ctx.symbol;
+        const Address sym_address = symbol->GetAddress();
+        
+        if (sym_address.IsValid()) {
+          switch (symbol->GetType()) {
+            case eSymbolTypeData:
+            case eSymbolTypeRuntime:
+            case eSymbolTypeAbsolute:
+            case eSymbolTypeObjCClass:
+            case eSymbolTypeObjCMetaClass:
+            case eSymbolTypeObjCIVar:
+              if (symbol->GetDemangledNameIsSynthesized()) {
+                // If the demangled name was synthesized, then don't use it
+                // for expressions. Only let the symbol match if the mangled
+                // named matches for these symbols.
+                if (symbol->GetMangled().GetMangledName() != name)
+                  break;
+              }
+              if (symbol->IsExternal()) {
+                external_symbols.push_back(symbol);
+              } else {
+                internal_symbols.push_back(symbol);
+              }
+              break;
+            case eSymbolTypeReExported: {
+              ConstString reexport_name = symbol->GetReExportedSymbolName();
+              if (reexport_name) {
+                ModuleSP reexport_module_sp;
+                ModuleSpec reexport_module_spec;
+                reexport_module_spec.GetPlatformFileSpec() =
+                symbol->GetReExportedSymbolSharedLibrary();
+                if (reexport_module_spec.GetPlatformFileSpec()) {
+                  reexport_module_sp =
+                  target.GetImages().FindFirstModule(reexport_module_spec);
+                  if (!reexport_module_sp) {
+                    reexport_module_spec.GetPlatformFileSpec()
+                    .GetDirectory()
+                    .Clear();
+                    reexport_module_sp =
+                    target.GetImages().FindFirstModule(reexport_module_spec);
+                  }
+                }
+                // Don't allow us to try and resolve a re-exported symbol if it is
+                // the same as the current symbol
+                if (name == symbol->GetReExportedSymbolName() &&
+                    module == reexport_module_sp.get())
+                  return nullptr;
+                
+                return FindBestGlobalDataSymbol(
+                    symbol->GetReExportedSymbolName(), error);
+              }
+            } break;
+              
+            case eSymbolTypeCode: // We already lookup functions elsewhere
+            case eSymbolTypeVariable:
+            case eSymbolTypeLocal:
+            case eSymbolTypeParam:
+            case eSymbolTypeTrampoline:
+            case eSymbolTypeInvalid:
+            case eSymbolTypeException:
+            case eSymbolTypeSourceFile:
+            case eSymbolTypeHeaderFile:
+            case eSymbolTypeObjectFile:
+            case eSymbolTypeCommonBlock:
+            case eSymbolTypeBlock:
+            case eSymbolTypeVariableType:
+            case eSymbolTypeLineEntry:
+            case eSymbolTypeLineHeader:
+            case eSymbolTypeScopeBegin:
+            case eSymbolTypeScopeEnd:
+            case eSymbolTypeAdditional:
+            case eSymbolTypeCompiler:
+            case eSymbolTypeInstrumentation:
+            case eSymbolTypeUndefined:
+            case eSymbolTypeResolver:
+              break;
+          }
+        }
+      }
+    }
+    
+    if (external_symbols.size() > 1) {
+      StreamString ss;
+      ss.Printf("Multiple external symbols found for '%s'\n", name.AsCString());
+      for (const Symbol *symbol : external_symbols) {
+        symbol->GetDescription(&ss, eDescriptionLevelFull, &target);
+      }
+      ss.PutChar('\n');
+      error.SetErrorString(ss.GetData());
+      return nullptr;
+    } else if (external_symbols.size()) {
+      return external_symbols[0];
+    } else if (internal_symbols.size() > 1) {
+      StreamString ss;
+      ss.Printf("Multiple internal symbols found for '%s'\n", name.AsCString());
+      for (const Symbol *symbol : internal_symbols) {
+        symbol->GetDescription(&ss, eDescriptionLevelVerbose, &target);
+        ss.PutChar('\n');
+      }
+      error.SetErrorString(ss.GetData());
+      return nullptr;
+    } else if (internal_symbols.size()) {
+      return internal_symbols[0];
+    } else {
+      return nullptr;
+    }
+  };
+  
+  if (module) {
+    SymbolContextList sc_list;
+    module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
+    const Symbol *const module_symbol = ProcessMatches(sc_list, error);
+    
+    if (!error.Success()) {
+      return nullptr;
+    } else if (module_symbol) {
+      return module_symbol;
+    }
+  }
+  
+  {
+    SymbolContextList sc_list;
+    target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny,
+                                                  sc_list);
+    const Symbol *const target_symbol = ProcessMatches(sc_list, error);
+    
+    if (!error.Success()) {
+      return nullptr;
+    } else if (target_symbol) {
+      return target_symbol;
+    }
+  }
+  
+  return nullptr; // no error; we just didn't find anything
+}
+
+
 //----------------------------------------------------------------------
 //
 //  SymbolContextSpecifier
Index: source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
===================================================================
--- source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
+++ source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -448,24 +448,6 @@
   uint64_t GetParserID() { return (uint64_t) this; }
 
   //------------------------------------------------------------------
-  /// Given a target, find a data symbol that has the given name.
-  ///
-  /// @param[in] target
-  ///     The target to use as the basis for the search.
-  ///
-  /// @param[in] name
-  ///     The name as a plain C string.
-  ///
-  /// @param[in] module
-  ///     The module to limit the search to. This can be NULL
-  ///
-  /// @return
-  ///     The LLDB Symbol found, or NULL if none was found.
-  //------------------------------------------------------------------
-  const Symbol *FindGlobalDataSymbol(Target &target, const ConstString &name,
-                                     Module *module = NULL);
-
-  //------------------------------------------------------------------
   /// Given a target, find a variable that matches the given name and
   /// type.
   ///
Index: source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
===================================================================
--- source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -591,103 +591,6 @@
                           symbol_type);
 }
 
-const Symbol *ClangExpressionDeclMap::FindGlobalDataSymbol(
-    Target &target, const ConstString &name, lldb_private::Module *module) {
-  SymbolContextList sc_list;
-
-  if (module)
-    module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
-  else
-    target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny,
-                                                  sc_list);
-
-  const uint32_t matches = sc_list.GetSize();
-  for (uint32_t i = 0; i < matches; ++i) {
-    SymbolContext sym_ctx;
-    sc_list.GetContextAtIndex(i, sym_ctx);
-    if (sym_ctx.symbol) {
-      const Symbol *symbol = sym_ctx.symbol;
-      const Address sym_address = symbol->GetAddress();
-
-      if (sym_address.IsValid()) {
-        switch (symbol->GetType()) {
-        case eSymbolTypeData:
-        case eSymbolTypeRuntime:
-        case eSymbolTypeAbsolute:
-        case eSymbolTypeObjCClass:
-        case eSymbolTypeObjCMetaClass:
-        case eSymbolTypeObjCIVar:
-          if (symbol->GetDemangledNameIsSynthesized()) {
-            // If the demangled name was synthesized, then don't use it
-            // for expressions. Only let the symbol match if the mangled
-            // named matches for these symbols.
-            if (symbol->GetMangled().GetMangledName() != name)
-              break;
-          }
-          return symbol;
-
-        case eSymbolTypeReExported: {
-          ConstString reexport_name = symbol->GetReExportedSymbolName();
-          if (reexport_name) {
-            ModuleSP reexport_module_sp;
-            ModuleSpec reexport_module_spec;
-            reexport_module_spec.GetPlatformFileSpec() =
-                symbol->GetReExportedSymbolSharedLibrary();
-            if (reexport_module_spec.GetPlatformFileSpec()) {
-              reexport_module_sp =
-                  target.GetImages().FindFirstModule(reexport_module_spec);
-              if (!reexport_module_sp) {
-                reexport_module_spec.GetPlatformFileSpec()
-                    .GetDirectory()
-                    .Clear();
-                reexport_module_sp =
-                    target.GetImages().FindFirstModule(reexport_module_spec);
-              }
-            }
-            // Don't allow us to try and resolve a re-exported symbol if it is
-            // the same
-            // as the current symbol
-            if (name == symbol->GetReExportedSymbolName() &&
-                module == reexport_module_sp.get())
-              return NULL;
-
-            return FindGlobalDataSymbol(target,
-                                        symbol->GetReExportedSymbolName(),
-                                        reexport_module_sp.get());
-          }
-        } break;
-
-        case eSymbolTypeCode: // We already lookup functions elsewhere
-        case eSymbolTypeVariable:
-        case eSymbolTypeLocal:
-        case eSymbolTypeParam:
-        case eSymbolTypeTrampoline:
-        case eSymbolTypeInvalid:
-        case eSymbolTypeException:
-        case eSymbolTypeSourceFile:
-        case eSymbolTypeHeaderFile:
-        case eSymbolTypeObjectFile:
-        case eSymbolTypeCommonBlock:
-        case eSymbolTypeBlock:
-        case eSymbolTypeVariableType:
-        case eSymbolTypeLineEntry:
-        case eSymbolTypeLineHeader:
-        case eSymbolTypeScopeBegin:
-        case eSymbolTypeScopeEnd:
-        case eSymbolTypeAdditional:
-        case eSymbolTypeCompiler:
-        case eSymbolTypeInstrumentation:
-        case eSymbolTypeUndefined:
-        case eSymbolTypeResolver:
-          break;
-        }
-      }
-    }
-  }
-
-  return NULL;
-}
-
 lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable(
     Target &target, ModuleSP &module, const ConstString &name,
     CompilerDeclContext *namespace_decl, TypeFromUser *type) {
@@ -1526,9 +1429,18 @@
       // We couldn't find a non-symbol variable for this.  Now we'll hunt for
       // a generic
       // data symbol, and -- if it is found -- treat it as a variable.
-
-      const Symbol *data_symbol = FindGlobalDataSymbol(*target, name);
-
+      Status error;
+      
+      const Symbol *data_symbol =
+          m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error);
+      
+      if (!error.Success()) {
+        const unsigned diag_id =
+            m_ast_context->getDiagnostics().getCustomDiagID(
+                clang::DiagnosticsEngine::Level::Error, "%0");
+        m_ast_context->getDiagnostics().Report(diag_id) << error.AsCString();
+      }
+                                          
       if (data_symbol) {
         std::string warning("got name from symbols: ");
         warning.append(name.AsCString());
Index: packages/Python/lldbsuite/test/lang/c/conflicting-symbol/main.c
===================================================================
--- packages/Python/lldbsuite/test/lang/c/conflicting-symbol/main.c
+++ packages/Python/lldbsuite/test/lang/c/conflicting-symbol/main.c
@@ -0,0 +1,11 @@
+#include "One/One.h"
+#include "Two/Two.h"
+
+#include <stdio.h>
+
+int main() {
+  one();
+  two();
+  printf("main\n"); // break here
+  return(0); 
+}
Index: packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two.mk
===================================================================
--- packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two.mk
+++ packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two.mk
@@ -0,0 +1,12 @@
+LEVEL := ../../../make
+
+DYLIB_NAME := Two
+DYLIB_C_SOURCES := Two/Two.c Two/TwoConstant.c
+DYLIB_ONLY := YES
+
+include $(LEVEL)/Makefile.rules
+
+CFLAGS_EXTRAS += -fPIC
+
+Two/TwoConstant.o: Two/TwoConstant.c
+	$(CC) $(CFLAGS_NO_DEBUG) -c $< -o $@
Index: packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two/TwoConstant.c
===================================================================
--- packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two/TwoConstant.c
+++ packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two/TwoConstant.c
@@ -0,0 +1 @@
+int __attribute__ ((visibility("hidden"))) conflicting_symbol = 22222;
Index: packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two/Two.h
===================================================================
--- packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two/Two.h
+++ packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two/Two.h
@@ -0,0 +1,4 @@
+#ifndef TWO_H
+#define TWO_H
+void two();
+#endif
Index: packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two/Two.c
===================================================================
--- packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two/Two.c
+++ packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Two/Two.c
@@ -0,0 +1,6 @@
+#include "Two.h"
+#include <stdio.h>
+
+void two() {
+  printf("Two\n"); // break here
+}
Index: packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py
===================================================================
--- packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py
+++ packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py
@@ -0,0 +1,86 @@
+"""Test that conflicting symbols in different shared libraries work correctly"""
+
+from __future__ import print_function
+
+
+import os
+import time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestConflictingSymbols(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+    NO_DEBUG_INFO_TESTCASE = True
+
+    @skipUnlessDarwin
+    def test_conflicting_symbols(self):
+        self.build()
+        self.common_setup()
+
+        One_line = line_number('One/One.c', '// break here')
+        Two_line = line_number('Two/Two.c', '// break here')
+        main_line = line_number('main.c', '// break here')
+        lldbutil.run_break_set_command(
+            self, 'breakpoint set -f One.c -l %s' % (One_line))
+        lldbutil.run_break_set_command(
+            self, 'breakpoint set -f Two.c -l %s' % (Two_line))
+        lldbutil.run_break_set_by_file_and_line(
+            self, 'main.c', main_line, num_expected_locations=1, loc_exact=True)
+
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+                    substrs=['stopped',
+                             'stop reason = breakpoint'])
+
+        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
+                    substrs=[' resolved, hit count = 1'])
+
+        # This should display correctly.
+        self.expect(
+            "expr (unsigned long long)conflicting_symbol",
+            "Symbol from One should be found",
+            substrs=[
+                "11111"])
+
+        self.runCmd("continue", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+                    substrs=['stopped',
+                             'stop reason = breakpoint'])
+
+        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
+                    substrs=[' resolved, hit count = 1'])
+
+        self.expect(
+            "expr (unsigned long long)conflicting_symbol",
+            "Symbol from Two should be found",
+            substrs=[
+                "22222"])
+
+        self.runCmd("continue", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+                    substrs=['stopped',
+                             'stop reason = breakpoint'])
+
+        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
+                    substrs=[' resolved, hit count = 1'])
+
+        self.expect(
+            "expr (unsigned long long)conflicting_symbol",
+            "An error should be printed when symbols can't be ordered",
+            error=True,
+            substrs=[
+                "Multiple internal symbols"])
+
+    def common_setup(self):
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
Index: packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One.mk
===================================================================
--- packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One.mk
+++ packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One.mk
@@ -0,0 +1,12 @@
+LEVEL := ../../../make
+
+DYLIB_NAME := One
+DYLIB_C_SOURCES := One/One.c One/OneConstant.c
+DYLIB_ONLY := YES
+
+include $(LEVEL)/Makefile.rules
+
+CFLAGS_EXTRAS += -fPIC
+
+One/OneConstant.o: One/OneConstant.c
+	$(CC) $(CFLAGS_NO_DEBUG) -c $< -o $@
Index: packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One/OneConstant.c
===================================================================
--- packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One/OneConstant.c
+++ packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One/OneConstant.c
@@ -0,0 +1 @@
+int __attribute__ ((visibility("hidden"))) conflicting_symbol = 11111;
Index: packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One/One.h
===================================================================
--- packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One/One.h
+++ packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One/One.h
@@ -0,0 +1,4 @@
+#ifndef ONE_H
+#define ONE_H
+void one();
+#endif
Index: packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One/One.c
===================================================================
--- packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One/One.c
+++ packages/Python/lldbsuite/test/lang/c/conflicting-symbol/One/One.c
@@ -0,0 +1,6 @@
+#include "One.h"
+#include <stdio.h>
+
+void one() {
+  printf("One\n"); // break here
+}
Index: packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Makefile
===================================================================
--- packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Makefile
+++ packages/Python/lldbsuite/test/lang/c/conflicting-symbol/Makefile
@@ -0,0 +1,18 @@
+LEVEL := ../../../make
+
+LD_EXTRAS := -L. -l$(LIB_PREFIX)One -l$(LIB_PREFIX)Two
+C_SOURCES := main.c
+
+main.o : CFLAGS_EXTRAS += -g -O0
+
+include $(LEVEL)/Makefile.rules
+
+.PHONY:
+a.out: lib_One lib_Two
+
+lib_%:
+	$(MAKE) -f $*.mk
+
+clean::
+	$(MAKE) -f One.mk clean
+	$(MAKE) -f Two.mk clean
Index: include/lldb/Symbol/SymbolContext.h
===================================================================
--- include/lldb/Symbol/SymbolContext.h
+++ include/lldb/Symbol/SymbolContext.h
@@ -235,6 +235,29 @@
 
   bool GetAddressRangeFromHereToEndLine(uint32_t end_line, AddressRange &range,
                                         Status &error);
+  
+  //------------------------------------------------------------------
+  /// Find the best global data symbol visible from this context.
+  ///
+  /// Symbol priority is:
+  ///     - extern symbol in the current module if there is one
+  ///     - non-extern symbol in the current module if there is one
+  ///     - extern symbol in the target
+  ///     - non-extern symbol in the target
+  /// It is an error if the highest-priority result is ambiguous.
+  ///
+  /// @param[in] name
+  ///     The name of the symbol to search for.
+  ///
+  /// @param[out] error
+  ///     An error that will be populated with a message if there was an
+  ///     ambiguous result.  The error will not be populated if no result
+  ///     was found.
+  ///
+  /// @return
+  ///     The symbol that was found, or \b nullptr if none was found.
+  //------------------------------------------------------------------
+  const Symbol *FindBestGlobalDataSymbol(const ConstString &name, Status &error);
 
   void GetDescription(Stream *s, lldb::DescriptionLevel level,
                       Target *target) const;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to