[llvm] r231493 - [dsymutil] Add debug_str construction support.
Frederic Riss
friss at apple.com
Fri Mar 6 09:56:30 PST 2015
Author: friss
Date: Fri Mar 6 11:56:30 2015
New Revision: 231493
URL: http://llvm.org/viewvc/llvm-project?rev=231493&view=rev
Log:
[dsymutil] Add debug_str construction support.
With this comes the ability to correctly clone string attributes in DIEs.
Modified:
llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test
llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test
llvm/trunk/tools/dsymutil/DwarfLinker.cpp
Modified: llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test?rev=231493&r1=231492&r2=231493&view=diff
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test (original)
+++ llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test Fri Mar 6 11:56:30 2015
@@ -13,29 +13,36 @@ CHECK: debug_info contents
CHECK: Compile Unit:
CHECK: DW_TAG_compile_unit [1] *
+CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99)
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000040] = "basic1.c")
+CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
CHECK: DW_TAG_subprogram [2] *
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000051] = "main")
CHECK: DW_AT_decl_line [DW_FORM_data1] (23)
CHECK: DW_AT_prototyped [DW_FORM_flag] (0x01)
CHECK: DW_AT_external [DW_FORM_flag] (0x01)
CHECK: DW_AT_accessibility [DW_FORM_data1] (DW_ACCESS_public)
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: DW_TAG_formal_parameter [3]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000056] = "argc")
CHECK: DW_AT_decl_line [DW_FORM_data1] (23)
CHECK: DW_AT_location [DW_FORM_block1] (<0x02> 91 78 )
CHECK: DW_TAG_formal_parameter [3]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000005b] = "argv")
CHECK: DW_AT_decl_file [DW_FORM_data1] (0x01)
CHECK: DW_AT_decl_line [DW_FORM_data1] (23)
CHECK: DW_AT_location [DW_FORM_block1] (<0x02> 91 70 )
CHECK: NULL
CHECK: DW_TAG_base_type [4]
-CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000000] = )
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000060] = "int")
CHECK: DW_AT_encoding [DW_FORM_data1] (DW_ATE_signed)
CHECK: DW_AT_byte_size [DW_FORM_data1] (0x04)
CHECK: DW_TAG_pointer_type [5]
CHECK: DW_TAG_pointer_type [5]
CHECK: DW_TAG_const_type [6]
CHECK: DW_TAG_base_type [4]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000064] = "char")
CHECK: DW_AT_encoding [DW_FORM_data1] (DW_ATE_signed_char)
CHECK: DW_AT_byte_size [DW_FORM_data1] (0x01)
CHECK: NULL
@@ -43,30 +50,47 @@ CHECK: NULL
CHECK: Compile Unit:
CHECK: DW_TAG_compile_unit [1] *
+CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000069] = "basic2.c")
+CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
CHECK: DW_TAG_base_type [4]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000060] = "int")
CHECK: DW_TAG_variable [7]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000072] = "private_int")
CHECK: DW_TAG_variable [7]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000007e] = "baz")
CHECK: DW_TAG_subprogram [2] *
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000082] = "foo")
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: DW_TAG_formal_parameter [3]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000086] = "arg")
CHECK: DW_AT_location [DW_FORM_block1] (<0x02> 91 7c )
CHECK: NULL
CHECK: DW_TAG_subprogram [8]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008a] = "inc")
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: NULL
CHECK: Compile Unit:
CHECK: DW_TAG_compile_unit [1] *
+CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008e] = "basic3.c")
+CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
CHECK: DW_TAG_variable [9]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000097] = "val")
CHECK: DW_TAG_volatile_type [10]
CHECK: DW_TAG_base_type [4]
+CHACK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000060] = "int")
CHECK: DW_TAG_subprogram [2] *
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000009b] = "bar")
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: DW_TAG_formal_parameter [3]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000086] = "arg")
CHECK: DW_AT_location [DW_FORM_block1] (<0x02> 91 78 )
CHECK: NULL
CHECK: DW_TAG_subprogram [8]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008a] = "inc")
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: NULL
Modified: llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test?rev=231493&r1=231492&r2=231493&view=diff
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test (original)
+++ llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test Fri Mar 6 11:56:30 2015
@@ -7,25 +7,33 @@ CHECK: debug_info contents
CHECK: Compile Unit:
CHECK: DW_TAG_compile_unit [1] *
+CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99)
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000040] = "basic1.c")
+CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
CHECK: DW_TAG_subprogram [2] *
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000051] = "main")
CHECK: DW_AT_decl_line [DW_FORM_data1] (23)
CHECK: DW_AT_prototyped [DW_FORM_flag] (0x01)
CHECK: DW_AT_external [DW_FORM_flag] (0x01)
CHECK: DW_AT_accessibility [DW_FORM_data1] (DW_ACCESS_public)
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: DW_TAG_formal_parameter [3]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000056] = "argc")
CHECK: DW_AT_location [DW_FORM_block1] (<0x03> 55 93 04 )
CHECK: DW_TAG_formal_parameter [3]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000005b] = "argv")
CHECK: DW_AT_location [DW_FORM_block1] (<0x01> 54 )
CHECK: NULL
-CHECK: DW_TAG_base_type [4
+CHECK: DW_TAG_base_type [4]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000060] = "int")
CHECK: DW_AT_encoding [DW_FORM_data1] (DW_ATE_signed)
CHECK: DW_AT_byte_size [DW_FORM_data1] (0x04)
CHECK: DW_TAG_pointer_type [5]
CHECK: DW_TAG_pointer_type [5]
CHECK: DW_TAG_const_type [6]
CHECK: DW_TAG_base_type [4]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000064] = "char")
CHECK: DW_AT_encoding [DW_FORM_data1] (DW_ATE_signed_char)
CHECK: DW_AT_byte_size [DW_FORM_data1] (0x01)
CHECK: NULL
@@ -33,29 +41,44 @@ CHECK: NULL
CHECK: Compile Unit:
CHECK: DW_TAG_compile_unit [1] *
+CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000069] = "basic2.c")
+CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
CHECK: DW_TAG_variable [7]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000072] = "private_int")
CHECK: DW_TAG_variable [7]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000007e] = "baz")
CHECK: DW_TAG_subprogram [8] *
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000082] = "foo")
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: DW_TAG_formal_parameter [9]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000086] = "arg")
CHECK: DW_TAG_inlined_subroutine [10]
CHECK: DW_AT_call_line [DW_FORM_data1] (20)
CHECK: NULL
CHECK: DW_TAG_subprogram [11]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008a] = "inc")
CHECK: DW_AT_inline [DW_FORM_data1] (DW_INL_inlined)
CHECK: NULL
CHECK: Compile Unit:
CHECK: DW_TAG_compile_unit [1] *
+CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008e] = "basic3.c")
+CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
CHECK: DW_TAG_variable [12]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000097] = "val")
CHECK: DW_TAG_volatile_type [13]
CHECK: DW_TAG_subprogram [8] *
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000009b] = "bar")
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: DW_TAG_formal_parameter [9]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000086] = "arg")
CHECK: DW_TAG_lexical_block [14] *
CHECK: DW_TAG_inlined_subroutine [15]
CHECK: NULL
CHECK: NULL
CHECK: DW_TAG_subprogram [11]
+CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008a] = "inc")
CHECK: NULL
Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=231493&r1=231492&r2=231493&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Fri Mar 6 11:56:30 2015
@@ -108,6 +108,91 @@ uint64_t CompileUnit::computeOffsets(uin
return NextUnitOffset;
}
+/// \brief A string table that doesn't need relocations.
+///
+/// We are doing a final link, no need for a string table that
+/// has relocation entries for every reference to it. This class
+/// provides this ablitity by just associating offsets with
+/// strings.
+class NonRelocatableStringpool {
+public:
+ /// \brief Entries are stored into the StringMap and simply linked
+ /// together through the second element of this pair in order to
+ /// keep track of insertion order.
+ typedef StringMap<std::pair<uint32_t, StringMapEntryBase *>, BumpPtrAllocator>
+ MapTy;
+
+ NonRelocatableStringpool()
+ : CurrentEndOffset(0), Sentinel(0), Last(&Sentinel) {
+ // Legacy dsymutil puts an empty string at the start of the line
+ // table.
+ getStringOffset("");
+ }
+
+ /// \brief Get the offset of string \p S in the string table. This
+ /// can insert a new element or return the offset of a preexisitng
+ /// one.
+ uint32_t getStringOffset(StringRef S);
+
+ /// \brief Get permanent storage for \p S (but do not necessarily
+ /// emit \p S in the output section).
+ /// \returns The StringRef that points to permanent storage to use
+ /// in place of \p S.
+ StringRef internString(StringRef S);
+
+ // \brief Return the first entry of the string table.
+ const MapTy::MapEntryTy *getFirstEntry() const {
+ return getNextEntry(&Sentinel);
+ }
+
+ // \brief Get the entry following \p E in the string table or null
+ // if \p E was the last entry.
+ const MapTy::MapEntryTy *getNextEntry(const MapTy::MapEntryTy *E) const {
+ return static_cast<const MapTy::MapEntryTy *>(E->getValue().second);
+ }
+
+ uint64_t getSize() { return CurrentEndOffset; }
+
+private:
+ MapTy Strings;
+ uint32_t CurrentEndOffset;
+ MapTy::MapEntryTy Sentinel, *Last;
+};
+
+/// \brief Get the offset of string \p S in the string table. This
+/// can insert a new element or return the offset of a preexisitng
+/// one.
+uint32_t NonRelocatableStringpool::getStringOffset(StringRef S) {
+ if (S.empty() && !Strings.empty())
+ return 0;
+
+ std::pair<uint32_t, StringMapEntryBase *> Entry(0, nullptr);
+ MapTy::iterator It;
+ bool Inserted;
+
+ // A non-empty string can't be at offset 0, so if we have an entry
+ // with a 0 offset, it must be a previously interned string.
+ std::tie(It, Inserted) = Strings.insert(std::make_pair(S, Entry));
+ if (Inserted || It->getValue().first == 0) {
+ // Set offset and chain at the end of the entries list.
+ It->getValue().first = CurrentEndOffset;
+ CurrentEndOffset += S.size() + 1; // +1 for the '\0'.
+ Last->getValue().second = &*It;
+ Last = &*It;
+ }
+ return It->getValue().first;
+};
+
+/// \brief Put \p S into the StringMap so that it gets permanent
+/// storage, but do not actually link it in the chain of elements
+/// that go into the output section. A latter call to
+/// getStringOffset() with the same string will chain it though.
+StringRef NonRelocatableStringpool::internString(StringRef S) {
+ std::pair<uint32_t, StringMapEntryBase *> Entry(0, nullptr);
+ auto InsertResult = Strings.insert(std::make_pair(S, Entry));
+ return InsertResult.first->getKey();
+};
+
/// \brief The Dwarf streaming logic
///
/// All interactions with the MC layer that is used to build the debug
@@ -160,6 +245,9 @@ public:
/// \brief Emit the abbreviation table \p Abbrevs to the
/// debug_abbrev section.
void emitAbbrevs(const std::vector<DIEAbbrev *> &Abbrevs);
+
+ /// \brief Emit the string table described by \p Pool.
+ void emitStrings(const NonRelocatableStringpool &Pool);
};
bool DwarfStreamer::init(Triple TheTriple, StringRef OutputFilename) {
@@ -278,6 +366,15 @@ void DwarfStreamer::emitDIE(DIE &Die) {
Asm->emitDwarfDIE(Die);
}
+/// \brief Emit the debug_str section stored in \p Pool.
+void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
+ Asm->OutStreamer.SwitchSection(MOFI->getDwarfStrSection());
+ for (auto *Entry = Pool.getFirstEntry(); Entry;
+ Entry = Pool.getNextEntry(Entry))
+ Asm->OutStreamer.EmitBytes(
+ StringRef(Entry->getKey().data(), Entry->getKey().size() + 1));
+}
+
/// \brief The core of the Dwarf linking logic.
///
/// The link of the dwarf information from the object files will be
@@ -417,7 +514,8 @@ private:
const AttributeSpec AttrSpec, unsigned AttrSize);
/// \brief Helper for cloneDIE.
- unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec);
+ unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
+ const DWARFFormValue &Val, const DWARFUnit &U);
/// \brief Helper for cloneDIE.
unsigned cloneDieReferenceAttribute(DIE &Die, AttributeSpec AttrSpec,
@@ -478,6 +576,9 @@ private:
/// The debug map object curently under consideration.
DebugMapObject *CurrentDebugObject;
+
+ /// \brief The Dwarf string pool
+ NonRelocatableStringpool StringPool;
};
/// \brief Similar to DWARFUnitSection::getUnitForOffset(), but
@@ -944,11 +1045,14 @@ void DwarfLinker::AssignAbbrev(DIEAbbrev
/// \brief Clone a string attribute described by \p AttrSpec and add
/// it to \p Die.
/// \returns the size of the new attribute.
-unsigned DwarfLinker::cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec) {
+unsigned DwarfLinker::cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
+ const DWARFFormValue &Val,
+ const DWARFUnit &U) {
// Switch everything to out of line strings.
- // FIXME: Construct the actual string table.
+ const char *String = *Val.getAsCString(&U);
+ unsigned Offset = StringPool.getStringOffset(String);
Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_strp,
- new (DIEAlloc) DIEInteger(0));
+ new (DIEAlloc) DIEInteger(Offset));
return 4;
}
@@ -1040,7 +1144,7 @@ unsigned DwarfLinker::cloneAttribute(DIE
switch (AttrSpec.Form) {
case dwarf::DW_FORM_strp:
case dwarf::DW_FORM_string:
- return cloneStringAttribute(Die, AttrSpec);
+ return cloneStringAttribute(Die, AttrSpec, Val, U);
case dwarf::DW_FORM_ref_addr:
case dwarf::DW_FORM_ref1:
case dwarf::DW_FORM_ref2:
@@ -1223,8 +1327,10 @@ bool DwarfLinker::link(const DebugMap &M
}
// Emit everything that's global.
- if (!Options.NoOutput)
+ if (!Options.NoOutput) {
Streamer->emitAbbrevs(Abbreviations);
+ Streamer->emitStrings(StringPool);
+ }
return Options.NoOutput ? true : Streamer->finish();
}
More information about the llvm-commits
mailing list