[llvm] r248331 - dsymutil: Follow references to clang modules and recursively clone the
Adrian Prantl via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 22 15:20:50 PDT 2015
Author: adrian
Date: Tue Sep 22 17:20:50 2015
New Revision: 248331
URL: http://llvm.org/viewvc/llvm-project?rev=248331&view=rev
Log:
dsymutil: Follow references to clang modules and recursively clone the
debug info.
This does not yet resolve external type references.
Added:
llvm/trunk/test/tools/dsymutil/Inputs/modules/
llvm/trunk/test/tools/dsymutil/Inputs/modules/1.o
llvm/trunk/test/tools/dsymutil/Inputs/modules/Bar.pcm
llvm/trunk/test/tools/dsymutil/Inputs/modules/Foo.pcm
llvm/trunk/test/tools/dsymutil/X86/modules.m
Modified:
llvm/trunk/test/tools/dsymutil/X86/lit.local.cfg
llvm/trunk/tools/dsymutil/DwarfLinker.cpp
Added: llvm/trunk/test/tools/dsymutil/Inputs/modules/1.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/modules/1.o?rev=248331&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/dsymutil/Inputs/modules/1.o (added) and llvm/trunk/test/tools/dsymutil/Inputs/modules/1.o Tue Sep 22 17:20:50 2015 differ
Added: llvm/trunk/test/tools/dsymutil/Inputs/modules/Bar.pcm
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/modules/Bar.pcm?rev=248331&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/dsymutil/Inputs/modules/Bar.pcm (added) and llvm/trunk/test/tools/dsymutil/Inputs/modules/Bar.pcm Tue Sep 22 17:20:50 2015 differ
Added: llvm/trunk/test/tools/dsymutil/Inputs/modules/Foo.pcm
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/modules/Foo.pcm?rev=248331&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/dsymutil/Inputs/modules/Foo.pcm (added) and llvm/trunk/test/tools/dsymutil/Inputs/modules/Foo.pcm Tue Sep 22 17:20:50 2015 differ
Modified: llvm/trunk/test/tools/dsymutil/X86/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/lit.local.cfg?rev=248331&r1=248330&r2=248331&view=diff
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/lit.local.cfg (original)
+++ llvm/trunk/test/tools/dsymutil/X86/lit.local.cfg Tue Sep 22 17:20:50 2015
@@ -1,4 +1,4 @@
if not 'X86' in config.root.targets:
config.unsupported = True
-config.suffixes = ['.test', '.cpp', '.s']
+config.suffixes = ['.test', '.cpp', '.m', '.s']
Added: llvm/trunk/test/tools/dsymutil/X86/modules.m
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/modules.m?rev=248331&view=auto
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/modules.m (added)
+++ llvm/trunk/test/tools/dsymutil/X86/modules.m Tue Sep 22 17:20:50 2015
@@ -0,0 +1,62 @@
+/* Compile with:
+ cat >modules.modulemap <<EOF
+ module Foo {
+ header "Foo.h"
+ export *
+ }
+ module Bar {
+ header "Bar.h"
+ export *
+ }
+ EOF
+ clang -D BAR_H -E -o Bar.h
+ clang -D FOO_H -E -o Foo.h
+ clang -cc1 -emit-obj -fmodules -fmodule-map-file=modules.modulemap \
+ -fmodule-format=obj -g -dwarf-ext-refs -fmodules-cache-path=. \
+ -fdisable-module-hash modules.m -o 1.o
+*/
+
+// RUN: llvm-dsymutil -f -oso-prepend-path=%p/../Inputs/modules \
+// RUN: -y %p/dummy-debug-map.map -o - \
+// RUN: | llvm-dwarfdump --debug-dump=info - | FileCheck %s
+
+// ---------------------------------------------------------------------
+#ifdef BAR_H
+// ---------------------------------------------------------------------
+// CHECK: DW_TAG_compile_unit
+// CHECK: DW_TAG_module
+// CHECK-NEXT: DW_AT_name {{.*}}"Bar"
+// CHECK: DW_TAG_member
+// CHECK: DW_AT_name {{.*}}"value"
+
+struct Bar {
+ int value;
+};
+
+#else
+// ---------------------------------------------------------------------
+#ifdef FOO_H
+// ---------------------------------------------------------------------
+// CHECK: 55{{.*}}DW_TAG_compile_unit
+// CHECK: DW_TAG_module
+// CHECK-NEXT: DW_AT_name {{.*}}"Foo"
+// CHECK: DW_TAG_typedef
+ at import Bar;
+typedef struct Bar Bar;
+struct S {};
+
+// ---------------------------------------------------------------------
+#else
+// ---------------------------------------------------------------------
+
+// CHECK: DW_TAG_compile_unit
+// CHECK: DW_TAG_subprogram
+// CHECK: DW_AT_name {{.*}}"main"
+ at import Foo;
+int main(int argc, char **argv) {
+ Bar bar;
+ bar.value = 42;
+ return bar.value;
+}
+#endif
+#endif
Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=248331&r1=248330&r2=248331&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Tue Sep 22 17:20:50 2015
@@ -13,7 +13,7 @@
#include "MachOUtils.h"
#include "NonRelocatableStringpool.h"
#include "llvm/ADT/IntervalMap.h"
-#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DIE.h"
@@ -248,6 +248,14 @@ public:
return LocationAttributes;
}
+ void setHasInterestingContent() { HasInterestingContent = true; }
+ bool hasInterestingContent() { return HasInterestingContent; }
+
+ /// Mark every DIE in this unit as kept. This function also
+ /// marks variables as InDebugMap so that they appear in the
+ /// reconstructed accelerator tables.
+ void markEverythingAsKept();
+
/// \brief Compute the end offset for this unit. Must be
/// called after the CU's DIEs have been cloned.
/// \returns the next unit offset (which is also the current
@@ -368,8 +376,15 @@ private:
/// Is this unit subject to the ODR rule?
bool HasODR;
+ /// Did a DIE actually contain a valid reloc?
+ bool HasInterestingContent;
};
+void CompileUnit::markEverythingAsKept() {
+ for (auto &I : Info)
+ I.Keep = true;
+}
+
uint64_t CompileUnit::computeNextUnitOffset() {
NextUnitOffset = StartOffset + 11 /* Header size */;
// The root DIE might be null, meaning that the Unit had nothing to
@@ -1177,6 +1192,22 @@ private:
const DebugMapObject &DMO, CompileUnit &CU,
unsigned Flags);
+ /// If this compile unit is really a skeleton CU that points to a
+ /// clang module, register it in ClangModules and return true.
+ ///
+ /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
+ /// pointing to the module, and a DW_AT_gnu_dwo_id with the module
+ /// hash.
+ bool registerModuleReference(const DWARFDebugInfoEntryMinimal &CUDie,
+ const DWARFUnit &Unit, DebugMap &ModuleMap,
+ unsigned Indent = 0);
+
+ /// Recursively add the debug info in this clang module .pcm
+ /// file (and all the modules imported by it in a bottom-up fashion)
+ /// to Units.
+ void loadClangModule(StringRef Filename, StringRef ModulePath,
+ DebugMap &ModuleMap, unsigned Indent = 0);
+
/// \brief Flags passed to DwarfLinker::lookForDIEsToKeep
enum TravesalFlags {
TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept.
@@ -1383,12 +1414,12 @@ private:
const DebugMap &Map);
/// @}
-private:
std::string OutputFilename;
LinkOptions Options;
BinaryHolder BinHolder;
std::unique_ptr<DwarfStreamer> Streamer;
uint64_t OutputDebugInfoSize;
+ unsigned UnitID; ///< A unique ID that identifies each compile unit.
/// The units of the current debug map object.
std::vector<CompileUnit> Units;
@@ -1416,6 +1447,9 @@ private:
/// Offset of the last CIE that has been emitted in the output
/// debug_frame section.
uint32_t LastCIEOffset;
+
+ /// FIXME: We may need to use something more resilient than the PCM filename.
+ StringSet<> ClangModules;
};
/// Similar to DWARFUnitSection::getUnitForOffset(), but returning our
@@ -2588,7 +2622,13 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
// Extract and clone every attribute.
DataExtractor Data = U.getDebugInfoExtractor();
- uint32_t NextOffset = U.getDIEAtIndex(Idx + 1)->getOffset();
+ // Point to the next DIE (generally there is always at least a NULL
+ // entry after the current one). If this is a lone
+ // DW_TAG_compile_unit without any children, point to the next unit.
+ uint32_t NextOffset =
+ (Idx + 1 < U.getNumDIEs())
+ ? U.getDIEAtIndex(Idx + 1)->getOffset()
+ : U.getNextUnitOffset();
AttributesInfo AttrInfo;
// We could copy the data only if we need to aply a relocation to
@@ -3051,6 +3091,38 @@ void DwarfLinker::DIECloner::copyAbbrev(
Linker.AssignAbbrev(Copy);
}
+bool DwarfLinker::registerModuleReference(
+ const DWARFDebugInfoEntryMinimal &CUDie, const DWARFUnit &Unit,
+ DebugMap &ModuleMap, unsigned Indent) {
+ std::string PCMfile =
+ CUDie.getAttributeValueAsString(&Unit, dwarf::DW_AT_GNU_dwo_name, "");
+ if (PCMfile.empty())
+ return false;
+
+ // Clang module DWARF skeleton CUs abuse this for the path to the module.
+ std::string PCMpath =
+ CUDie.getAttributeValueAsString(&Unit, dwarf::DW_AT_comp_dir, "");
+
+ if (Options.Verbose) {
+ outs().indent(Indent);
+ outs() << "Found clang module reference " << PCMfile;
+ }
+
+ if (ClangModules.count(PCMfile)) {
+ if (Options.Verbose)
+ outs() << " [cached].\n";
+ return true;
+ }
+ if (Options.Verbose)
+ outs() << " ...\n";
+
+ // Cyclic dependencies are disallowed by Clang, but we still
+ // shouldn't run into an infinite loop, so mark it as processed now.
+ ClangModules.insert(PCMfile);
+ loadClangModule(PCMfile, PCMpath, ModuleMap, Indent + 2);
+ return true;
+}
+
ErrorOr<const object::ObjectFile &>
DwarfLinker::loadObject(BinaryHolder &BinaryHolder, DebugMapObject &Obj,
const DebugMap &Map) {
@@ -3066,6 +3138,58 @@ DwarfLinker::loadObject(BinaryHolder &Bi
return ErrOrObj;
}
+void DwarfLinker::loadClangModule(StringRef Filename, StringRef ModulePath,
+ DebugMap &ModuleMap, unsigned Indent) {
+ SmallString<80> Path(Options.PrependPath);
+ if (sys::path::is_relative(Filename))
+ sys::path::append(Path, ModulePath, Filename);
+ else
+ sys::path::append(Path, Filename);
+ BinaryHolder ObjHolder(Options.Verbose);
+ auto &Obj =
+ ModuleMap.addDebugMapObject(Path, sys::TimeValue::PosixZeroTime());
+ auto ErrOrObj = loadObject(ObjHolder, Obj, ModuleMap);
+ if (!ErrOrObj) {
+ ClangModules.erase(ClangModules.find(Filename));
+ return;
+ }
+
+ // FIXME: At this point dsymutil should verify the DW_AT_gnu_dwo_id
+ // against the module hash of the clang module.
+
+ CompileUnit *Unit = nullptr;
+
+ // Setup access to the debug info.
+ DWARFContextInMemory DwarfContext(*ErrOrObj);
+ RelocationManager RelocMgr(*this);
+ for (const auto &CU : DwarfContext.compile_units()) {
+ auto *CUDie = CU->getUnitDIE(false);
+ // Recursively get all modules imported by this one.
+ if (!registerModuleReference(*CUDie, *CU, ModuleMap, Indent)) {
+ // Add this module.
+ if (Unit) {
+ errs() << Filename << ": Clang modules are expected to have exactly"
+ << " 1 compile unit.\n";
+ exitDsymutil(1);
+ }
+ Unit = new CompileUnit(*CU, UnitID++, !Options.NoODR);
+ Unit->setHasInterestingContent();
+ gatherDIEParents(CUDie, 0, *Unit, &ODRContexts.getRoot(), StringPool,
+ ODRContexts);
+ // Keep everything.
+ Unit->markEverythingAsKept();
+ }
+ }
+ if (Options.Verbose) {
+ outs().indent(Indent);
+ outs() << "cloning .debug_info from " << Filename << "\n";
+ }
+
+ DIECloner(*this, RelocMgr, DIEAlloc, MutableArrayRef<CompileUnit>(*Unit),
+ Options)
+ .cloneAllCompileUnits(DwarfContext);
+}
+
void DwarfLinker::DIECloner::cloneAllCompileUnits(
DWARFContextInMemory &DwarfContext) {
if (!Linker.Streamer)
@@ -3113,7 +3237,9 @@ bool DwarfLinker::link(const DebugMap &M
// Size of the DIEs (and headers) generated for the linked output.
OutputDebugInfoSize = 0;
// A unique ID that identifies each compile unit.
- unsigned UnitID = 0;
+ UnitID = 0;
+ DebugMap ModuleMap(Map.getTriple(), Map.getBinaryPath());
+
for (const auto &Obj : Map.objects()) {
CurrentDebugObject = Obj.get();
@@ -3143,9 +3269,11 @@ bool DwarfLinker::link(const DebugMap &M
outs() << "Input compilation unit:";
CUDie->dump(outs(), CU.get(), 0);
}
- Units.emplace_back(*CU, UnitID++, !Options.NoODR);
- gatherDIEParents(CUDie, 0, Units.back(), &ODRContexts.getRoot(),
- StringPool, ODRContexts);
+ if (!registerModuleReference(*CUDie, *CU, ModuleMap)) {
+ Units.emplace_back(*CU, UnitID++, !Options.NoODR);
+ gatherDIEParents(CUDie, 0, Units.back(), &ODRContexts.getRoot(),
+ StringPool, ODRContexts);
+ }
}
// Then mark all the DIEs that need to be present in the linked
More information about the llvm-commits
mailing list