From f2580f0981681484b9b7c9c1d4f64e808a02599a Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Fri, 5 Jan 2024 14:25:17 -0800 Subject: [PATCH] [DWARFLinker] Support MD5 checksums in the line table Add support to the DWARF linkers for emitting DWARF 5 MD5 checksum in the line table. --- llvm/lib/DWARFLinker/DWARFStreamer.cpp | 24 +++++++++++++------ .../DebugLineSectionEmitter.h | 13 +++++++++- .../DWARFLinkerParallel/OutputSections.cpp | 4 ++++ llvm/lib/DWARFLinkerParallel/OutputSections.h | 2 ++ .../ARM/dwarf5-dwarf4-combination-macho.test | 12 +++++----- .../test/tools/dsymutil/ARM/dwarf5-macho.test | 9 +++---- 6 files changed, 46 insertions(+), 18 deletions(-) diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp index faa91364ec9c3..3ec082f4ea0c2 100644 --- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp +++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp @@ -859,10 +859,8 @@ void DwarfStreamer::emitLineTablePrologueV5IncludeAndFileTable( for (auto Include : P.IncludeDirectories) emitLineTableString(P, Include, DebugStrPool, DebugLineStrPool); - bool InlineSources = any_of(P.FileNames, [](auto &File) { - auto s = dwarf::toString(File.Source); - return s && !**s; - }); + bool HasChecksums = P.ContentTypes.HasMD5; + bool HasInlineSources = P.ContentTypes.HasSource; if (P.FileNames.empty()) { // file_name_entry_format_count (ubyte). @@ -870,7 +868,7 @@ void DwarfStreamer::emitLineTablePrologueV5IncludeAndFileTable( LineSectionSize += 1; } else { // file_name_entry_format_count (ubyte). - MS->emitInt8(2 + (InlineSources ? 1 : 0)); + MS->emitInt8(2 + (HasChecksums ? 1 : 0) + (HasInlineSources ? 1 : 0)); LineSectionSize += 1; // file_name_entry_format (sequence of ULEB128 pairs). @@ -880,7 +878,13 @@ void DwarfStreamer::emitLineTablePrologueV5IncludeAndFileTable( LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index); LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_FORM_data1); - if (InlineSources) { + + if (HasChecksums) { + LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_MD5); + LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_FORM_data16); + } + + if (HasInlineSources) { LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source); LineSectionSize += MS->emitULEB128IntValue(StrForm); } @@ -894,7 +898,13 @@ void DwarfStreamer::emitLineTablePrologueV5IncludeAndFileTable( emitLineTableString(P, File.Name, DebugStrPool, DebugLineStrPool); MS->emitInt8(File.DirIdx); LineSectionSize += 1; - if (InlineSources) + if (HasChecksums) { + MS->emitBinaryData( + StringRef(reinterpret_cast(File.Checksum.data()), + File.Checksum.size())); + LineSectionSize += File.Checksum.size(); + } + if (HasInlineSources) emitLineTableString(P, File.Source, DebugStrPool, DebugLineStrPool); } } diff --git a/llvm/lib/DWARFLinkerParallel/DebugLineSectionEmitter.h b/llvm/lib/DWARFLinkerParallel/DebugLineSectionEmitter.h index fc7f8cbc4a8e7..27c63fad712f1 100644 --- a/llvm/lib/DWARFLinkerParallel/DebugLineSectionEmitter.h +++ b/llvm/lib/DWARFLinkerParallel/DebugLineSectionEmitter.h @@ -197,7 +197,7 @@ class DebugLineSectionEmitter { Section.emitIntVal(0, 1); } else { // file_name_entry_format_count (ubyte). - Section.emitIntVal(2, 1); + Section.emitIntVal(2 + (P.ContentTypes.HasMD5 ? 1 : 0), 1); // file_name_entry_format (sequence of ULEB128 pairs). encodeULEB128(dwarf::DW_LNCT_path, Section.OS); @@ -205,6 +205,11 @@ class DebugLineSectionEmitter { encodeULEB128(dwarf::DW_LNCT_directory_index, Section.OS); encodeULEB128(dwarf::DW_FORM_data1, Section.OS); + + if (P.ContentTypes.HasMD5) { + encodeULEB128(dwarf::DW_LNCT_MD5, Section.OS); + encodeULEB128(dwarf::DW_FORM_data16, Section.OS); + } } // file_names_count (ULEB128). @@ -222,6 +227,12 @@ class DebugLineSectionEmitter { // source file. Section.emitString(File.Name.getForm(), *FileNameStr); Section.emitIntVal(File.DirIdx, 1); + + if (P.ContentTypes.HasMD5) { + Section.emitBinaryData( + StringRef(reinterpret_cast(File.Checksum.data()), + File.Checksum.size())); + } } } diff --git a/llvm/lib/DWARFLinkerParallel/OutputSections.cpp b/llvm/lib/DWARFLinkerParallel/OutputSections.cpp index 9c3e3ebd220aa..730ae0f83d7b2 100644 --- a/llvm/lib/DWARFLinkerParallel/OutputSections.cpp +++ b/llvm/lib/DWARFLinkerParallel/OutputSections.cpp @@ -227,6 +227,10 @@ void SectionDescriptor::emitIntVal(uint64_t Val, unsigned Size) { } } +void SectionDescriptor::emitBinaryData(llvm::StringRef Data) { + OS.write(Data.data(), Data.size()); +} + void SectionDescriptor::apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val) { switch (AttrForm) { diff --git a/llvm/lib/DWARFLinkerParallel/OutputSections.h b/llvm/lib/DWARFLinkerParallel/OutputSections.h index f23b2efb869da..0f394b0810ea9 100644 --- a/llvm/lib/DWARFLinkerParallel/OutputSections.h +++ b/llvm/lib/DWARFLinkerParallel/OutputSections.h @@ -283,6 +283,8 @@ struct SectionDescriptor { void emitString(dwarf::Form StringForm, const char *StringVal); + void emitBinaryData(llvm::StringRef Data); + /// Emit specified inplace string value into the current section contents. void emitInplaceString(StringRef String) { OS << GlobalData.translateString(String); diff --git a/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test b/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test index 0199bf28681bc..d5b78bd1487e1 100644 --- a/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test +++ b/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test @@ -73,7 +73,7 @@ CHECK-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000000) address = 0x[[ CHECK: DW_AT_linkage_name [DW_FORM_strx] (indexed (00000005) string = "_Z4foo2i") CHECK: DW_AT_name [DW_FORM_strx] (indexed (00000006) string = "foo2") CHECK: DW_TAG_formal_parameter -CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x[[LOCLIST_OFFSET:[0-9a-f]+]]: +CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x[[LOCLIST_OFFSET:[0-9a-f]+]]: CHECK-NEXT: [0x[[#%.16x,LOCLIST_PAIR_START:]], 0x[[#%.16x,LOCLIST_PAIR_END:]]): [[LOCLIST_EXPR:.*]] CHECK-NEXT: [0x[[#%.16x,LOCLIST_PAIR_START2:]], 0x[[#%.16x,LOCLIST_PAIR_END2:]]): [[LOCLIST_EXPR2:.*]]) CHECK: DW_AT_name [DW_FORM_strx] (indexed (00000007) string = "a") @@ -93,7 +93,7 @@ CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x[[#%.16x,LOC_LOWPC CHECK: DW_AT_linkage_name [DW_FORM_strp] ( .debug_str[0x000000e6] = "_Z3bari") CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000ee] = "bar") CHECK: DW_TAG_formal_parameter -CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x[[LOC_OFFSET:[0-9a-f]+]]: +CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x[[LOC_OFFSET:[0-9a-f]+]]: CHECK-NEXT: [0x[[#%.16x,LOC_PAIR_START:]], 0x[[#%.16x,LOC_PAIR_END:]]): [[LOC_EXPR:.*]] CHECK-NEXT: [0x[[#%.16x,LOC_PAIR_START2:]], 0x[[#%.16x,LOC_PAIR_END2:]]): [[LOC_EXPR2:.*]]) CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000f2] = "x") @@ -105,7 +105,7 @@ CHECK-NEXT: (0x[[#sub(LOC_PAIR_START2,LOC_LOWPC)]], 0x[[#sub(LOC_PAIR CHECK: .debug_loclists contents: CHECK-NEXT: 0x00000000: locations list header: length = 0x00000018, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 -CHECK-NEXT: 0x[[LOCLIST_OFFSET]]: +CHECK-NEXT: 0x[[LOCLIST_OFFSET]]: CHECK-NEXT: DW_LLE_base_addressx (0x0000000000000000) CHECK-NEXT: DW_LLE_offset_pair (0x[[#sub(LOCLIST_PAIR_START,LOCLIST_LOWPC)]], 0x[[#sub(LOCLIST_PAIR_END,LOCLIST_LOWPC)]]) CHECK-NEXT: DW_LLE_offset_pair (0x[[#sub(LOCLIST_PAIR_START2,LOCLIST_LOWPC)]], 0x[[#sub(LOCLIST_PAIR_END2,LOCLIST_LOWPC)]]) @@ -114,12 +114,12 @@ CHECK-NEXT: DW_LLE_end_of_list () CHECK: .debug_line contents: CHECK-NEXT: debug_line[0x00000000] CHECK-NEXT: Line table prologue: -CHECK-NEXT: total_length: 0x00000048 +CHECK-NEXT: total_length: 0x0000005a CHECK-NEXT: format: DWARF32 CHECK-NEXT: version: 5 CHECK-NEXT: address_size: 8 CHECK-NEXT: seg_select_size: 0 -CHECK-NEXT: prologue_length: 0x00000025 +CHECK-NEXT: prologue_length: 0x00000037 CHECK-NEXT: min_inst_length: 1 CHECK-NEXT: max_ops_per_inst: 1 CHECK-NEXT: default_is_stmt: 1 @@ -143,7 +143,7 @@ CHECK-NEXT: file_names[ 0]: CHECK-NEXT: name: .debug_line_str[0x00000029] = "a.cpp" CHECK-NEXT: dir_index: 0 -CHECK: debug_line[0x0000004c] +CHECK: debug_line[0x0000005e] CHECK-NEXT: Line table prologue: CHECK-NEXT: total_length: 0x0000003b CHECK-NEXT: format: DWARF32 diff --git a/llvm/test/tools/dsymutil/ARM/dwarf5-macho.test b/llvm/test/tools/dsymutil/ARM/dwarf5-macho.test index 13409b2a07a31..f6d42a18424cf 100644 --- a/llvm/test/tools/dsymutil/ARM/dwarf5-macho.test +++ b/llvm/test/tools/dsymutil/ARM/dwarf5-macho.test @@ -49,13 +49,13 @@ CHECK-NEXT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000008) CHECK: DW_TAG_subprogram CHECK-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000000) address = 0x[[#%.16x,LOCLIST_LOWPC:]]) CHECK: DW_TAG_formal_parameter -CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x[[LOC_OFFSET:[0-9a-f]+]]: +CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x[[LOC_OFFSET:[0-9a-f]+]]: CHECK-NEXT: [0x[[#%.16x,LOCLIST_PAIR_START:]], 0x[[#%.16x,LOCLIST_PAIR_END:]]): [[LOCLIST_EXPR:.*]] CHECK-NEXT: [0x[[#%.16x,LOCLIST_PAIR_START2:]], 0x[[#%.16x,LOCLIST_PAIR_END2:]]): [[LOCLIST_EXPR2:.*]]) CHECK: .debug_loclists contents: CHECK-NEXT: 0x00000000: locations list header: length = 0x00000018, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 -CHECK-NEXT: 0x[[LOC_OFFSET]]: +CHECK-NEXT: 0x[[LOC_OFFSET]]: CHECK-NEXT: DW_LLE_base_addressx (0x0000000000000000) CHECK-NEXT: DW_LLE_offset_pair (0x[[#sub(LOCLIST_PAIR_START,LOCLIST_LOWPC)]], 0x[[#sub(LOCLIST_PAIR_END,LOCLIST_LOWPC)]]) CHECK-NEXT: DW_LLE_offset_pair (0x[[#sub(LOCLIST_PAIR_START2,LOCLIST_LOWPC)]], 0x[[#sub(LOCLIST_PAIR_END2,LOCLIST_LOWPC)]]) @@ -64,12 +64,12 @@ CHECK-NEXT: DW_LLE_end_of_list () CHECK: .debug_line contents: CHECK-NEXT: debug_line[0x00000000] CHECK-NEXT: Line table prologue: -CHECK-NEXT: total_length: 0x00000048 +CHECK-NEXT: total_length: 0x0000005a CHECK-NEXT: format: DWARF32 CHECK-NEXT: version: 5 CHECK-NEXT: address_size: 8 CHECK-NEXT: seg_select_size: 0 -CHECK-NEXT: prologue_length: 0x00000025 +CHECK-NEXT: prologue_length: 0x00000037 CHECK-NEXT: min_inst_length: 1 CHECK-NEXT: max_ops_per_inst: 1 CHECK-NEXT: default_is_stmt: 1 @@ -92,6 +92,7 @@ CHECK-NEXT: include_directories[ 0] = .debug_line_str[0x00000000] = "/Users/sh CHECK-NEXT: file_names[ 0]: CHECK-NEXT: name: .debug_line_str[0x00000029] = "a.cpp" CHECK-NEXT: dir_index: 0 +CHECK-NEXT: md5_checksum: 2675ab7ce3623b564cfd8a2906a462e5 CHECK: .debug_str contents: