Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
## This test checks the warning message displayed if input file
## contains non-empty .debug_macinfo section. Warning message
## should not be displayed if .debug_macinfo is empty.

# RUN: yaml2obj -D MACINFO_CONTENT="0000" %s -o %t.o

# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 \
# RUN: | FileCheck %s -DFILE=%t.o --check-prefix=NOWARN --allow-empty

# RUN: yaml2obj -D MACINFO_CONTENT="0001" %s -o %t.o

# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 \
# RUN: | FileCheck %s -DFILE=%t.o --check-prefix=WARN

# WARN: [[FILE]]: warning: '.debug_macinfo' is not currently supported: file will be skipped
# NOWARN-NOT: warning

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x1000
AddressAlign: 0x0000000000000010
Content: "FFFFFFFF"
- Name: .debug_macinfo
Type: SHT_PROGBITS
Flags: [ ]
Content: [[MACINFO_CONTENT]]
DWARF:
debug_abbrev:
- Table:
- Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_producer
Form: DW_FORM_string
- Attribute: DW_AT_language
Form: DW_FORM_data2
- Attribute: DW_AT_name
Form: DW_FORM_string
- Attribute: DW_AT_low_pc
Form: DW_FORM_addr
- Attribute: DW_AT_high_pc
Form: DW_FORM_data8
debug_info:
- Version: 4
Entries:
- AbbrCode: 1
Values:
- CStr: by_hand
- Value: 0x04
- CStr: CU1
- Value: 0x1000
- Value: 0x4
- AbbrCode: 0
...
54 changes: 54 additions & 0 deletions llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-macro.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## This test checks the warning message displayed if input file
## contains .debug_macro section.

# RUN: yaml2obj %s -o %t.o

# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o

# CHECK: [[FILE]]: warning: '.debug_macro' is not currently supported: file will be skipped

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x1000
AddressAlign: 0x0000000000000010
Content: "FFFFFFFF"
- Name: .debug_macro
Type: SHT_PROGBITS
Flags: [ ]
Content: "0000"
DWARF:
debug_abbrev:
- Table:
- Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_producer
Form: DW_FORM_string
- Attribute: DW_AT_language
Form: DW_FORM_data2
- Attribute: DW_AT_name
Form: DW_FORM_string
- Attribute: DW_AT_low_pc
Form: DW_FORM_addr
- Attribute: DW_AT_high_pc
Form: DW_FORM_data8
debug_info:
- Version: 4
Entries:
- AbbrCode: 1
Values:
- CStr: by_hand
- Value: 0x04
- CStr: CU1
- Value: 0x1000
- Value: 0x4
- AbbrCode: 0
...
54 changes: 54 additions & 0 deletions llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-names.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## This test checks the warning message displayed if input file
## contains .debug_names section.

# RUN: yaml2obj %s -o %t.o

# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o

# CHECK: [[FILE]]: warning: '.debug_names' is not currently supported: section will be skipped

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x1000
AddressAlign: 0x0000000000000010
Content: "FFFFFFFF"
- Name: .debug_names
Type: SHT_PROGBITS
Flags: [ ]
Content: "0000"
DWARF:
debug_abbrev:
- Table:
- Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_producer
Form: DW_FORM_string
- Attribute: DW_AT_language
Form: DW_FORM_data2
- Attribute: DW_AT_name
Form: DW_FORM_string
- Attribute: DW_AT_low_pc
Form: DW_FORM_addr
- Attribute: DW_AT_high_pc
Form: DW_FORM_data8
debug_info:
- Version: 4
Entries:
- AbbrCode: 1
Values:
- CStr: by_hand
- Value: 0x04
- CStr: CU1
- Value: 0x1000
- Value: 0x4
- AbbrCode: 0
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## This test checks the warning message displayed if input file
## contains .debug_pubnames section.

# RUN: yaml2obj %s -o %t.o

# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o

