aprantl created this revision.
aprantl added reviewers: jingham, JDevlieghere.
Herald added a reviewer: jdoerfert.
This feature is mostly there to aid debugging of Clang module issues, since the
only useful actual the end-user can to is to recompile their program. Dsymutil
prints a similar warning in this case.
https://reviews.llvm.org/D70272
Files:
lldb/include/lldb/Symbol/SymbolFile.h
lldb/include/lldb/Utility/Log.h
lldb/packages/Python/lldbsuite/test/lang/objc/modules-hash-mismatch/Makefile
lldb/packages/Python/lldbsuite/test/lang/objc/modules-hash-mismatch/TestClangModulesHashMismatch.py
lldb/packages/Python/lldbsuite/test/lang/objc/modules-hash-mismatch/main.m
lldb/packages/Python/lldbsuite/test/lang/objc/modules-hash-mismatch/other.m
lldb/packages/Python/lldbsuite/test/make/Makefile.rules
lldb/source/Host/common/Host.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -289,6 +289,9 @@
virtual llvm::Optional<uint32_t> GetDwoNum() { return llvm::None; }
+ llvm::Optional<uint64_t> GetSymbolHash() override;
+
+
static bool
DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx,
const DWARFDIE &die);
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1553,6 +1553,39 @@
return DWARFDIE();
}
+/// Return the DW_AT_(GNU_)dwo_name.
+static const char *GetDWOName(DWARFCompileUnit &dwarf_cu,
+ DWARFDebugInfoEntry cu_die) {
+ const char *dwo_name =
+ cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
+ if (!dwo_name)
+ dwo_name =
+ cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_dwo_name, nullptr);
+ return dwo_name;
+}
+
+/// Return the DW_AT_(GNU_)dwo_id.
+/// FIXME: Technically 0 is a valid hash.
+static uint64_t GetDWOId(DWARFCompileUnit &dwarf_cu,
+ DWARFDebugInfoEntry cu_die) {
+ uint64_t dwo_id =
+ cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_GNU_dwo_id, 0);
+ if (!dwo_id)
+ dwo_id = cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_dwo_id, 0);
+ return dwo_id;
+}
+
+llvm::Optional<uint64_t> SymbolFileDWARF::GetSymbolHash() {
+ if (auto comp_unit = GetCompileUnitAtIndex(0)) {
+ if (DWARFCompileUnit *cu = llvm::dyn_cast_or_null<DWARFCompileUnit>(
+ GetDWARFCompileUnit(comp_unit.get())))
+ if (DWARFDebugInfoEntry *cu_die = cu->DIE().GetDIE())
+ if (uint64_t dwo_id = GetDWOId(*cu, *cu_die))
+ return dwo_id;
+ }
+ return {};
+}
+
std::unique_ptr<SymbolFileDWARFDwo>
SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
DWARFUnit &unit, const DWARFDebugInfoEntry &cu_die) {
@@ -1569,15 +1602,13 @@
if (!dwarf_cu)
return nullptr;
- const char *dwo_name =
- cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
+ const char *dwo_name = GetDWOName(*dwarf_cu, cu_die);
if (!dwo_name)
return nullptr;
SymbolFileDWARFDwp *dwp_symfile = GetDwpSymbolFile();
if (dwp_symfile) {
- uint64_t dwo_id =
- cu_die.GetAttributeValueAsUnsigned(dwarf_cu, DW_AT_GNU_dwo_id, 0);
+ uint64_t dwo_id = GetDWOId(*dwarf_cu, cu_die);
std::unique_ptr<SymbolFileDWARFDwo> dwo_symfile =
dwp_symfile->GetSymbolFileForDwoId(*dwarf_cu, dwo_id);
if (dwo_symfile)
@@ -1617,15 +1648,18 @@
if (m_fetched_external_modules)
return;
m_fetched_external_modules = true;
-
DWARFDebugInfo *debug_info = DebugInfo();
// Follow DWO skeleton unit breadcrumbs.
const uint32_t num_compile_units = GetNumCompileUnits();
for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- DWARFUnit *dwarf_cu = debug_info->GetUnitAtIndex(cu_idx);
+ auto *dwarf_cu =
+ llvm::dyn_cast<DWARFCompileUnit>(debug_info->GetUnitAtIndex(cu_idx));
+ if (!dwarf_cu)
+ continue;
+
const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly();
- if (!die || die.HasChildren())
+ if (!die || die.HasChildren() || !die.GetDIE())
continue;
const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
@@ -1637,10 +1671,7 @@
if (module_sp)
continue;
- const char *dwo_path =
- die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
- if (!dwo_path)
- dwo_path = die.GetAttributeValueAsString(DW_AT_dwo_name, nullptr);
+ const char *dwo_path = GetDWOName(*dwarf_cu, *die.GetDIE());
if (!dwo_path)
continue;
@@ -1683,12 +1714,34 @@
GetObjectFile()->GetModule()->ReportWarning(
"0x%8.8x: unable to locate module needed for external types: "
"%s\nerror: %s\nDebugging will be degraded due to missing "
- "types. Rebuilding your project will regenerate the needed "
+ "types. Rebuilding the project will regenerate the needed "
"module files.",
die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str(),
error.AsCString("unknown error"));
continue;
}
+
+ // Verify the DWO hash.
+ // FIXME: Technically "0" is a valid hash.
+ uint64_t dwo_id = GetDWOId(*dwarf_cu, *die.GetDIE());
+ if (!dwo_id)
+ continue;
+
+ SymbolFile *dwo_symfile = module_sp->GetSymbolFile();
+ if (!dwo_symfile)
+ continue;
+ llvm::Optional<uint64_t> dwo_dwo_id = dwo_symfile->GetSymbolHash();
+ if (!dwo_dwo_id)
+ continue;
+
+ if (dwo_id != dwo_dwo_id) {
+ GetObjectFile()->GetModule()->ReportWarning(
+ "0x%8.8x: Module %s is out-of-date (hash mismatch). Type information "
+ "from this module may be incomplete or inconsistent with the rest of "
+ "the program. Rebuilding the project will regenerate the needed "
+ "module files.",
+ die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str());
+ }
}
}
Index: lldb/source/Host/common/Host.cpp
===================================================================
--- lldb/source/Host/common/Host.cpp
+++ lldb/source/Host/common/Host.cpp
@@ -297,6 +297,11 @@
va_start(args, format);
SystemLog(type, format, args);
va_end(args);
+
+ // Log to log channel. This allows testcases to grep for log output.
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_HOST));
+ if (log)
+ log->VAPrintf(format, args);
}
lldb::pid_t Host::GetCurrentProcessID() { return ::getpid(); }
Index: lldb/packages/Python/lldbsuite/test/make/Makefile.rules
===================================================================
--- lldb/packages/Python/lldbsuite/test/make/Makefile.rules
+++ lldb/packages/Python/lldbsuite/test/make/Makefile.rules
@@ -25,6 +25,7 @@
# LD_EXTRAS :=
# SPLIT_DEBUG_SYMBOLS := YES
# CROSS_COMPILE :=
+# USE_PRIVATE_MODULE_CACHE := YES
#
# And test/functionalities/archives/Makefile:
# MAKE_DSYM := NO
@@ -306,7 +307,13 @@
CFLAGS += -gsplit-dwarf
endif
-MODULE_BASE_FLAGS := -fmodules -gmodules -fmodules-cache-path=$(CLANG_MODULE_CACHE_DIR)
+ifeq "$(USE_PRIVATE_MODULE_CACHE)" "YES"
+THE_CLANG_MODULE_CACHE_DIR := $(BUILDDIR)/private-module-cache
+else
+THE_CLANG_MODULE_CACHE_DIR := $(CLANG_MODULE_CACHE_DIR)
+endif
+
+MODULE_BASE_FLAGS := -fmodules -gmodules -fmodules-cache-path=$(THE_CLANG_MODULE_CACHE_DIR)
MANDATORY_MODULE_BUILD_CFLAGS := $(MODULE_BASE_FLAGS) -gmodules
# Build flags for building with C++ modules.
# -glldb is necessary for emitting information about what modules were imported.
Index: lldb/packages/Python/lldbsuite/test/lang/objc/modules-hash-mismatch/other.m
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/lang/objc/modules-hash-mismatch/other.m
@@ -0,0 +1,4 @@
+#include "f.h"
+something_other f() {
+ return 0;
+}
Index: lldb/packages/Python/lldbsuite/test/lang/objc/modules-hash-mismatch/main.m
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/lang/objc/modules-hash-mismatch/main.m
@@ -0,0 +1,6 @@
+#include "f.h"
+int main(int argc, char **argv) {
+ my_int i = argc;
+ f(); // break here
+ return 0;
+}
Index: lldb/packages/Python/lldbsuite/test/lang/objc/modules-hash-mismatch/TestClangModulesHashMismatch.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/lang/objc/modules-hash-mismatch/TestClangModulesHashMismatch.py
@@ -0,0 +1,49 @@
+from __future__ import print_function
+
+import unittest2
+import os
+import shutil
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestClangModuleHashMismatch(TestBase):
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ TestBase.setUp(self)
+
+ @skipUnlessDarwin
+ @skipIf(debug_info=no_match(["gmodules"]))
+ def test_expr(self):
+ with open(self.getBuildArtifact("module.modulemap"), "w") as f:
+ f.write("""
+ module Foo { header "f.h" }
+ """)
+ with open(self.getBuildArtifact("f.h"), "w") as f:
+ f.write("""
+ typedef int my_int;
+ void f() {}
+ """)
+
+ mod_cache = self.getBuildArtifact("private-module-cache")
+ if os.path.isdir(mod_cache):
+ shutil.rmtree(mod_cache)
+ self.build()
+ self.assertTrue(os.path.isdir(mod_cache), "module cache exists")
+
+ logfile = self.getBuildArtifact("host.log")
+ self.runCmd("log enable -f %s lldb host" % logfile)
+ target, _, _, _ = lldbutil.run_to_source_breakpoint(
+ self, "break here", lldb.SBFileSpec("main.m"))
+ target.GetModuleAtIndex(0).FindTypes('my_int')
+
+ found = False
+ with open(logfile, 'r') as f:
+ for line in f:
+ if "hash mismatch" in line and "Foo" in line:
+ found = True
+ self.assertTrue(found)
Index: lldb/packages/Python/lldbsuite/test/lang/objc/modules-hash-mismatch/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/lang/objc/modules-hash-mismatch/Makefile
@@ -0,0 +1,16 @@
+OBJC_SOURCES := main.m
+CFLAGS_EXTRAS = -I$(BUILDDIR)
+USE_PRIVATE_MODULE_CACHE = YES
+
+.PHONY: update-module
+
+all: $(EXE)
+ $(MAKE) -f $(SRCDIR)/Makefile update-module
+
+include Makefile.rules
+
+update-module:
+ echo "forcing an update of f.pcm"
+ echo "typedef int something_other;" > $(BUILDDIR)/f.h
+ $(CC) $(CFLAGS) $(MANDATORY_MODULE_BUILD_CFLAGS) \
+ -c $(SRCDIR)/other.m -o $(BUILDDIR)/other.o
Index: lldb/include/lldb/Utility/Log.h
===================================================================
--- lldb/include/lldb/Utility/Log.h
+++ lldb/include/lldb/Utility/Log.h
@@ -166,10 +166,10 @@
bool GetVerbose() const;
-private:
void VAPrintf(const char *format, va_list args);
void VAError(const char *format, va_list args);
+private:
Channel &m_channel;
// The mutex makes sure enable/disable operations are thread-safe. The
Index: lldb/include/lldb/Symbol/SymbolFile.h
===================================================================
--- lldb/include/lldb/Symbol/SymbolFile.h
+++ lldb/include/lldb/Symbol/SymbolFile.h
@@ -280,6 +280,9 @@
"Operation not supported.");
}
+ /// Return a hash for this symbol file, such as a dwo_id.
+ virtual llvm::Optional<uint64_t> GetSymbolHash() { return {}; }
+
virtual void Dump(Stream &s);
protected:
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits