diff --git a/llvm/tools/objwriter/debugInfo/dwarf/dwarfAbbrev.cpp b/llvm/tools/objwriter/debugInfo/dwarf/dwarfAbbrev.cpp index 362d5df76017bd..200431a34cdef6 100644 --- a/llvm/tools/objwriter/debugInfo/dwarf/dwarfAbbrev.cpp +++ b/llvm/tools/objwriter/debugInfo/dwarf/dwarfAbbrev.cpp @@ -38,6 +38,10 @@ void Dump(MCObjectStreamer *Streamer, uint16_t DwarfVersion, unsigned TargetPoin dwarf::DW_TAG_compile_unit, dwarf::DW_CHILDREN_yes, dwarf::DW_AT_producer, dwarf::DW_FORM_string, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + dwarf::DW_AT_name, dwarf::DW_FORM_string, + dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, + dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + dwarf::DW_AT_high_pc, DW_FORM_size, dwarf::DW_AT_stmt_list, (DwarfVersion >= 4 ? dwarf::DW_FORM_sec_offset : dwarf::DW_FORM_data4), 0, 0, @@ -125,6 +129,17 @@ void Dump(MCObjectStreamer *Streamer, uint16_t DwarfVersion, unsigned TargetPoin dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, 0, 0, + SubprogramStaticNoChildrenSpec, + dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, + dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, + dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, + 0, 0, + Variable, dwarf::DW_TAG_variable, dwarf::DW_CHILDREN_no, dwarf::DW_AT_name, dwarf::DW_FORM_strp, diff --git a/llvm/tools/objwriter/debugInfo/dwarf/dwarfAbbrev.h b/llvm/tools/objwriter/debugInfo/dwarf/dwarfAbbrev.h index 3cd8cea23772cc..1a79930824c150 100644 --- a/llvm/tools/objwriter/debugInfo/dwarf/dwarfAbbrev.h +++ b/llvm/tools/objwriter/debugInfo/dwarf/dwarfAbbrev.h @@ -30,6 +30,7 @@ enum DwarfAbbrev : uint16_t SubprogramStatic, SubprogramSpec, SubprogramStaticSpec, + SubprogramStaticNoChildrenSpec, Variable, VariableLoc, VariableStatic, diff --git a/llvm/tools/objwriter/debugInfo/dwarf/dwarfGen.cpp b/llvm/tools/objwriter/debugInfo/dwarf/dwarfGen.cpp index b2ad3f4bd3d565..555bb2ccb8a43e 100644 --- a/llvm/tools/objwriter/debugInfo/dwarf/dwarfGen.cpp +++ b/llvm/tools/objwriter/debugInfo/dwarf/dwarfGen.cpp @@ -816,7 +816,7 @@ void SubprogramInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTy EmitInfoOffset(Streamer, MethodTypeInfo, 4); // DW_AT_low_pc - MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name)); + MCSymbol *Sym = context.lookupSymbol(Twine(Name)); const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context); Streamer->emitValue(SymExpr, TargetPointerSize); @@ -907,6 +907,7 @@ void DwarfGen::SetTypeBuilder(UserDefinedDwarfTypesBuilder *TypeBuilder) { void DwarfGen::EmitCompileUnit() { MCContext &context = Streamer->getContext(); + unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize(); MCSymbol *LineSectionSymbol = nullptr; MCSymbol *AbbrevSectionSymbol = nullptr; @@ -966,6 +967,31 @@ void DwarfGen::EmitCompileUnit() { Streamer->emitIntValue(dwarf::DW_LANG_C_plus_plus, 2); #endif + // We need to generate DW_AT_name and DW_AT_compdir to get Apple's ld64 to correctly + // generate debug map in final executable. If we don't generate it then the linker + // will skip over the object file. + // Ref: https://github.com/apple-oss-distributions/ld64/blob/dbf8f7feb5579761f1623b004bd468bdea7c6225/src/ld/OutputFile.cpp#L7166 + + // DW_AT_name + Streamer->emitBytes(StringRef("IL.c")); + Streamer->emitIntValue(0, 1); + + // DW_AT_compdir + Streamer->emitBytes(StringRef("/tmp")); + Streamer->emitIntValue(0, 1); + + // There need to be global DW_AT_low_pc/DW_AT_high_pc symbols to indicate the base and + // size of the range covered by the symbols. Currently we use a shortcut where we emit + // a range starting at the beginning of file and ending at the start of the debug section + // which is located at the end of the object file. + + // DW_AT_low_pc + Streamer->emitIntValue(0, TargetPointerSize); + + // DW_AT_high_pc + const MCExpr *SymExpr = MCSymbolRefExpr::create(debugSection->getBeginSymbol(), MCSymbolRefExpr::VK_None, context); + Streamer->emitValue(SymExpr, TargetPointerSize); + // DW_AT_stmt_list if (LineSectionSymbol == nullptr) { Streamer->emitIntValue(0, 4); diff --git a/llvm/tools/objwriter/debugInfo/dwarf/dwarfTypeBuilder.cpp b/llvm/tools/objwriter/debugInfo/dwarf/dwarfTypeBuilder.cpp index 6d663e05128844..f124d239a06f5b 100644 --- a/llvm/tools/objwriter/debugInfo/dwarf/dwarfTypeBuilder.cpp +++ b/llvm/tools/objwriter/debugInfo/dwarf/dwarfTypeBuilder.cpp @@ -601,8 +601,12 @@ void DwarfMemberFunctionIdTypeInfo::DumpStrings(MCObjectStreamer *Streamer) { void DwarfMemberFunctionIdTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { // Abbrev Number bool IsStatic = MemberFunctionTypeInfo->IsStatic(); + bool HasParameters = MemberFunctionTypeInfo->GetArgTypes().size(); - Streamer->emitULEB128IntValue(IsStatic ? DwarfAbbrev::SubprogramStaticSpec : DwarfAbbrev::SubprogramSpec); + Streamer->emitULEB128IntValue( + IsStatic ? (HasParameters ? DwarfAbbrev::SubprogramStaticSpec + : DwarfAbbrev::SubprogramStaticNoChildrenSpec) + : DwarfAbbrev::SubprogramSpec); // DW_AT_name EmitSectionOffset(Streamer, StrSymbol, 4); @@ -652,8 +656,10 @@ void DwarfMemberFunctionIdTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, Use EmitInfoOffset(Streamer, ArgTypeInfo, 4); } - // Ternimate DIE - Streamer->emitIntValue(0, 1); + // Terminate DIE (skip for SubprogramStaticNoChildrenSpec which has no children) + if (!IsStatic || HasParameters) { + Streamer->emitIntValue(0, 1); + } } // DwarfTypesBuilder diff --git a/llvm/tools/objwriter/objwriter.cpp b/llvm/tools/objwriter/objwriter.cpp index 3fe42df9b7a3bc..f4906580786e8f 100644 --- a/llvm/tools/objwriter/objwriter.cpp +++ b/llvm/tools/objwriter/objwriter.cpp @@ -152,10 +152,8 @@ bool ObjectWriter::Init(llvm::StringRef ObjectFilePath, const char* tripleName) unsigned TargetPointerSize = Streamer->getContext().getAsmInfo()->getCodePointerSize(); TypeBuilder->SetTargetPointerSize(TargetPointerSize); - if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsELF) { - DwarfGenerator.reset(new DwarfGen()); - DwarfGenerator->SetTypeBuilder(static_cast(TypeBuilder.get())); - } + DwarfGenerator.reset(new DwarfGen()); + DwarfGenerator->SetTypeBuilder(static_cast(TypeBuilder.get())); CFIsPerOffset.set_size(0); @@ -256,6 +254,12 @@ MCSection *ObjectWriter::GetSpecificSection(const char *SectionName, if (attributes & CustomSectionAttributes_MachO_Init_Func_Pointers) { typeAndAttributes |= MachO::SectionType::S_MOD_INIT_FUNC_POINTERS; } + if (attributes & CustomSectionAttributes_Executable) { + // Needs to be set on sections with actual code. The linker uses + // it to determine code sections and emit information about function + // boundaries. + typeAndAttributes |= MachO::S_ATTR_PURE_INSTRUCTIONS; + } Section = OutContext->getMachOSection( (attributes & CustomSectionAttributes_Executable) ? "__TEXT" : "__DATA", SectionName, typeAndAttributes, Kind); @@ -882,9 +886,8 @@ void ObjectWriter::EmitDebugFunctionInfo(const char *FunctionName, Streamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction); Streamer->emitELFSize(Sym, MCConstantExpr::create(FunctionSize, *OutContext)); - EmitDwarfFunctionInfo(FunctionName, FunctionSize, MethodTypeIndex); } - // TODO: Should test it for Macho. + EmitDwarfFunctionInfo(FunctionName, FunctionSize, MethodTypeIndex); } } @@ -963,12 +966,10 @@ void ObjectWriter::EmitDebugModuleInfo() { Streamer->SwitchSection(Section); Streamer->emitCVFileChecksumsDirective(); Streamer->emitCVStringTableDirective(); - } else if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsELF) { + } else { DwarfGenerator->EmitAbbrev(); DwarfGenerator->EmitAranges(); DwarfGenerator->Finish(); - } else { - OutContext->setGenDwarfForAssembly(true); } }