Get the expression parser to handle missing weak symbols.
authorJim Ingham <jingham@apple.com>
Fri, 28 Jun 2019 21:40:05 +0000 (21:40 +0000)
committerJim Ingham <jingham@apple.com>
Fri, 28 Jun 2019 21:40:05 +0000 (21:40 +0000)
MachO only for this patch.

Differential Revision: https://reviews.llvm.org/D63914

<rdar://problem/51463642>

llvm-svn: 364686

14 files changed:
lldb/include/lldb/Expression/IRExecutionUnit.h
lldb/include/lldb/Symbol/Symbol.h
lldb/include/lldb/lldb-enumerations.h
lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/Makefile [new file with mode: 0644]
lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/TestWeakSymbols.py [new file with mode: 0644]
lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/dylib.c [new file with mode: 0644]
lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/dylib.h [new file with mode: 0644]
lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/main.c [new file with mode: 0644]
lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/module.modulemap [new file with mode: 0644]
lldb/source/Expression/IRExecutionUnit.cpp
lldb/source/Expression/IRInterpreter.cpp
lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
lldb/source/Symbol/Symbol.cpp

index 37f3135..beff44d 100644 (file)
@@ -101,7 +101,7 @@ public:
 
   lldb::ModuleSP GetJITModule();
 
-  lldb::addr_t FindSymbol(ConstString name);
+  lldb::addr_t FindSymbol(ConstString name, bool &missing_weak);
 
   void GetStaticInitializers(std::vector<lldb::addr_t> &static_initializers);
 
@@ -226,7 +226,8 @@ private:
                             const std::vector<SearchSpec> &C_specs);
 
   lldb::addr_t FindInSymbols(const std::vector<SearchSpec> &specs,
-                             const lldb_private::SymbolContext &sc);
+                             const lldb_private::SymbolContext &sc,
+                             bool &symbol_was_missing_weak);
 
   lldb::addr_t FindInRuntimes(const std::vector<SearchSpec> &specs,
                               const lldb_private::SymbolContext &sc);
@@ -301,6 +302,13 @@ private:
                           size_t Size) override {}
 
     uint64_t getSymbolAddress(const std::string &Name) override;
+    
+    // Find the address of the symbol Name.  If Name is a missing weak symbol
+    // then missing_weak will be true.
+    uint64_t GetSymbolAddressAndPresence(const std::string &Name, 
+                                         bool &missing_weak);
+    
+    llvm::JITSymbol findSymbol(const std::string &Name) override;
 
     void *getPointerToNamedFunction(const std::string &Name,
                                     bool AbortOnFailure = true) override;
index d366297..1cbc2f5 100644 (file)
@@ -165,6 +165,10 @@ public:
   bool IsTrampoline() const;
 
   bool IsIndirect() const;
+  
+  bool IsWeak() const { return m_is_weak; }
+  
+  void SetIsWeak (bool b) { m_is_weak = b; }
 
   bool GetByteSizeIsValid() const { return m_size_is_valid; }
 
@@ -250,7 +254,8 @@ protected:
       m_contains_linker_annotations : 1, // The symbol name contains linker
                                          // annotations, which are optional when
                                          // doing name lookups
-      m_type : 7;
+      m_is_weak : 1,
+      m_type : 6;            // Values from the lldb::SymbolType enum.
   Mangled m_mangled;         // uniqued symbol name/mangled name pair
   AddressRange m_addr_range; // Contains the value, or the section offset
                              // address when the value is an address in a
index 9d2d9ba..f9830c0 100644 (file)
@@ -592,6 +592,8 @@ enum CommandArgumentType {
 };
 
 // Symbol types
