@@ -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