# CHECK: [[FILE]]: warning: '.debug_pubnames' is not currently supported: section will be skipped

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x1000
AddressAlign: 0x0000000000000010
Content: "FFFFFFFF"
- Name: .debug_pubnames
Type: SHT_PROGBITS
Flags: [ ]
Content: "0000"
DWARF:
debug_abbrev:
- Table:
- Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_producer
Form: DW_FORM_string
- Attribute: DW_AT_language
Form: DW_FORM_data2
- Attribute: DW_AT_name
Form: DW_FORM_string
- Attribute: DW_AT_low_pc
Form: DW_FORM_addr
- Attribute: DW_AT_high_pc
Form: DW_FORM_data8
debug_info:
- Version: 4
Entries:
- AbbrCode: 1
Values:
- CStr: by_hand
- Value: 0x04
- CStr: CU1
- Value: 0x1000
- Value: 0x4
- AbbrCode: 0
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## This test checks the warning message displayed if input file
## contains .debug_pubtypes section.

# RUN: yaml2obj %s -o %t.o

# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o

# CHECK: [[FILE]]: warning: '.debug_pubtypes' is not currently supported: section will be skipped

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x1000
AddressAlign: 0x0000000000000010
Content: "FFFFFFFF"
- Name: .debug_pubtypes
Type: SHT_PROGBITS
Flags: [ ]
Content: "0000"
DWARF:
debug_abbrev:
- Table:
- Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_producer
Form: DW_FORM_string
- Attribute: DW_AT_language
Form: DW_FORM_data2
- Attribute: DW_AT_name
Form: DW_FORM_string
- Attribute: DW_AT_low_pc
Form: DW_FORM_addr
- Attribute: DW_AT_high_pc
Form: DW_FORM_data8
debug_info:
- Version: 4
Entries:
- AbbrCode: 1
Values:
- CStr: by_hand
- Value: 0x04
- CStr: CU1
- Value: 0x1000
- Value: 0x4
- AbbrCode: 0
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## This test checks the warning message displayed if input file
## contains .debug_rnglists section.

# RUN: yaml2obj %s -o %t.o

# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o

# CHECK: [[FILE]]: warning: '.debug_rnglists' is not currently supported: file will be skipped

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x1000
AddressAlign: 0x0000000000000010
Content: "FFFFFFFF"
- Name: .debug_rnglists
Type: SHT_PROGBITS
Flags: [ ]
Content: "0000"
DWARF:
debug_abbrev:
- Table:
- Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_producer
Form: DW_FORM_string
- Attribute: DW_AT_language
Form: DW_FORM_data2
- Attribute: DW_AT_name
Form: DW_FORM_string
- Attribute: DW_AT_low_pc
Form: DW_FORM_addr
- Attribute: DW_AT_high_pc
Form: DW_FORM_data8
debug_info:
- Version: 4
Entries:
- AbbrCode: 1
Values:
- CStr: by_hand
- Value: 0x04
- CStr: CU1
- Value: 0x1000
- Value: 0x4
- AbbrCode: 0
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## This test checks the warning message displayed if input file
## contains type units.

# RUN: llvm-dwarfutil --garbage-collection --tombstone=maxpc %p/Inputs/type-units.o %t1 2>&1 | FileCheck %s -DFILE=%p/Inputs/type-units.o

# CHECK: [[FILE]]: warning: type units are not currently supported: file will be skipped
3 changes: 2 additions & 1 deletion llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,8 @@ bool DwarfLinkerForBinary::link(const DebugMap &Map) {
}

// link debug info for loaded object files.
GeneralLinker.link();
if (Error E = GeneralLinker.link())
return error(toString(std::move(E)));

StringRef ArchName = Map.getTriple().getArchName();
if (Error E = emitRemarks(Options, Map.getBinaryPath(), ArchName, RL))
Expand Down
49 changes: 43 additions & 6 deletions llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "DebugInfoLinker.h"
#include "Error.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/DWARFLinker/DWARFLinker.h"
#include "llvm/DWARFLinker/DWARFStreamer.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
Expand Down Expand Up @@ -210,8 +211,29 @@ class ObjFileAddressMap : public AddressesMap {
const Options &Opts;
};

