[llvm] cb5a20e - [dsymutil] Fix ODR type uniquing for -gsimple-template-names (#194501) (#195174)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 30 16:07:29 PDT 2026
Author: Jonas Devlieghere
Date: 2026-04-30T23:07:24Z
New Revision: cb5a20e4c6f63ffca1906661e36f34bd2edcde67
URL: https://github.com/llvm/llvm-project/commit/cb5a20e4c6f63ffca1906661e36f34bd2edcde67
DIFF: https://github.com/llvm/llvm-project/commit/cb5a20e4c6f63ffca1906661e36f34bd2edcde67.diff
LOG: [dsymutil] Fix ODR type uniquing for -gsimple-template-names (#194501) (#195174)
With -gsimple-template-names (now the default on macOS with deployment
target >= 26), template types like vector<int> and vector<float> both
get DW_AT_name("vector") in DWARF, with template parameters encoded only
as DW_TAG_template_type_parameter children.
Previously, dsymutil used only DW_AT_name for ODR type uniquing, causing
different template specializations to collide. This PR fixes that by
reconstructing template parameter information from child DIEs when the
type name does not already contain template parameters.
The reconstructed name is used only for uniquing and not emitted into
the output DWARF. The parallel DWARF linker already handled this
correctly via SyntheticTypeNameBuilder.
This reland removes an overly strict assertion when clang emits
DW_TAG_subprogram DIEs with a demangled template-like DW_AT_name (e.g.
foo<int>) but no DW_AT_linkage_name. The surrounding logic already
handles this case correctly — it sees the name already contains template
parameters and uses it as-is for uniquing — so the assertion was simply
wrong. Added a regression test covering both the classic and parallel
linkers.
rdar://175115639
Added:
llvm/test/tools/dsymutil/X86/odr-simple-template-names-mixed.test
llvm/test/tools/dsymutil/X86/odr-simple-template-names.test
llvm/test/tools/dsymutil/X86/odr-subprogram-template-name-no-linkage.test
Modified:
llvm/lib/DWARFLinker/Classic/DWARFLinkerDeclContext.cpp
Removed:
################################################################################
diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinkerDeclContext.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinkerDeclContext.cpp
index 66a1ba9c6711f..8aa3a4cbc63c4 100644
--- a/llvm/lib/DWARFLinker/Classic/DWARFLinkerDeclContext.cpp
+++ b/llvm/lib/DWARFLinker/Classic/DWARFLinkerDeclContext.cpp
@@ -10,10 +10,23 @@
#include "llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/raw_ostream.h"
namespace llvm {
+static std::optional<std::string>
+makeSimpleTemplateNameWithParams(StringRef Name, const DWARFDie &DIE) {
+ std::string Result = Name.str();
+ raw_string_ostream OS(Result);
+ DWARFTypePrinter<DWARFDie> Printer(OS);
+ Printer.appendAndTerminateTemplateParameters(DIE);
+ if (Result == Name)
+ return std::nullopt;
+ return Result;
+}
+
using namespace dwarf_linker;
using namespace dwarf_linker::classic;
@@ -88,10 +101,20 @@ DeclContextTree::getChildDeclContext(DeclContext &Context, const DWARFDie &DIE,
StringRef NameForUniquing;
StringRef FileRef;
- if (const char *LinkageName = DIE.getLinkageName())
+ if (const char *LinkageName = DIE.getLinkageName()) {
NameForUniquing = StringPool.internString(LinkageName);
- else if (!Name.empty())
- NameForUniquing = StringPool.internString(Name);
+ } else if (!Name.empty()) {
+ // With -gsimple-template-names, DW_AT_name omits template parameters
+ // ("vector" instead of "vector<int>"). Reconstruct them from child
+ // DW_TAG_template_*_parameter DIEs so
diff erent specializations get
+ // distinct uniquing names.
+ bool HasTemplateParamsInName =
+ Name.ends_with(">") && !Name.ends_with("<=>") && Name.contains('<');
+ std::optional<std::string> FullName;
+ if (!HasTemplateParamsInName)
+ FullName = makeSimpleTemplateNameWithParams(Name, DIE);
+ NameForUniquing = StringPool.internString(FullName ? *FullName : Name);
+ }
bool IsAnonymousNamespace =
NameForUniquing.empty() && Tag == dwarf::DW_TAG_namespace;
diff --git a/llvm/test/tools/dsymutil/X86/odr-simple-template-names-mixed.test b/llvm/test/tools/dsymutil/X86/odr-simple-template-names-mixed.test
new file mode 100644
index 0000000000000..766d90fdedfb2
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/odr-simple-template-names-mixed.test
@@ -0,0 +1,348 @@
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '---' > %t2.map
+# RUN: echo "triple: 'x86_64-apple-darwin'" >> %t2.map
+# RUN: echo 'objects:' >> %t2.map
+# RUN: echo " - filename: '%t.o'" >> %t2.map
+# RUN: echo ' symbols:' >> %t2.map
+# RUN: echo ' - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }' >> %t2.map
+# RUN: echo '...' >> %t2.map
+# RUN: dsymutil -f -y %t2.map -o - | llvm-dwarfdump --debug-info - | FileCheck %s
+# RUN: dsymutil --linker parallel -f -y %t2.map -o - | llvm-dwarfdump --debug-info - | FileCheck --check-prefix=PARALLEL %s
+
+## Test that dsymutil correctly resolves simple template names to types that use
+## non-simple (fully qualified) template names. This simulates a situation where
+## part of the program is compiled without -gsimple-template-names linking with
+## code that does.
+##
+## CU1: defines MyTemplate<int> and MyTemplate<float> with full
+## names in DW_AT_name.
+##
+## CU2: defines MyTemplate<float> using a simple template name
+## ("MyTemplate") with DW_TAG_template_type_parameter children.
+
+# CHECK: .debug_info contents:
+# CHECK: DW_TAG_compile_unit
+# CHECK-NOT: DW_TAG
+# CHECK: DW_AT_name{{.*}}"CU1"
+# CHECK: 0x[[TMPL_INT:[0-9a-f]*]]: DW_TAG_class_type
+# CHECK-NEXT: DW_AT_name{{.*}}"MyTemplate<int>"
+# CHECK: 0x[[TMPL_FLOAT:[0-9a-f]*]]: DW_TAG_class_type
+# CHECK-NEXT: DW_AT_name{{.*}}"MyTemplate<float>"
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var1"
+# CHECK: DW_AT_type{{.*}}0x00000000[[TMPL_INT]] "MyTemplate<int>"
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var2"
+# CHECK: DW_AT_type{{.*}}0x00000000[[TMPL_FLOAT]] "MyTemplate<float>"
+# CHECK: DW_TAG_compile_unit
+# CHECK-NOT: DW_TAG
+# CHECK: DW_AT_name{{.*}}"CU2"
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var3"
+# CHECK: DW_AT_type{{.*}}0x00000000[[TMPL_FLOAT]] "MyTemplate<float>"
+
+## Parallel linker: types go to artificial type CU. The parallel linker does
+## not currently unify across simple/non-simple template name representations.
+# PARALLEL: .debug_info contents:
+# PARALLEL: DW_TAG_compile_unit
+# PARALLEL: DW_AT_name{{.*}}"__artificial_type_unit"
+# PARALLEL: 0x[[TMPL_FLOAT_S:[0-9a-f]*]]: DW_TAG_class_type
+# PARALLEL: DW_AT_name{{.*}}"MyTemplate"
+# PARALLEL: DW_TAG_template_type_parameter
+# PARALLEL: DW_AT_type{{.*}}"float"
+# PARALLEL: 0x[[TMPL_FLOAT_F:[0-9a-f]*]]: DW_TAG_class_type
+# PARALLEL: DW_AT_name{{.*}}"MyTemplate<float>"
+# PARALLEL: 0x[[TMPL_INT:[0-9a-f]*]]: DW_TAG_class_type
+# PARALLEL: DW_AT_name{{.*}}"MyTemplate<int>"
+# PARALLEL: DW_TAG_compile_unit
+# PARALLEL: DW_AT_name{{.*}}"CU1"
+# PARALLEL: DW_TAG_variable
+# PARALLEL: DW_AT_name{{.*}}"var1"
+# PARALLEL: DW_AT_type{{.*}}0x00000000[[TMPL_INT]]
+# PARALLEL: DW_TAG_variable
+# PARALLEL: DW_AT_name{{.*}}"var2"
+# PARALLEL: DW_AT_type{{.*}}0x00000000[[TMPL_FLOAT_F]]
+# PARALLEL: DW_TAG_compile_unit
+# PARALLEL: DW_AT_name{{.*}}"CU2"
+# PARALLEL: DW_TAG_variable
+# PARALLEL: DW_AT_name{{.*}}"var3"
+# PARALLEL: DW_AT_type{{.*}}0x00000000[[TMPL_FLOAT_S]]
+
+## ---- Mach-O + DWARF definition ----
+##
+## CU1 debug_info layout (old compiler, no simple template names):
+## 0x00: CU header (11 bytes)
+## 0x0b: DW_TAG_compile_unit
+## 0x1a: DW_TAG_class_type "MyTemplate<int>" (no children)
+## 0x2c: DW_TAG_class_type "MyTemplate<float>" (no children)
+## 0x40: DW_TAG_base_type "int"
+## 0x45: DW_TAG_base_type "float"
+## 0x4c: DW_TAG_subprogram "foo" (low_pc at section offset 0x51)
+## 0x5d: DW_TAG_variable "var1" (type -> 0x1a)
+## 0x6b: DW_TAG_variable "var2" (type -> 0x2c)
+## 0x7b: end CU1
+##
+## CU2 debug_info layout (new compiler, simple template names):
+## 0x7b: CU header (11 bytes)
+## 0x86: DW_TAG_compile_unit
+## 0x95: DW_TAG_class_type "MyTemplate" (children: template param T -> float)
+## 0xa2: DW_TAG_template_type_parameter (type -> 0xaf)
+## 0xaa: DW_TAG_base_type "int"
+## 0xaf: DW_TAG_base_type "float"
+## 0xb6: DW_TAG_subprogram "foo" (low_pc at section offset 0xbb)
+## 0xc7: DW_TAG_variable "var3" (type -> 0x95)
+## 0xd7: end CU2
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 2
+ sizeofcmds: 376
+ flags: 0x00002000
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 232
+ segname: ''
+ vmaddr: 0x00
+ vmsize: 0x300
+ fileoff: 0x300
+ filesize: 0x300
+ maxprot: 7
+ initprot: 7
+ nsects: 2
+ flags: 0
+ Sections:
+ - sectname: __debug_abbrev
+ segname: __DWARF
+ addr: 0x000000000000000F
+ size: 0x6d
+ offset: 0x00000380
+ align: 0
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x02000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __debug_info
+ segname: __DWARF
+ addr: 0x000000000000100
+ size: 0xD7
+ offset: 0x000003ED
+ align: 0
+ reloff: 0x00000600
+ nreloc: 2
+ flags: 0x02000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ relocations:
+ - address: 0x51
+ symbolnum: 0
+ pcrel: false
+ length: 3
+ extern: true
+ type: 0
+ scattered: false
+ value: 0
+ - address: 0xBB
+ symbolnum: 0
+ pcrel: false
+ length: 3
+ extern: true
+ type: 0
+ scattered: false
+ value: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 0x700
+ nsyms: 1
+ stroff: 0x710
+ strsize: 10
+LinkEditData:
+ NameList:
+ - n_strx: 1
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 0
+ StringTable:
+ - ''
+ - '__Z3foov'
+ - ''
+DWARF:
+ debug_abbrev:
+ - Table:
+ ## CU1 abbreviations (old compiler, no template parameter children)
+ - 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
+ - Tag: DW_TAG_class_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_byte_size
+ Form: DW_FORM_data1
+ - Tag: DW_TAG_base_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - 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_data4
+ - Tag: DW_TAG_variable
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_const_value
+ Form: DW_FORM_data4
+ - Attribute: DW_AT_type
+ Form: DW_FORM_ref_addr
+ - Table:
+ ## CU2 abbreviations (new compiler, simple template names)
+ - 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
+ - Tag: DW_TAG_class_type
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_byte_size
+ Form: DW_FORM_data1
+ - Tag: DW_TAG_template_type_parameter
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_type
+ Form: DW_FORM_ref_addr
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Tag: DW_TAG_base_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - 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_data4
+ - Tag: DW_TAG_variable
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_const_value
+ Form: DW_FORM_data4
+ - Attribute: DW_AT_type
+ Form: DW_FORM_ref_addr
+ debug_info:
+ - Version: 4
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - Value: 0x04
+ - CStr: CU1
+ ## 0x1a: MyTemplate<int> (full name, no children)
+ - AbbrCode: 2
+ Values:
+ - CStr: "MyTemplate<int>"
+ - Value: 0x04
+ ## 0x2c: MyTemplate<float> (full name, no children)
+ - AbbrCode: 2
+ Values:
+ - CStr: "MyTemplate<float>"
+ - Value: 0x04
+ ## 0x40: base types
+ - AbbrCode: 3
+ Values:
+ - CStr: int
+ - AbbrCode: 3
+ Values:
+ - CStr: float
+ ## 0x4c: subprogram (low_pc at section offset 0x51)
+ - AbbrCode: 4
+ Values:
+ - CStr: foo
+ - Value: 0x0000000000000000
+ - Value: 0x00000010
+ - AbbrCode: 5
+ Values:
+ - CStr: var1
+ - Value: 0x00000000
+ - Value: 0x0000001a
+ - AbbrCode: 5
+ Values:
+ - CStr: var2
+ - Value: 0x00000000
+ - Value: 0x0000002c
+ - AbbrCode: 0
+ - AbbrCode: 0
+ - Version: 4
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - Value: 0x04
+ - CStr: CU2
+ ## 0x95: MyTemplate<float> (simple template name)
+ - AbbrCode: 2
+ Values:
+ - CStr: MyTemplate
+ - Value: 0x04
+ - AbbrCode: 3
+ Values:
+ - Value: 0x000000af
+ - CStr: T
+ - AbbrCode: 0
+ ## base types
+ - AbbrCode: 4
+ Values:
+ - CStr: int
+ - AbbrCode: 4
+ Values:
+ - CStr: float
+ ## 0xb6: subprogram (low_pc at section offset 0xbb)
+ - AbbrCode: 5
+ Values:
+ - CStr: foo
+ - Value: 0x0000000000000000
+ - Value: 0x00000010
+ - AbbrCode: 6
+ Values:
+ - CStr: var3
+ - Value: 0x00000000
+ - Value: 0x00000095
+ - AbbrCode: 0
+ - AbbrCode: 0
+...
diff --git a/llvm/test/tools/dsymutil/X86/odr-simple-template-names.test b/llvm/test/tools/dsymutil/X86/odr-simple-template-names.test
new file mode 100644
index 0000000000000..f37c076fd2905
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/odr-simple-template-names.test
@@ -0,0 +1,369 @@
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '---' > %t2.map
+# RUN: echo "triple: 'x86_64-apple-darwin'" >> %t2.map
+# RUN: echo 'objects:' >> %t2.map
+# RUN: echo " - filename: '%t.o'" >> %t2.map
+# RUN: echo ' symbols:' >> %t2.map
+# RUN: echo ' - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }' >> %t2.map
+# RUN: echo '...' >> %t2.map
+# RUN: dsymutil -f -y %t2.map -o - | llvm-dwarfdump --debug-info - | FileCheck %s
+# RUN: dsymutil --linker parallel -f -y %t2.map -o - | llvm-dwarfdump --debug-info - | FileCheck --check-prefix=PARALLEL %s
+
+## Test that dsymutil correctly handles -gsimple-template-names, where
+## DW_AT_name does not include template parameters and template arguments are
+## represented as DW_TAG_template_type_parameter children instead.
+##
+## CU1 defines MyTemplate<int> and MyTemplate<float> (both named "MyTemplate").
+## CU2 defines MyTemplate<float> (also named "MyTemplate").
+##
+## dsymutil must not incorrectly unify MyTemplate<int> with MyTemplate<float>.
+## CU2's MyTemplate<float> should unify with CU1's MyTemplate<float>.
+
+## Classic linker: CU1 keeps both specializations. CU2's type reference is
+## redirected to CU1's MyTemplate<float>.
+##
+## Type references use 0x00000000[[VAR]] to match DWARF32 ref_addr (8 hex digit
+## DIE offset zero-extended to 16 hex digits for the 8-byte ref_addr).
+# CHECK: .debug_info contents:
+# CHECK: DW_TAG_compile_unit
+# CHECK-NOT: DW_TAG
+# CHECK: DW_AT_name{{.*}}"CU1"
+# CHECK: 0x[[TMPL_INT:[0-9a-f]*]]: DW_TAG_class_type
+# CHECK-NEXT: DW_AT_name{{.*}}"MyTemplate"
+# CHECK: DW_TAG_template_type_parameter
+# CHECK: DW_AT_type{{.*}}"int"
+# CHECK: 0x[[TMPL_FLOAT:[0-9a-f]*]]: DW_TAG_class_type
+# CHECK-NEXT: DW_AT_name{{.*}}"MyTemplate"
+# CHECK: DW_TAG_template_type_parameter
+# CHECK: DW_AT_type{{.*}}"float"
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var1"
+# CHECK: DW_AT_type{{.*}}0x00000000[[TMPL_INT]] "MyTemplate
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var2"
+# CHECK: DW_AT_type{{.*}}0x00000000[[TMPL_FLOAT]] "MyTemplate
+# CHECK: DW_TAG_compile_unit
+# CHECK-NOT: DW_TAG
+# CHECK: DW_AT_name{{.*}}"CU2"
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var3"
+# CHECK: DW_AT_type{{.*}}0x00000000[[TMPL_FLOAT]] "MyTemplate
+
+## Parallel linker: types go to artificial type CU with separate entries.
+# PARALLEL: .debug_info contents:
+# PARALLEL: DW_TAG_compile_unit
+# PARALLEL: DW_AT_name{{.*}}"__artificial_type_unit"
+# PARALLEL: 0x[[TMPL_FLOAT:[0-9a-f]*]]: DW_TAG_class_type
+# PARALLEL: DW_AT_name{{.*}}"MyTemplate"
+# PARALLEL: DW_TAG_template_type_parameter
+# PARALLEL: DW_AT_type{{.*}}"float"
+# PARALLEL: 0x[[TMPL_INT:[0-9a-f]*]]: DW_TAG_class_type
+# PARALLEL: DW_AT_name{{.*}}"MyTemplate"
+# PARALLEL: DW_TAG_template_type_parameter
+# PARALLEL: DW_AT_type{{.*}}"int"
+# PARALLEL: DW_TAG_compile_unit
+# PARALLEL: DW_AT_name{{.*}}"CU1"
+# PARALLEL: DW_TAG_variable
+# PARALLEL: DW_AT_name{{.*}}"var1"
+# PARALLEL: DW_AT_type{{.*}}0x00000000[[TMPL_INT]]
+# PARALLEL: DW_TAG_variable
+# PARALLEL: DW_AT_name{{.*}}"var2"
+# PARALLEL: DW_AT_type{{.*}}0x00000000[[TMPL_FLOAT]]
+# PARALLEL: DW_TAG_compile_unit
+# PARALLEL: DW_AT_name{{.*}}"CU2"
+# PARALLEL: DW_TAG_variable
+# PARALLEL: DW_AT_name{{.*}}"var3"
+# PARALLEL: DW_AT_type{{.*}}0x00000000[[TMPL_FLOAT]]
+
+## ---- Mach-O + DWARF definition ----
+##
+## CU1 debug_info layout (starting at 0x00):
+## 0x00: CU header (11 bytes)
+## 0x0b: DW_TAG_compile_unit
+## 0x1a: DW_TAG_class_type "MyTemplate" (template param T -> int at 0x44)
+## 0x2f: DW_TAG_class_type "MyTemplate" (template param T -> float at 0x49)
+## 0x44: DW_TAG_base_type "int"
+## 0x49: DW_TAG_base_type "float"
+## 0x50: DW_TAG_subprogram "foo" (low_pc at section offset 0x55)
+## 0x61: DW_TAG_variable "var1" (type -> 0x1a)
+## 0x6f: DW_TAG_variable "var2" (type -> 0x2f)
+## 0x7e: end CU1
+##
+## CU2 debug_info layout (starting at 0x7f):
+## 0x7f: CU header (11 bytes)
+## 0x8a: DW_TAG_compile_unit
+## 0x99: DW_TAG_class_type "MyTemplate" (template param T -> float at 0xb3)
+## 0xae: DW_TAG_base_type "int"
+## 0xb3: DW_TAG_base_type "float"
+## 0xba: DW_TAG_subprogram "foo" (low_pc at section offset 0xbf)
+## 0xcb: DW_TAG_variable "var3" (type -> 0x99)
+## 0xda: end CU2
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 2
+ sizeofcmds: 376
+ flags: 0x00002000
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 232
+ segname: ''
+ vmaddr: 0x00
+ vmsize: 0x300
+ fileoff: 0x300
+ filesize: 0x300
+ maxprot: 7
+ initprot: 7
+ nsects: 2
+ flags: 0
+ Sections:
+ - sectname: __debug_abbrev
+ segname: __DWARF
+ addr: 0x000000000000000F
+ size: 0x76
+ offset: 0x00000380
+ align: 0
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x02000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __debug_info
+ segname: __DWARF
+ addr: 0x000000000000100
+ size: 0xDB
+ offset: 0x000003F6
+ align: 0
+ reloff: 0x00000600
+ nreloc: 2
+ flags: 0x02000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ relocations:
+ - address: 0x55
+ symbolnum: 0
+ pcrel: false
+ length: 3
+ extern: true
+ type: 0
+ scattered: false
+ value: 0
+ - address: 0xBF
+ symbolnum: 0
+ pcrel: false
+ length: 3
+ extern: true
+ type: 0
+ scattered: false
+ value: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 0x700
+ nsyms: 1
+ stroff: 0x710
+ strsize: 10
+LinkEditData:
+ NameList:
+ - n_strx: 1
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 0
+ StringTable:
+ - ''
+ - '__Z3foov'
+ - ''
+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
+ - Tag: DW_TAG_class_type
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_byte_size
+ Form: DW_FORM_data1
+ - Tag: DW_TAG_template_type_parameter
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_type
+ Form: DW_FORM_ref_addr
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Tag: DW_TAG_base_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - 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_data4
+ - Tag: DW_TAG_variable
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_const_value
+ Form: DW_FORM_data4
+ - Attribute: DW_AT_type
+ Form: DW_FORM_ref_addr
+ - 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
+ - Tag: DW_TAG_class_type
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_byte_size
+ Form: DW_FORM_data1
+ - Tag: DW_TAG_template_type_parameter
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_type
+ Form: DW_FORM_ref_addr
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Tag: DW_TAG_base_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - 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_data4
+ - Tag: DW_TAG_variable
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_const_value
+ Form: DW_FORM_data4
+ - Attribute: DW_AT_type
+ Form: DW_FORM_ref_addr
+ debug_info:
+ - Version: 4
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - Value: 0x04
+ - CStr: CU1
+ ## 0x1a: MyTemplate<int> (simple template name)
+ - AbbrCode: 2
+ Values:
+ - CStr: MyTemplate
+ - Value: 0x04
+ - AbbrCode: 3
+ Values:
+ - Value: 0x00000044
+ - CStr: T
+ - AbbrCode: 0
+ ## 0x2f: MyTemplate<float> (simple template name)
+ - AbbrCode: 2
+ Values:
+ - CStr: MyTemplate
+ - Value: 0x04
+ - AbbrCode: 3
+ Values:
+ - Value: 0x00000049
+ - CStr: T
+ - AbbrCode: 0
+ ## 0x44: base types
+ - AbbrCode: 4
+ Values:
+ - CStr: int
+ - AbbrCode: 4
+ Values:
+ - CStr: float
+ ## 0x50: subprogram (low_pc at offset 0x55 in section)
+ - AbbrCode: 5
+ Values:
+ - CStr: foo
+ - Value: 0x0000000000000000
+ - Value: 0x00000010
+ - AbbrCode: 6
+ Values:
+ - CStr: var1
+ - Value: 0x00000000
+ - Value: 0x0000001a
+ - AbbrCode: 6
+ Values:
+ - CStr: var2
+ - Value: 0x00000000
+ - Value: 0x0000002f
+ - AbbrCode: 0
+ - AbbrCode: 0
+ - Version: 4
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - Value: 0x04
+ - CStr: CU2
+ ## 0x99: MyTemplate<float> (simple template name)
+ - AbbrCode: 2
+ Values:
+ - CStr: MyTemplate
+ - Value: 0x04
+ - AbbrCode: 3
+ Values:
+ - Value: 0x000000b3
+ - CStr: T
+ - AbbrCode: 0
+ ## base types
+ - AbbrCode: 4
+ Values:
+ - CStr: int
+ - AbbrCode: 4
+ Values:
+ - CStr: float
+ ## 0xba: subprogram (low_pc at offset 0xbf in section)
+ - AbbrCode: 5
+ Values:
+ - CStr: foo
+ - Value: 0x0000000000000000
+ - Value: 0x00000010
+ - AbbrCode: 6
+ Values:
+ - CStr: var3
+ - Value: 0x00000000
+ - Value: 0x00000099
+ - AbbrCode: 0
+ - AbbrCode: 0
+...
diff --git a/llvm/test/tools/dsymutil/X86/odr-subprogram-template-name-no-linkage.test b/llvm/test/tools/dsymutil/X86/odr-subprogram-template-name-no-linkage.test
new file mode 100644
index 0000000000000..b2a01f046a983
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/odr-subprogram-template-name-no-linkage.test
@@ -0,0 +1,133 @@
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '---' > %t.map
+# RUN: echo "triple: 'x86_64-apple-darwin'" >> %t.map
+# RUN: echo 'objects:' >> %t.map
+# RUN: echo " - filename: '%t.o'" >> %t.map
+# RUN: echo ' symbols:' >> %t.map
+# RUN: echo ' - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }' >> %t.map
+# RUN: echo '...' >> %t.map
+# RUN: dsymutil --linker classic -f -y %t.map -o - | llvm-dwarfdump --debug-info - | FileCheck %s
+# RUN: dsymutil --linker parallel -f -y %t.map -o - | llvm-dwarfdump --debug-info - | FileCheck %s
+
+## Regression test: with -gline-tables-only, clang may emit a DW_TAG_subprogram
+## with a demangled template-like DW_AT_name (e.g. "foo<int>") but no
+## DW_AT_linkage_name. dsymutil must not assert in this case.
+
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"CU1"
+# CHECK: DW_TAG_subprogram
+# CHECK: DW_AT_name{{.*}}"foo<int>"
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 2
+ sizeofcmds: 296
+ flags: 0x00002000
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 232
+ segname: ''
+ vmaddr: 0x00
+ vmsize: 0x200
+ fileoff: 0x200
+ filesize: 0x200
+ maxprot: 7
+ initprot: 7
+ nsects: 2
+ flags: 0
+ Sections:
+ - sectname: __debug_abbrev
+ segname: __DWARF
+ addr: 0x0000000000000000
+ size: 0x20
+ offset: 0x00000280
+ align: 0
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x02000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __debug_info
+ segname: __DWARF
+ addr: 0x0000000000000100
+ size: 0x32
+ offset: 0x000002A0
+ align: 0
+ reloff: 0x00000400
+ nreloc: 1
+ flags: 0x02000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ relocations:
+ - address: 0x25
+ symbolnum: 0
+ pcrel: false
+ length: 3
+ extern: true
+ type: 0
+ scattered: false
+ value: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 0x500
+ nsyms: 1
+ stroff: 0x510
+ strsize: 10
+LinkEditData:
+ NameList:
+ - n_strx: 1
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 0
+ StringTable:
+ - ''
+ - '__Z3foov'
+ - ''
+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
+ - Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_external
+ Form: DW_FORM_flag
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_high_pc
+ Form: DW_FORM_data4
+ debug_info:
+ - Version: 4
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - Value: 0x04
+ - CStr: CU1
+ ## DW_TAG_subprogram with template-like DW_AT_name and no linkage name.
+ - AbbrCode: 2
+ Values:
+ - CStr: 'foo<int>'
+ - Value: 0x01
+ - Value: 0x0000000000000000
+ - Value: 0x00000010
+ - AbbrCode: 0
+...
More information about the llvm-commits
mailing list