+// Symbol holds the SymbolType in a 6-bit field (m_type), so if you get over 63 
+// entries you will have to resize that field.
 enum SymbolType {
   eSymbolTypeAny = 0,
   eSymbolTypeInvalid = 0,
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/Makefile
new file mode 100644 (file)
index 0000000..7c70b50
--- /dev/null
@@ -0,0 +1,26 @@
+LEVEL = ../../make
+CFLAGS_EXTRAS += -std=c99
+LD_FLAGS := -dynamiclib
+include $(LEVEL)/Makefile.rules
+
+all: a.out dylib missing
+
+dylib: dylib.o
+       $(CC)  $(LD_FLAGS) -o libdylib.dylib dylib.o
+
+missing: dylib2.o
+       mkdir hidden
+       $(CC)  $(LD_FLAGS) -o hidden/libdylib.dylib dylib2.o
+
+a.out: main.o dylib missing
+       $(CC)  $(CFLAGS) -L. -ldylib main.o
+
+dylib.o: dylib.h $(SRCDIR)/dylib.c
+       $(CC) -DHAS_THEM  $(CFLAGS) -c $(SRCDIR)/dylib.c
+
+dylib2.o: dylib.h $(SRCDIR)/dylib.c
+       $(CC)  $(CFLAGS) -c $(SRCDIR)/dylib.c -o dylib2.o
+
+main.o: dylib.h $(SRCDIR)/main.c
+       $(CC)  $(CFLAGS) -c $(SRCDIR)/main.c -fmodules
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/TestWeakSymbols.py b/lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/TestWeakSymbols.py
new file mode 100644 (file)
index 0000000..a5d7a4b
--- /dev/null
@@ -0,0 +1,83 @@
+"""
+Test that we can compile expressions referring to
+absent weak symbols from a dylib.
+"""
+
+from __future__ import print_function
+
+
+import os
+import time
+import re
+import lldb
+from lldbsuite.test import decorators
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+
+
+class TestWeakSymbolsInExpressions(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    NO_DEBUG_INFO_TESTCASE = True
+
+    @decorators.skipUnlessDarwin
+    def test_weak_symbol_in_expr(self):
+        """Tests that we can refer to weak symbols in expressions."""
+        self.build()
+        self.main_source_file = lldb.SBFileSpec("main.c")
+        self.do_test()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+
+    def run_weak_var_check (self, weak_varname, present):
+        # The expression will modify present_weak_int to signify which branch
+        # was taken.  Set it to so we don't get confused by a previous run.
+        value = self.target.FindFirstGlobalVariable("present_weak_int")
+        value.SetValueFromCString("0")
+        if present:
+            correct_value = 10
+        else:
+            correct_value = 20
+            
+        # Note, I'm adding the "; 10" at the end of the expression to work around
+        # the bug that expressions with no result currently return False for Success()...
+        expr = "if (&" + weak_varname + " != NULL) { present_weak_int = 10; } else { present_weak_int = 20;}; 10"
+        result = self.frame.EvaluateExpression(expr)
+        self.assertTrue(result.GetError().Success(), "absent_weak_int expr failed: %s"%(result.GetError().GetCString()))
+        self.assertEqual(value.GetValueAsSigned(), correct_value, "Didn't change present_weak_int correctly.")
+        
+    def do_test(self):
+        hidden_dir = os.path.join(self.getBuildDir(), "hidden")
+        
+        launch_info = lldb.SBLaunchInfo(None)
+        launch_info.SetWorkingDirectory(self.getBuildDir())
+        # We have to point to the hidden directory to pick up the
+        # version of the dylib without the weak symbols:
+        env_expr = self.platformContext.shlib_environment_var + "=" + hidden_dir
+        launch_info.SetEnvironmentEntries([env_expr], True)
+        
+        (self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+                                                                            "Set a breakpoint here", self.main_source_file,
+                                                                            launch_info = launch_info)
+        # First we have to import the Dylib module so we get the type info
+        # for the weak symbol.  We need to add the source dir to the module
+        # search paths, and then run @import to introduce it into the expression
+        # context:
+        self.dbg.HandleCommand("settings set target.clang-module-search-paths " + self.getSourceDir())
+        
+        self.frame = thread.frames[0]
+        self.assertTrue(self.frame.IsValid(), "Got a good frame")
+        options = lldb.SBExpressionOptions()
+        options.SetLanguage(lldb.eLanguageTypeObjC)
+        result = self.frame.EvaluateExpression("@import Dylib", options)
+
+        # Now run an expression that references an absent weak symbol:
+        self.run_weak_var_check("absent_weak_int", False)
+        self.run_weak_var_check("absent_weak_function", False)
+        
+        # Make sure we can do the same thing with present weak symbols
+        self.run_weak_var_check("present_weak_int", True)
+        self.run_weak_var_check("present_weak_function", True)
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/dylib.c b/lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/dylib.c
new file mode 100644 (file)
index 0000000..dc513e5
--- /dev/null
@@ -0,0 +1,14 @@
+#include "dylib.h"
+
+int present_weak_int = 10;
+int present_weak_function()
+{
+  return present_weak_int;
+}
+
+#if defined HAS_THEM
+int absent_weak_int = 10;
+int absent_weak_function() {
+  return absent_weak_int;
+}
+#endif
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/dylib.h b/lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/dylib.h
new file mode 100644 (file)
index 0000000..f668ec0
--- /dev/null
@@ -0,0 +1,8 @@
+extern int absent_weak_int __attribute__((weak_import));
+
+extern int present_weak_int __attribute__((weak_import));
+
+extern int absent_weak_function() __attribute__((weak_import));
+
+extern int present_weak_function() __attribute__((weak_import));
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/main.c b/lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/main.c
new file mode 100644 (file)
index 0000000..5ea257b
--- /dev/null
@@ -0,0 +1,23 @@
+#include "dylib.h"
+#include <stdio.h>
+
+int
+doSomething()
+{
+  // Set a breakpoint here.
+  if (&absent_weak_int != NULL)
+    printf("In absent_weak_int: %d\n", absent_weak_int);
+  if (absent_weak_function != NULL)
+    printf("In absent_weak_func: %p\n", absent_weak_function);
+  if (&present_weak_int != NULL)
+    printf("In present_weak_int: %d\n", present_weak_int);
+  if (present_weak_function != NULL)
+    printf("In present_weak_func: %p\n", present_weak_function);
+
+}
+
+int
+main()
+{
+  return doSomething();
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/module.modulemap b/lldb/packages/Python/lldbsuite/test/expression_command/weak_symbols/module.modulemap
new file mode 100644 (file)
index 0000000..6f76714
--- /dev/null
@@ -0,0 +1,3 @@
+module Dylib {
+  header "dylib.h"
+}
index 160f586..da74966 100644 (file)
@@ -774,7 +774,9 @@ void IRExecutionUnit::CollectFallbackNames(
 
 lldb::addr_t IRExecutionUnit::FindInSymbols(
     const std::vector<IRExecutionUnit::SearchSpec> &specs,
-    const lldb_private::SymbolContext &sc) {
+    const lldb_private::SymbolContext &sc,
+    bool &symbol_was_missing_weak) {
+  symbol_was_missing_weak = false;
   Target *target = sc.target_sp.get();
 
   if (!target) {
@@ -794,11 +796,20 @@ lldb::addr_t IRExecutionUnit::FindInSymbols(
             const lldb_private::SymbolContext &sc) -> lldb::addr_t {
       load_address = LLDB_INVALID_ADDRESS;
 
-      for (size_t si = 0, se = sc_list.GetSize(); si < se; ++si) {
-        SymbolContext candidate_sc;
-
-        sc_list.GetContextAtIndex(si, candidate_sc);
-
+      if (sc_list.GetSize() == 0)
+        return false;
+
+      // missing_weak_symbol will be true only if we found only weak undefined 
+      // references to this symbol.
+      bool symbol_was_missing_weak = true;      
+      for (auto candidate_sc : sc_list.SymbolContexts()) {        
+        // Only symbols can be weak undefined:
+        if (!candidate_sc.symbol)
+          symbol_was_missing_weak = false;
+        else if (candidate_sc.symbol->GetType() != lldb::eSymbolTypeUndefined
+                  || !candidate_sc.symbol->IsWeak())
+          symbol_was_missing_weak = false;
+        
         const bool is_external =
             (candidate_sc.function) ||
             (candidate_sc.symbol && candidate_sc.symbol->IsExternal());
@@ -835,6 +846,13 @@ lldb::addr_t IRExecutionUnit::FindInSymbols(
         }
       }
 
+      // You test the address of a weak symbol against NULL to see if it is
+      // present.  So we should return 0 for a missing weak symbol.
+      if (symbol_was_missing_weak) {
+        load_address = 0;
+        return true;
+      }
+      
       return false;
     };
 
@@ -930,31 +948,37 @@ lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols(
 }
 
 lldb::addr_t
-IRExecutionUnit::FindSymbol(lldb_private::ConstString name) {
+IRExecutionUnit::FindSymbol(lldb_private::ConstString name, bool &missing_weak) {
   std::vector<SearchSpec> candidate_C_names;
   std::vector<SearchSpec> candidate_CPlusPlus_names;
 
   CollectCandidateCNames(candidate_C_names, name);
+  
+  lldb::addr_t ret = FindInSymbols(candidate_C_names, m_sym_ctx, missing_weak);
+  if (ret != LLDB_INVALID_ADDRESS)
+    return ret;
+  
+  // If we find the symbol in runtimes or user defined symbols it can't be 
+  // a missing weak symbol.
+  missing_weak = false;
+  ret = FindInRuntimes(candidate_C_names, m_sym_ctx);
+  if (ret != LLDB_INVALID_ADDRESS)
+    return ret;
 
-  lldb::addr_t ret = FindInSymbols(candidate_C_names, m_sym_ctx);
-  if (ret == LLDB_INVALID_ADDRESS)
-    ret = FindInRuntimes(candidate_C_names, m_sym_ctx);
-
-  if (ret == LLDB_INVALID_ADDRESS)
-    ret = FindInUserDefinedSymbols(candidate_C_names, m_sym_ctx);
+  ret = FindInUserDefinedSymbols(candidate_C_names, m_sym_ctx);
+  if (ret != LLDB_INVALID_ADDRESS)
+    return ret;
 
-  if (ret == LLDB_INVALID_ADDRESS) {
-    CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names,
-                                   m_sym_ctx);
-    ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx);
-  }
+  CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names,
+                                 m_sym_ctx);
+  ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx, missing_weak);
+  if (ret != LLDB_INVALID_ADDRESS)
+    return ret;
 
-  if (ret == LLDB_INVALID_ADDRESS) {
-    std::vector<SearchSpec> candidate_fallback_names;
+  std::vector<SearchSpec> candidate_fallback_names;
 
-    CollectFallbackNames(candidate_fallback_names, candidate_C_names);
-    ret = FindInSymbols(candidate_fallback_names, m_sym_ctx);
-  }
+  CollectFallbackNames(candidate_fallback_names, candidate_C_names);
+  ret = FindInSymbols(candidate_fallback_names, m_sym_ctx, missing_weak);
 
   return ret;
 }
@@ -989,13 +1013,32 @@ void IRExecutionUnit::GetStaticInitializers(
   }
 }
 
+llvm::JITSymbol 
+IRExecutionUnit::MemoryManager::findSymbol(const std::string &Name) {
+    bool missing_weak = false;
+    uint64_t addr = GetSymbolAddressAndPresence(Name, missing_weak);
+    // This is a weak symbol:
+    if (missing_weak) 
+      return llvm::JITSymbol(addr, 
+          llvm::JITSymbolFlags::Exported | llvm::JITSymbolFlags::Weak);
+    else
+      return llvm::JITSymbol(addr, llvm::JITSymbolFlags::Exported);
+}
+
 uint64_t
 IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) {
+  bool missing_weak = false;
+  return GetSymbolAddressAndPresence(Name, missing_weak);
+}
+
+uint64_t 
+IRExecutionUnit::MemoryManager::GetSymbolAddressAndPresence(
+    const std::string &Name, bool &missing_weak) {
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
 
   ConstString name_cs(Name.c_str());
 
-  lldb::addr_t ret = m_parent.FindSymbol(name_cs);
+  lldb::addr_t ret = m_parent.FindSymbol(name_cs, missing_weak);
 
   if (ret == LLDB_INVALID_ADDRESS) {
     if (log)
index 24a3cd2..5a9814d 100644 (file)
@@ -233,8 +233,9 @@ public:
     case Value::FunctionVal:
       if (const Function *constant_func = dyn_cast<Function>(constant)) {
         lldb_private::ConstString name(constant_func->getName());
-        lldb::addr_t addr = m_execution_unit.FindSymbol(name);
-        if (addr == LLDB_INVALID_ADDRESS)
+        bool missing_weak = false;
+        lldb::addr_t addr = m_execution_unit.FindSymbol(name, missing_weak);
+        if (addr == LLDB_INVALID_ADDRESS || missing_weak)
           return false;
         value = APInt(m_target_data.getPointerSizeInBits(), addr);
         return true;
index f083b92..07acb2e 100644 (file)
@@ -433,9 +433,11 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str,
     static lldb_private::ConstString g_CFStringCreateWithBytes_str(
         "CFStringCreateWithBytes");
 
+    bool missing_weak = false;
     CFStringCreateWithBytes_addr =
-        m_execution_unit.FindSymbol(g_CFStringCreateWithBytes_str);
-    if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS) {
+        m_execution_unit.FindSymbol(g_CFStringCreateWithBytes_str, 
+                                    missing_weak);
+    if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS || missing_weak) {
       if (log)
         log->PutCString("Couldn't find CFStringCreateWithBytes in the target");
 
@@ -857,9 +859,11 @@ bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) {
   if (!m_sel_registerName) {
     lldb::addr_t sel_registerName_addr;
 
+    bool missing_weak = false;
     static lldb_private::ConstString g_sel_registerName_str("sel_registerName");
-    sel_registerName_addr = m_execution_unit.FindSymbol(g_sel_registerName_str);
-    if (sel_registerName_addr == LLDB_INVALID_ADDRESS)
+    sel_registerName_addr = m_execution_unit.FindSymbol(g_sel_registerName_str,
+                                                        missing_weak);
+    if (sel_registerName_addr == LLDB_INVALID_ADDRESS || missing_weak)
       return false;
 
     if (log)
@@ -1027,9 +1031,11 @@ bool IRForTarget::RewriteObjCClassReference(Instruction *class_load) {
   if (!m_objc_getClass) {
     lldb::addr_t objc_getClass_addr;
 
+    bool missing_weak = false;
     static lldb_private::ConstString g_objc_getClass_str("objc_getClass");
-    objc_getClass_addr = m_execution_unit.FindSymbol(g_objc_getClass_str);
-    if (objc_getClass_addr == LLDB_INVALID_ADDRESS)
+    objc_getClass_addr = m_execution_unit.FindSymbol(g_objc_getClass_str,
+                                                     missing_weak);
+    if (objc_getClass_addr == LLDB_INVALID_ADDRESS || missing_weak)
       return false;
 
     if (log)
index e1d6881..6e82282 100644 (file)
@@ -4575,6 +4575,8 @@ size_t ObjectFileMachO::ParseSymtab() {
             sym[sym_idx].GetAddressRef().SetOffset(symbol_value);
           }
           sym[sym_idx].SetFlags(nlist.n_type << 16 | nlist.n_desc);
+          if (nlist.n_desc & N_WEAK_REF)
+            sym[sym_idx].SetIsWeak(true);
 
           if (symbol_byte_size > 0)
             sym[sym_idx].SetByteSize(symbol_byte_size);
index 6e9bfe7..589f692 100644 (file)
@@ -28,7 +28,8 @@ Symbol::Symbol()
       m_is_external(false), m_size_is_sibling(false),
       m_size_is_synthesized(false), m_size_is_valid(false),
       m_demangled_is_synthesized(false), m_contains_linker_annotations(false),
-      m_type(eSymbolTypeInvalid), m_mangled(), m_addr_range(), m_flags() {}
+      m_is_weak(false), m_type(eSymbolTypeInvalid), m_mangled(), m_addr_range(),
+      m_flags() {}
 
 Symbol::Symbol(uint32_t symID, const char *name, bool name_is_mangled,
                SymbolType type, bool external, bool is_debug,
@@ -41,7 +42,8 @@ Symbol::Symbol(uint32_t symID, const char *name, bool name_is_mangled,
       m_is_debug(is_debug), m_is_external(external), m_size_is_sibling(false),
       m_size_is_synthesized(false), m_size_is_valid(size_is_valid || size > 0),
       m_demangled_is_synthesized(false),
-      m_contains_linker_annotations(contains_linker_annotations), m_type(type),
+      m_contains_linker_annotations(contains_linker_annotations), 
+      m_is_weak(false), m_type(type),
       m_mangled(ConstString(name), name_is_mangled),
       m_addr_range(section_sp, offset, size), m_flags(flags) {}
 
@@ -56,8 +58,9 @@ Symbol::Symbol(uint32_t symID, const Mangled &mangled, SymbolType type,
       m_size_is_synthesized(false),
       m_size_is_valid(size_is_valid || range.GetByteSize() > 0),
       m_demangled_is_synthesized(false),
-      m_contains_linker_annotations(contains_linker_annotations), m_type(type),
-      m_mangled(mangled), m_addr_range(range), m_flags(flags) {}
+      m_contains_linker_annotations(contains_linker_annotations), 
+      m_is_weak(false), m_type(type), m_mangled(mangled), m_addr_range(range), 
+      m_flags(flags) {}
 
 Symbol::Symbol(const Symbol &rhs)
     : SymbolContextScope(rhs), m_uid(rhs.m_uid), m_type_data(rhs.m_type_data),
@@ -68,7 +71,7 @@ Symbol::Symbol(const Symbol &rhs)
       m_size_is_valid(rhs.m_size_is_valid),
       m_demangled_is_synthesized(rhs.m_demangled_is_synthesized),
       m_contains_linker_annotations(rhs.m_contains_linker_annotations),
-      m_type(rhs.m_type), m_mangled(rhs.m_mangled),
+      m_is_weak(rhs.m_is_weak), m_type(rhs.m_type), m_mangled(rhs.m_mangled),
       m_addr_range(rhs.m_addr_range), m_flags(rhs.m_flags) {}
 
 const Symbol &Symbol::operator=(const Symbol &rhs) {
@@ -85,6 +88,7 @@ const Symbol &Symbol::operator=(const Symbol &rhs) {
     m_size_is_valid = rhs.m_size_is_valid;
     m_demangled_is_synthesized = rhs.m_demangled_is_synthesized;
     m_contains_linker_annotations = rhs.m_contains_linker_annotations;
+    m_is_weak = rhs.m_is_weak;
     m_type = rhs.m_type;
     m_mangled = rhs.m_mangled;
     m_addr_range = rhs.m_addr_range;
@@ -106,6 +110,7 @@ void Symbol::Clear() {
   m_size_is_valid = false;
   m_demangled_is_synthesized = false;
   m_contains_linker_annotations = false;
+  m_is_weak = false;
   m_type = eSymbolTypeInvalid;
   m_flags = 0;
   m_addr_range.Clear();