bool linkDebugInfo(object::ObjectFile &File, const Options &Options,
raw_pwrite_stream &OutStream) {
static bool knownByDWARFUtil(StringRef SecName) {
return llvm::StringSwitch<bool>(SecName)
.Case(".debug_info", true)
.Case(".debug_types", true)
.Case(".debug_abbrev", true)
.Case(".debug_loc", true)
.Case(".debug_loclists", true)
.Case(".debug_frame", true)
.Case(".debug_aranges", true)
.Case(".debug_ranges", true)
.Case(".debug_rnglists", true)
.Case(".debug_line", true)
.Case(".debug_line_str", true)
.Case(".debug_addr", true)
.Case(".debug_macro", true)
.Case(".debug_macinfo", true)
.Case(".debug_str", true)
.Case(".debug_str_offsets", true)
.Default(false);
}

Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
raw_pwrite_stream &OutStream) {

auto ReportWarn = [&](const Twine &Message, StringRef Context,
const DWARFDie *Die) {
Expand All @@ -235,8 +257,11 @@ bool linkDebugInfo(object::ObjectFile &File, const Options &Options,
// Create output streamer.
DwarfStreamer OutStreamer(OutputFileType::Object, OutStream, nullptr,
ReportWarn, ReportWarn);
if (!OutStreamer.init(File.makeTriple(), ""))
return false;
Triple TargetTriple = File.makeTriple();
if (!OutStreamer.init(TargetTriple, formatv("cannot create a stream for {0}",
TargetTriple.getTriple())
.str()))
return createStringError(std::errc::invalid_argument, "");

// Create DWARF linker.
DWARFLinker DebugInfoLinker(&OutStreamer, DwarfLinkerClient::LLD);
Expand All @@ -256,6 +281,16 @@ bool linkDebugInfo(object::ObjectFile &File, const Options &Options,

std::unique_ptr<DWARFContext> Context = DWARFContext::create(File);

// Unknown debug sections would be removed. Display warning
// for such sections.
for (SectionName Sec : Context->getDWARFObj().getSectionNames()) {
if (isDebugSection(Sec.Name) && !knownByDWARFUtil(Sec.Name))
warning(
formatv("'{0}' is not currently supported: section will be skipped",
Sec.Name),
Options.InputFileName);
}

// Add object files to the DWARFLinker.
AddresssMapForLinking[0] =
std::make_unique<ObjFileAddressMap>(*Context, Options, File);
Expand All @@ -268,9 +303,11 @@ bool linkDebugInfo(object::ObjectFile &File, const Options &Options,
DebugInfoLinker.addObjectFile(*ObjectsForLinking[I]);

// Link debug info.
DebugInfoLinker.link();
if (Error Err = DebugInfoLinker.link())
return Err;

OutStreamer.finish();
return true;
return Error::success();
}

} // end of namespace dwarfutil
Expand Down
4 changes: 2 additions & 2 deletions llvm/tools/llvm-dwarfutil/DebugInfoLinker.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ inline bool isDebugSection(StringRef SecName) {
SecName == ".gdb_index";
}

bool linkDebugInfo(object::ObjectFile &file, const Options &Options,
raw_pwrite_stream &OutStream);
Error linkDebugInfo(object::ObjectFile &file, const Options &Options,
raw_pwrite_stream &OutStream);

} // end of namespace dwarfutil
} // end of namespace llvm
Expand Down
14 changes: 6 additions & 8 deletions llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,16 +426,14 @@ static Error applyCLOptions(const struct Options &Opts, ObjectFile &InputFile) {
DebugInfoBits LinkedDebugInfo;
raw_svector_ostream OutStream(LinkedDebugInfo);

if (linkDebugInfo(InputFile, Opts, OutStream)) {
if (Error Err =
saveLinkedDebugInfo(Opts, InputFile, std::move(LinkedDebugInfo)))
return Err;
if (Error Err = linkDebugInfo(InputFile, Opts, OutStream))
return Err;

return Error::success();
}
if (Error Err =
saveLinkedDebugInfo(Opts, InputFile, std::move(LinkedDebugInfo)))
return Err;

return createStringError(std::errc::invalid_argument,
"possible broken debug info");
return Error::success();
} else if (Opts.BuildSeparateDebugFile) {
if (Error Err = splitDebugIntoSeparateFile(Opts, InputFile))
return Err;
Expand Down