Skip to content

Commit 78be6b2

Browse files
authored
llvm-gsymutil now handles empty linkage names correctly. (llvm#68931)
Previous to this fix, if we had a DW_TAG_subprogram that had a DW_AT_linkage_name that was empty, it would attempt to use this name which would cause an error to be emitted when saving the gsym file to disk: error: DWARF conversion failed: : attempted to encode invalid FunctionInfo object This patch fixes this issue and adds a unit test case.
1 parent 910a4bf commit 78be6b2

File tree

2 files changed

+157
-5
lines changed

2 files changed

+157
-5
lines changed

llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,11 @@ static DWARFDie GetParentDeclContextDIE(DWARFDie &Die) {
132132
static std::optional<uint32_t>
133133
getQualifiedNameIndex(DWARFDie &Die, uint64_t Language, GsymCreator &Gsym) {
134134
// If the dwarf has mangled name, use mangled name
135-
if (auto LinkageName =
136-
dwarf::toString(Die.findRecursively({dwarf::DW_AT_MIPS_linkage_name,
137-
dwarf::DW_AT_linkage_name}),
138-
nullptr))
139-
return Gsym.insertString(LinkageName, /* Copy */ false);
135+
if (auto LinkageName = Die.getLinkageName()) {
136+
// We have seen cases were linkage name is actually empty.
137+
if (strlen(LinkageName) > 0)
138+
return Gsym.insertString(LinkageName, /* Copy */ false);
139+
}
140140

141141
StringRef ShortName(Die.getName(DINameKind::ShortName));
142142
if (ShortName.empty())

llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4005,3 +4005,155 @@ TEST(GSYMTest, TestEmptyRangeWarnings) {
40054005
// Make sure we don't see spurious errors in the output:
40064006
EXPECT_TRUE(errors.find("error:") == std::string::npos);
40074007
}
4008+
4009+
4010+
TEST(GSYMTest, TestEmptyLinkageName) {
4011+
// This example has a single compile unit that has a DW_TAG_subprogram that
4012+
// has a function that has an empty linkage name and a valid normal name.
4013+
// Previously this would cause an encoding error:
4014+
//
4015+
// DWARF conversion failed: attempted to encode invalid FunctionInfo object
4016+
//
4017+
// This was because we would get a valid but empty linkage name and we would
4018+
// try to use this in the GSYM FunctionInfo and that would cause the error
4019+
// as the name was empty.
4020+
//
4021+
// 0x0000000b: DW_TAG_compile_unit
4022+
// DW_AT_name ("/tmp/main.cpp")
4023+
// DW_AT_language (DW_LANG_C)
4024+
// DW_AT_stmt_list (0x00000000)
4025+
//
4026+
// 0x00000015: DW_TAG_subprogram
4027+
// DW_AT_name ("foo")
4028+
// DW_AT_linkage_name ("")
4029+
// DW_AT_low_pc (0x0000000000001000)
4030+
// DW_AT_high_pc (0x0000000000001050)
4031+
//
4032+
// 0x0000002e: NULL
4033+
4034+
4035+
StringRef yamldata = R"(
4036+
debug_str:
4037+
- ''
4038+
- '/tmp/main.cpp'
4039+
- foo
4040+
- ''
4041+
debug_abbrev:
4042+
- ID: 0
4043+
Table:
4044+
- Code: 0x1
4045+
Tag: DW_TAG_compile_unit
4046+
Children: DW_CHILDREN_yes
4047+
Attributes:
4048+
- Attribute: DW_AT_name
4049+
Form: DW_FORM_strp
4050+
- Attribute: DW_AT_language
4051+
Form: DW_FORM_udata
4052+
- Attribute: DW_AT_stmt_list
4053+
Form: DW_FORM_sec_offset
4054+
- Code: 0x2
4055+
Tag: DW_TAG_subprogram
4056+
Children: DW_CHILDREN_no
4057+
Attributes:
4058+
- Attribute: DW_AT_name
4059+
Form: DW_FORM_strp
4060+
- Attribute: DW_AT_linkage_name
4061+
Form: DW_FORM_strp
4062+
- Attribute: DW_AT_low_pc
4063+
Form: DW_FORM_addr
4064+
- Attribute: DW_AT_high_pc
4065+
Form: DW_FORM_addr
4066+
debug_info:
4067+
- Length: 0x2B
4068+
Version: 4
4069+
AbbrevTableID: 0
4070+
AbbrOffset: 0x0
4071+
AddrSize: 8
4072+
Entries:
4073+
- AbbrCode: 0x1
4074+
Values:
4075+
- Value: 0x1
4076+
- Value: 0x2
4077+
- Value: 0x0
4078+
- AbbrCode: 0x2
4079+
Values:
4080+
- Value: 0xF
4081+
- Value: 0x13
4082+
- Value: 0x1000
4083+
- Value: 0x1050
4084+
- AbbrCode: 0x0
4085+
debug_line:
4086+
- Length: 68
4087+
Version: 2
4088+
PrologueLength: 36
4089+
MinInstLength: 1
4090+
DefaultIsStmt: 1
4091+
LineBase: 251
4092+
LineRange: 14
4093+
OpcodeBase: 13
4094+
StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
4095+
IncludeDirs:
4096+
- '/tmp'
4097+
Files:
4098+
- Name: main.cpp
4099+
DirIdx: 1
4100+
ModTime: 0
4101+
Length: 0
4102+
Opcodes:
4103+
- Opcode: DW_LNS_extended_op
4104+
ExtLen: 9
4105+
SubOpcode: DW_LNE_set_address
4106+
Data: 4096
4107+
- Opcode: DW_LNS_advance_line
4108+
SData: 9
4109+
Data: 0
4110+
- Opcode: DW_LNS_copy
4111+
Data: 0
4112+
- Opcode: DW_LNS_advance_pc
4113+
Data: 256
4114+
- Opcode: DW_LNS_advance_line
4115+
SData: 1
4116+
Data: 0
4117+
- Opcode: DW_LNS_copy
4118+
Data: 0
4119+
- Opcode: DW_LNS_advance_pc
4120+
Data: 256
4121+
- Opcode: DW_LNS_extended_op
4122+
ExtLen: 1
4123+
SubOpcode: DW_LNE_end_sequence
4124+
Data: 0
4125+
)";
4126+
auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
4127+
ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
4128+
std::unique_ptr<DWARFContext> DwarfContext =
4129+
DWARFContext::create(*ErrOrSections, 8);
4130+
ASSERT_TRUE(DwarfContext.get() != nullptr);
4131+
std::string errors;
4132+
raw_string_ostream OS(errors);
4133+
GsymCreator GC;
4134+
DwarfTransformer DT(*DwarfContext, GC);
4135+
const uint32_t ThreadCount = 1;
4136+
ASSERT_THAT_ERROR(DT.convert(ThreadCount, &OS), Succeeded());
4137+
ASSERT_THAT_ERROR(GC.finalize(OS), Succeeded());
4138+
OS.flush();
4139+
SmallString<512> Str;
4140+
raw_svector_ostream OutStrm(Str);
4141+
const auto ByteOrder = llvm::endianness::native;
4142+
FileWriter FW(OutStrm, ByteOrder);
4143+
ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
4144+
Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
4145+
ASSERT_THAT_EXPECTED(GR, Succeeded());
4146+
// There should be one function in our GSYM.
4147+
EXPECT_EQ(GR->getNumAddresses(), 1u);
4148+
// Verify "foo" is present and has a line table and no inline info.
4149+
auto ExpFI = GR->getFunctionInfo(0x1000);
4150+
ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
4151+
ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));
4152+
EXPECT_TRUE(ExpFI->OptLineTable.has_value());
4153+
EXPECT_FALSE(ExpFI->Inline.has_value());
4154+
StringRef FuncName = GR->getString(ExpFI->Name);
4155+
EXPECT_EQ(FuncName, "foo");
4156+
4157+
// Make sure we don't see spurious errors in the output:
4158+
EXPECT_TRUE(errors.find("error:") == std::string::npos);
4159+
}

0 commit comments

Comments
 (0)