https://github.com/xgupta updated https://github.com/llvm/llvm-project/pull/146572
>From 31de6db3f0d2b28b5c7307aeb4d6b9acb68c252a Mon Sep 17 00:00:00 2001 From: Shivam Gupta <[email protected]> Date: Tue, 1 Jul 2025 19:42:48 +0530 Subject: [PATCH 1/6] [AArch64] Support TLS variables in debug info This adds an implementation of getDebugThreadLocalSymbol for AArch64 by using AArch::S_DTPREL. Fixes #83466 --- lld/ELF/Arch/AArch64.cpp | 8 ++++ .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 1 + .../AArch64/AArch64TargetObjectFile.cpp | 7 +++- .../Target/AArch64/AArch64TargetObjectFile.h | 3 ++ .../AArch64/AsmParser/AArch64AsmParser.cpp | 1 + .../MCTargetDesc/AArch64ELFObjectWriter.cpp | 5 +++ .../AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp | 4 ++ llvm/test/CodeGen/AArch64/tls-dtprel64.ll | 37 ++++++++++++++++++ .../test/DebugInfo/AArch64/tls-at-location.ll | 12 ++++-- llvm/test/MC/AArch64/tls-dtprel64.s | 38 +++++++++++++++++++ 10 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/tls-dtprel64.ll create mode 100644 llvm/test/MC/AArch64/tls-dtprel64.s diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index f85a3f48f2183..26d98aa8312a9 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -236,6 +236,10 @@ void AArch64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) { expr = RE_AARCH64_AUTH; break; + case R_AARCH64_TLS_DTPREL64: + expr = R_DTPREL; + break; + case R_AARCH64_PATCHINST: if (!isAbsolute(sym)) Err(ctx) << getErrorLoc(ctx, sec.content().data() + offset) @@ -649,6 +653,10 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, checkInt(ctx, loc, val, 32, rel); write32(ctx, loc, val); break; + case R_AARCH64_TLS_DTPREL64: + checkInt(ctx, loc, val, 64, rel); + write64(ctx, loc, val); + break; case R_AARCH64_ADD_ABS_LO12_NC: case R_AARCH64_AUTH_GOT_ADD_LO12_NC: write32Imm12(loc, val); diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index d5d0dcf1e0d84..de60c0bd41340 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -3118,6 +3118,7 @@ unsigned ObjectFileELF::ApplyRelocations( case llvm::ELF::EM_AARCH64: switch (reloc_type(rel)) { case R_AARCH64_ABS64: + case R_AARCH64_TLS_DTPREL64: ApplyELF64ABS64Relocation(symtab, rel, debug_data, rel_section); break; case R_AARCH64_ABS32: diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp index 886f41975e199..0d2c3e15004eb 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp @@ -30,7 +30,7 @@ void AArch64_ELFTargetObjectFile::Initialize(MCContext &Ctx, // AARCH64 ELF ABI does not define static relocation type for TLS offset // within a module. Do not generate AT_location for TLS variables. - SupportDebugThreadLocalLocation = false; + SupportDebugThreadLocalLocation = true; // Make sure the implicitly created empty .text section has the // SHF_AARCH64_PURECODE flag set if the "+execute-only" target feature is @@ -187,3 +187,8 @@ MCSection *AArch64_ELFTargetObjectFile::SelectSectionForGlobal( return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM); } + +const MCExpr *AArch64_ELFTargetObjectFile::getDebugThreadLocalSymbol( + const MCSymbol *Sym) const { + return MCSymbolRefExpr::create(Sym, AArch64::S_DTPREL, getContext()); +} diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h index 6b3381452c70b..78c0c22da8d1b 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h +++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h @@ -40,6 +40,9 @@ class AArch64_ELFTargetObjectFile : public TargetLoweringObjectFileELF { MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const override; + + /// Describe a TLS variable address within debug info. + const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const override; }; /// AArch64_MachoTargetObjectFile - This TLOF implementation is used for Darwin. diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 590da8f93873d..cdfb9ee46634a 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -4659,6 +4659,7 @@ bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) { .Case("prel_g1_nc", AArch64::S_PREL_G1_NC) .Case("prel_g0", AArch64::S_PREL_G0) .Case("prel_g0_nc", AArch64::S_PREL_G0_NC) + .Case("dtprel", AArch64::S_DTPREL) .Case("dtprel_g2", AArch64::S_DTPREL_G2) .Case("dtprel_g1", AArch64::S_DTPREL_G1) .Case("dtprel_g1_nc", AArch64::S_DTPREL_G1_NC) diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp index e33196d4c0144..003c666814cc8 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp @@ -249,8 +249,11 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup, } if (RefKind == AArch64::S_AUTH || RefKind == AArch64::S_AUTHADDR) return ELF::R_AARCH64_AUTH_ABS64; + if (RefKind == AArch64::S_DTPREL) { + return ELF::R_AARCH64_TLS_DTPREL64; if (RefKind == AArch64::S_FUNCINIT) return ELF::R_AARCH64_FUNCINIT64; + } return ELF::R_AARCH64_ABS64; } case AArch64::fixup_aarch64_add_imm12: @@ -465,6 +468,8 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup, return R_CLS(MOVW_PREL_G0); if (RefKind == AArch64::S_PREL_G0_NC) return R_CLS(MOVW_PREL_G0_NC); + if (RefKind == AArch64::S_DTPREL) + return ELF::R_AARCH64_TLS_DTPREL64; if (RefKind == AArch64::S_DTPREL_G2) return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2; if (RefKind == AArch64::S_DTPREL_G1) diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp index ff7831e752b8a..66c8d52736f5e 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp @@ -38,6 +38,9 @@ const MCAsmInfo::AtSpecifier COFFAtSpecifiers[] = { const MCAsmInfo::AtSpecifier ELFAtSpecifiers[] = { {AArch64::S_GOT, "GOT"}, + {AArch64::S_GOTPCREL, "GOTPCREL"}, + {AArch64::S_PLT, "PLT"}, + {AArch64::S_FUNCINIT, "FUNCINIT"}, }; const MCAsmInfo::AtSpecifier MachOAtSpecifiers[] = { @@ -73,6 +76,7 @@ StringRef AArch64::getSpecifierName(AArch64::Specifier S) { case AArch64::S_PREL_G1_NC: return ":prel_g1_nc:"; case AArch64::S_PREL_G0: return ":prel_g0:"; case AArch64::S_PREL_G0_NC: return ":prel_g0_nc:"; + case AArch64::S_DTPREL: return ":dtprel:"; case AArch64::S_DTPREL_G2: return ":dtprel_g2:"; case AArch64::S_DTPREL_G1: return ":dtprel_g1:"; case AArch64::S_DTPREL_G1_NC: return ":dtprel_g1_nc:"; diff --git a/llvm/test/CodeGen/AArch64/tls-dtprel64.ll b/llvm/test/CodeGen/AArch64/tls-dtprel64.ll new file mode 100644 index 0000000000000..c481980354905 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/tls-dtprel64.ll @@ -0,0 +1,37 @@ +; RUN: llc -O0 -mtriple=aarch64-linux-gnu -filetype=obj < %s \ +; RUN: | llvm-objdump -r - | FileCheck %s + +; CHECK: R_AARCH64_TLS_DTPREL64 + +@var = thread_local global i32 0, align 4, !dbg !0 + +; Function Attrs: noinline nounwind optnone +define i32 @foo() #0 !dbg !11 { +entry: + %0 = load i32, ptr @var, align 4, !dbg !14 + ret i32 %0, !dbg !15 +} + +attributes #0 = { noinline nounwind optnone } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "var", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 7.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) +!3 = !DIFile(filename: "tls-at-location.c", directory: "/home/lliu0/llvm/tls-at-location/DebugInfo/AArch64") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 7.0.0"} +!11 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 3, type: !12, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: false, unit: !2) +!12 = !DISubroutineType(types: !13) +!13 = !{!6} +!14 = !DILocation(line: 4, column: 10, scope: !11) +!15 = !DILocation(line: 4, column: 3, scope: !11) + diff --git a/llvm/test/DebugInfo/AArch64/tls-at-location.ll b/llvm/test/DebugInfo/AArch64/tls-at-location.ll index 20a0afb789771..d619962ccbf69 100644 --- a/llvm/test/DebugInfo/AArch64/tls-at-location.ll +++ b/llvm/test/DebugInfo/AArch64/tls-at-location.ll @@ -1,8 +1,14 @@ -; RUN: llc -filetype=obj -mtriple=aarch64--linux-gnu -o - %s | llvm-dwarfdump -v - | FileCheck %s -; +; RUN: llc -O0 -mtriple=aarch64-non-linux-gnu -filetype=obj < %s \ +; RUN: | llvm-dwarfdump - | FileCheck %s + ; CHECK: .debug_info contents: ; CHECK: DW_TAG_variable -; CHECK-NOT: DW_AT_location +; CHECK: DW_AT_name ("var") +; CHECK-NEXT: DW_AT_type (0x00000040 "int") +; CHECK-NEXT: DW_AT_external (true) +; CHECK-NEXT: DW_AT_decl_file ("{{.*}}tls-at-location.c") +; CHECK-NEXT: DW_AT_decl_line (1) +; CHECK-NEXT: DW_AT_location (DW_OP_const8u 0x0, DW_OP_GNU_push_tls_address) @var = thread_local global i32 0, align 4, !dbg !0 diff --git a/llvm/test/MC/AArch64/tls-dtprel64.s b/llvm/test/MC/AArch64/tls-dtprel64.s new file mode 100644 index 0000000000000..7cb47f9543f68 --- /dev/null +++ b/llvm/test/MC/AArch64/tls-dtprel64.s @@ -0,0 +1,38 @@ +# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s | llvm-readobj -r - | FileCheck %s + +# CHECK: Relocations [ +# CHECK: Section {{.*}} .rela.debug_info { +# CHECK: 0x{{[0-9A-F]+}} R_AARCH64_TLS_DTPREL64 var {{.*}} +# CHECK: } + +.section .tdata,"awT",@progbits +.globl var +var: + .word 0 + +.section .debug_abbrev,"",@progbits +.byte 1 // Abbreviation Code +.byte 17 // DW_TAG_compile_unit +.byte 1 // DW_CHILDREN_yes +.byte 0 // EOM(1) +.byte 0 // EOM(2) + +.byte 2 // Abbreviation Code +.byte 52 // DW_TAG_variable +.byte 0 // DW_CHILDREN_no +.byte 2; // DW_AT_location +.byte 24 // DW_FORM_exprloc +.byte 0 // EOM(1) +.byte 0 // EOM(2) + +.section .debug_info,"",@progbits +.Lcu_begin0: + .word .Lcu_end - .Lcu_body // Length of Unit +.Lcu_body: + .hword 4 // DWARF version number + .word .debug_abbrev // Offset Into Abbrev. Section + .byte 8 // Address Size (in bytes) + .byte 1 // Abbrev [1] DW_TAG_compile_unit + .byte 2 // Abbrev [2] DW_TAG_variable + .xword var@DTPREL +.Lcu_end: >From 4950d703933fbc46a84ca85b9a6313ca69d0430a Mon Sep 17 00:00:00 2001 From: Shivam Gupta <[email protected]> Date: Sun, 18 Jan 2026 21:14:48 +0530 Subject: [PATCH 2/6] Address reviewer's comments --- llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp | 2 -- .../Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp | 3 +-- llvm/test/CodeGen/AArch64/tls-dtprel64.ll | 4 ++-- llvm/test/DebugInfo/AArch64/tls-at-location.ll | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp index 0d2c3e15004eb..573498e6152b6 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp @@ -28,8 +28,6 @@ void AArch64_ELFTargetObjectFile::Initialize(MCContext &Ctx, PLTPCRelativeSpecifier = AArch64::S_PLT; SupportIndirectSymViaGOTPCRel = true; - // AARCH64 ELF ABI does not define static relocation type for TLS offset - // within a module. Do not generate AT_location for TLS variables. SupportDebugThreadLocalLocation = true; // Make sure the implicitly created empty .text section has the diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp index 003c666814cc8..4ecf2ef268f91 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp @@ -249,11 +249,10 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup, } if (RefKind == AArch64::S_AUTH || RefKind == AArch64::S_AUTHADDR) return ELF::R_AARCH64_AUTH_ABS64; - if (RefKind == AArch64::S_DTPREL) { + if (RefKind == AArch64::S_DTPREL) return ELF::R_AARCH64_TLS_DTPREL64; if (RefKind == AArch64::S_FUNCINIT) return ELF::R_AARCH64_FUNCINIT64; - } return ELF::R_AARCH64_ABS64; } case AArch64::fixup_aarch64_add_imm12: diff --git a/llvm/test/CodeGen/AArch64/tls-dtprel64.ll b/llvm/test/CodeGen/AArch64/tls-dtprel64.ll index c481980354905..b025c8c9331fd 100644 --- a/llvm/test/CodeGen/AArch64/tls-dtprel64.ll +++ b/llvm/test/CodeGen/AArch64/tls-dtprel64.ll @@ -1,7 +1,7 @@ ; RUN: llc -O0 -mtriple=aarch64-linux-gnu -filetype=obj < %s \ -; RUN: | llvm-objdump -r - | FileCheck %s +; RUN: | llvm-objdump -r - | FileCheck %s -; CHECK: R_AARCH64_TLS_DTPREL64 +; CHECK: R_AARCH64_TLS_DTPREL64 var @var = thread_local global i32 0, align 4, !dbg !0 diff --git a/llvm/test/DebugInfo/AArch64/tls-at-location.ll b/llvm/test/DebugInfo/AArch64/tls-at-location.ll index d619962ccbf69..13bdad20032be 100644 --- a/llvm/test/DebugInfo/AArch64/tls-at-location.ll +++ b/llvm/test/DebugInfo/AArch64/tls-at-location.ll @@ -1,5 +1,5 @@ ; RUN: llc -O0 -mtriple=aarch64-non-linux-gnu -filetype=obj < %s \ -; RUN: | llvm-dwarfdump - | FileCheck %s +; RUN: | llvm-dwarfdump - | FileCheck %s ; CHECK: .debug_info contents: ; CHECK: DW_TAG_variable >From 38354f86f304fa29c87c13f00db3a90caf1a1268 Mon Sep 17 00:00:00 2001 From: Shivam Gupta <[email protected]> Date: Wed, 25 Feb 2026 12:20:02 +0000 Subject: [PATCH 3/6] Update new ABI syntax for dtprel --- .../AArch64/AsmParser/AArch64AsmParser.cpp | 41 ++++++++++++++++++- llvm/test/MC/AArch64/tls-dtprel64.s | 17 ++++---- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index cdfb9ee46634a..fe34ca17b80ee 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -185,6 +185,7 @@ class AArch64AsmParser : public MCTargetAsmParser { bool parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E); bool parseDataExpr(const MCExpr *&Res) override; bool parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc); + bool parsePercentRelocExpr(const MCExpr *&Res, SMLoc &EndLoc); bool parseDirectiveArch(SMLoc L); bool parseDirectiveArchExtension(SMLoc L); @@ -8476,13 +8477,28 @@ bool AArch64AsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) { } bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) { + MCAsmParser &Parser = getParser(); + SMLoc StartLoc = getLoc(); SMLoc EndLoc; if (parseOptionalToken(AsmToken::Percent)) return parseExprWithSpecifier(Res, EndLoc); + if (getLexer().is(AsmToken::Percent)) { + Lex(); // eat % + + if (getLexer().getKind() != AsmToken::Identifier) + return Error(StartLoc, "expected identifier after '%'"); + + StringRef Identifier = getLexer().getTok().getIdentifier(); + Lex(); // eat identifier + + if (Identifier == "dtprel") + return parsePercentRelocExpr(Res, EndLoc); + return false; + } + if (getParser().parseExpression(Res)) return true; - MCAsmParser &Parser = getParser(); if (!parseOptionalToken(AsmToken::At)) return false; if (getLexer().getKind() != AsmToken::Identifier) @@ -8523,6 +8539,29 @@ bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) { return false; } +bool AArch64AsmParser::parsePercentRelocExpr(const MCExpr *&Res, + SMLoc &EndLoc) { + SMLoc StartLoc = getLoc(); + if (parseToken(AsmToken::LParen, "expected '('")) + return true; + + const MCExpr *Inner; + if (getParser().parseExpression(Inner)) + return true; + + EndLoc = getParser().getTok().getEndLoc(); + + if (parseToken(AsmToken::RParen, "expected ')'")) + return true; + + auto *SymRef = dyn_cast<MCSymbolRefExpr>(Inner); + if (!SymRef) + return Error(StartLoc, "expected symbol inside %operator()"); + + Res = MCSpecifierExpr::create(Inner, AArch64::S_DTPREL, getContext()); + return false; +} + /// parseAuthExpr /// ::= _sym@AUTH(ib,123[,addr]) /// ::= (_sym + 5)@AUTH(ib,123[,addr]) diff --git a/llvm/test/MC/AArch64/tls-dtprel64.s b/llvm/test/MC/AArch64/tls-dtprel64.s index 7cb47f9543f68..34e9588c48f2d 100644 --- a/llvm/test/MC/AArch64/tls-dtprel64.s +++ b/llvm/test/MC/AArch64/tls-dtprel64.s @@ -1,9 +1,12 @@ -# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s | llvm-readobj -r - | FileCheck %s - -# CHECK: Relocations [ -# CHECK: Section {{.*}} .rela.debug_info { -# CHECK: 0x{{[0-9A-F]+}} R_AARCH64_TLS_DTPREL64 var {{.*}} -# CHECK: } +// RUN: llvm-mc -triple=aarch64-none-linux-gnu -show-encoding < %s | FileCheck %s +// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s | llvm-readobj -r - | FileCheck --check-prefix=CHECK-ELF %s + +# CHECK: .xword %dtprel(var) + +# CHECK-ELF: Relocations [ +# CHECK-ELF: Section {{.*}} .rela.debug_info { +# CHECK-ELF: 0x{{[0-9A-F]+}} R_AARCH64_TLS_DTPREL64 var {{.*}} +# CHECK-ELF: } .section .tdata,"awT",@progbits .globl var @@ -34,5 +37,5 @@ var: .byte 8 // Address Size (in bytes) .byte 1 // Abbrev [1] DW_TAG_compile_unit .byte 2 // Abbrev [2] DW_TAG_variable - .xword var@DTPREL + .xword %dtprel(var) .Lcu_end: >From d9b011124409012a3f784bd5658b31804cceedcc Mon Sep 17 00:00:00 2001 From: Shivam Gupta <[email protected]> Date: Sat, 28 Feb 2026 21:07:12 +0000 Subject: [PATCH 4/6] Address review comment --- lld/ELF/Arch/AArch64.cpp | 8 ---- .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 1 - .../AArch64/AArch64TargetObjectFile.cpp | 2 +- .../AArch64/AsmParser/AArch64AsmParser.cpp | 42 +------------------ .../AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp | 3 +- 5 files changed, 4 insertions(+), 52 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 26d98aa8312a9..f85a3f48f2183 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -236,10 +236,6 @@ void AArch64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) { expr = RE_AARCH64_AUTH; break; - case R_AARCH64_TLS_DTPREL64: - expr = R_DTPREL; - break; - case R_AARCH64_PATCHINST: if (!isAbsolute(sym)) Err(ctx) << getErrorLoc(ctx, sec.content().data() + offset) @@ -653,10 +649,6 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, checkInt(ctx, loc, val, 32, rel); write32(ctx, loc, val); break; - case R_AARCH64_TLS_DTPREL64: - checkInt(ctx, loc, val, 64, rel); - write64(ctx, loc, val); - break; case R_AARCH64_ADD_ABS_LO12_NC: case R_AARCH64_AUTH_GOT_ADD_LO12_NC: write32Imm12(loc, val); diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index de60c0bd41340..d5d0dcf1e0d84 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -3118,7 +3118,6 @@ unsigned ObjectFileELF::ApplyRelocations( case llvm::ELF::EM_AARCH64: switch (reloc_type(rel)) { case R_AARCH64_ABS64: - case R_AARCH64_TLS_DTPREL64: ApplyELF64ABS64Relocation(symtab, rel, debug_data, rel_section); break; case R_AARCH64_ABS32: diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp index 573498e6152b6..b855cd9b992d0 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp @@ -188,5 +188,5 @@ MCSection *AArch64_ELFTargetObjectFile::SelectSectionForGlobal( const MCExpr *AArch64_ELFTargetObjectFile::getDebugThreadLocalSymbol( const MCSymbol *Sym) const { - return MCSymbolRefExpr::create(Sym, AArch64::S_DTPREL, getContext()); + return MCSpecifierExpr::create(Sym, AArch64::S_DTPREL, getContext()); } diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index fe34ca17b80ee..017ed2a5d0868 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -185,7 +185,6 @@ class AArch64AsmParser : public MCTargetAsmParser { bool parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E); bool parseDataExpr(const MCExpr *&Res) override; bool parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc); - bool parsePercentRelocExpr(const MCExpr *&Res, SMLoc &EndLoc); bool parseDirectiveArch(SMLoc L); bool parseDirectiveArchExtension(SMLoc L); @@ -8463,7 +8462,6 @@ bool AArch64AsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) { auto Spec = AArch64::parsePercentSpecifierName(Identifier); if (!Spec) return TokError("invalid relocation specifier"); - getParser().Lex(); // Eat the identifier if (parseToken(AsmToken::LParen, "expected '('")) return true; @@ -8477,28 +8475,13 @@ bool AArch64AsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) { } bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) { - MCAsmParser &Parser = getParser(); - SMLoc StartLoc = getLoc(); SMLoc EndLoc; if (parseOptionalToken(AsmToken::Percent)) return parseExprWithSpecifier(Res, EndLoc); - if (getLexer().is(AsmToken::Percent)) { - Lex(); // eat % - - if (getLexer().getKind() != AsmToken::Identifier) - return Error(StartLoc, "expected identifier after '%'"); - - StringRef Identifier = getLexer().getTok().getIdentifier(); - Lex(); // eat identifier - - if (Identifier == "dtprel") - return parsePercentRelocExpr(Res, EndLoc); - return false; - } - if (getParser().parseExpression(Res)) return true; + MCAsmParser &Parser = getParser(); if (!parseOptionalToken(AsmToken::At)) return false; if (getLexer().getKind() != AsmToken::Identifier) @@ -8539,29 +8522,6 @@ bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) { return false; } -bool AArch64AsmParser::parsePercentRelocExpr(const MCExpr *&Res, - SMLoc &EndLoc) { - SMLoc StartLoc = getLoc(); - if (parseToken(AsmToken::LParen, "expected '('")) - return true; - - const MCExpr *Inner; - if (getParser().parseExpression(Inner)) - return true; - - EndLoc = getParser().getTok().getEndLoc(); - - if (parseToken(AsmToken::RParen, "expected ')'")) - return true; - - auto *SymRef = dyn_cast<MCSymbolRefExpr>(Inner); - if (!SymRef) - return Error(StartLoc, "expected symbol inside %operator()"); - - Res = MCSpecifierExpr::create(Inner, AArch64::S_DTPREL, getContext()); - return false; -} - /// parseAuthExpr /// ::= _sym@AUTH(ib,123[,addr]) /// ::= (_sym + 5)@AUTH(ib,123[,addr]) diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp index 66c8d52736f5e..fdbfe6218264d 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp @@ -76,7 +76,6 @@ StringRef AArch64::getSpecifierName(AArch64::Specifier S) { case AArch64::S_PREL_G1_NC: return ":prel_g1_nc:"; case AArch64::S_PREL_G0: return ":prel_g0:"; case AArch64::S_PREL_G0_NC: return ":prel_g0_nc:"; - case AArch64::S_DTPREL: return ":dtprel:"; case AArch64::S_DTPREL_G2: return ":dtprel_g2:"; case AArch64::S_DTPREL_G1: return ":dtprel_g1:"; case AArch64::S_DTPREL_G1_NC: return ":dtprel_g1_nc:"; @@ -118,6 +117,7 @@ StringRef AArch64::getSpecifierName(AArch64::Specifier S) { case AArch64::S_GOTPCREL: return "%gotpcrel"; case AArch64::S_PLT: return "%pltpcrel"; + case AArch64::S_DTPREL: return "%dtprel"; case AArch64::S_FUNCINIT: return "%funcinit"; default: llvm_unreachable("Invalid relocation specifier"); @@ -129,6 +129,7 @@ AArch64::Specifier AArch64::parsePercentSpecifierName(StringRef name) { return StringSwitch<AArch64::Specifier>(name) .Case("pltpcrel", AArch64::S_PLT) .Case("gotpcrel", AArch64::S_GOTPCREL) + .Case("dtprel", AArch64::S_DTPREL) .Case("funcinit", AArch64::S_FUNCINIT) .Default(0); } >From 560348964b084cb49bad6b029b245f2a56ea7edf Mon Sep 17 00:00:00 2001 From: Shivam Gupta <[email protected]> Date: Sat, 28 Feb 2026 22:37:59 +0000 Subject: [PATCH 5/6] added back a removed blank line --- llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 017ed2a5d0868..cdfb9ee46634a 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -8462,6 +8462,7 @@ bool AArch64AsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) { auto Spec = AArch64::parsePercentSpecifierName(Identifier); if (!Spec) return TokError("invalid relocation specifier"); + getParser().Lex(); // Eat the identifier if (parseToken(AsmToken::LParen, "expected '('")) return true; >From 84ed476938ae1a7053b193723c023237c92292b2 Mon Sep 17 00:00:00 2001 From: Shivam Gupta <[email protected]> Date: Sat, 7 Mar 2026 12:12:38 +0000 Subject: [PATCH 6/6] Do not emit DW_AT_location for preemptible global TLS variables --- .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 15 ++++++-- llvm/test/CodeGen/AArch64/tls-dtprel64.ll | 2 +- .../test/DebugInfo/AArch64/tls-at-location.ll | 4 +- .../DebugInfo/AArch64/tls-at-location1.ll | 38 +++++++++++++++++++ 4 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 llvm/test/DebugInfo/AArch64/tls-at-location1.ll diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index eb55b47dfde2b..c9a5e1b4a2e6b 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -274,9 +274,18 @@ void DwarfCompileUnit::addLocationAttribute( if (!Global && (!Expr || !Expr->isConstant())) continue; - if (Global && Global->isThreadLocal() && - !Asm->getObjFileLowering().supportDebugThreadLocalLocation()) - continue; + if (Global && Global->isThreadLocal()) { + // Do not emit TLS location for interposable TLS variables + // (e.g. TLS in shared libraries). The TLS offset cannot be + // represented safely in DWARF. In that case let Debugger use + // Runtime TLS lookup via DTV (Dynmic thread vector). + if (Asm->TM.getTargetTriple().isAArch64() && + Asm->TM.getTargetTriple().isOSBinFormatELF() && !Global->isDSOLocal()) + continue; + + if (!Asm->getObjFileLowering().supportDebugThreadLocalLocation()) + continue; + } if (!Loc) { addToAccelTable = true; diff --git a/llvm/test/CodeGen/AArch64/tls-dtprel64.ll b/llvm/test/CodeGen/AArch64/tls-dtprel64.ll index b025c8c9331fd..a3898e88be6ff 100644 --- a/llvm/test/CodeGen/AArch64/tls-dtprel64.ll +++ b/llvm/test/CodeGen/AArch64/tls-dtprel64.ll @@ -3,7 +3,7 @@ ; CHECK: R_AARCH64_TLS_DTPREL64 var -@var = thread_local global i32 0, align 4, !dbg !0 +@var = internal thread_local global i32 0, align 4, !dbg !0 ; Function Attrs: noinline nounwind optnone define i32 @foo() #0 !dbg !11 { diff --git a/llvm/test/DebugInfo/AArch64/tls-at-location.ll b/llvm/test/DebugInfo/AArch64/tls-at-location.ll index 13bdad20032be..69911eaa3a17b 100644 --- a/llvm/test/DebugInfo/AArch64/tls-at-location.ll +++ b/llvm/test/DebugInfo/AArch64/tls-at-location.ll @@ -4,13 +4,13 @@ ; CHECK: .debug_info contents: ; CHECK: DW_TAG_variable ; CHECK: DW_AT_name ("var") -; CHECK-NEXT: DW_AT_type (0x00000040 "int") +; CHECK-NEXT: DW_AT_type (0x{{.*}} "int") ; CHECK-NEXT: DW_AT_external (true) ; CHECK-NEXT: DW_AT_decl_file ("{{.*}}tls-at-location.c") ; CHECK-NEXT: DW_AT_decl_line (1) ; CHECK-NEXT: DW_AT_location (DW_OP_const8u 0x0, DW_OP_GNU_push_tls_address) -@var = thread_local global i32 0, align 4, !dbg !0 +@var = internal thread_local global i32 0, align 4, !dbg !0 ; Function Attrs: noinline nounwind optnone define i32 @foo() #0 !dbg !11 { diff --git a/llvm/test/DebugInfo/AArch64/tls-at-location1.ll b/llvm/test/DebugInfo/AArch64/tls-at-location1.ll new file mode 100644 index 0000000000000..6e70c36e6e9bf --- /dev/null +++ b/llvm/test/DebugInfo/AArch64/tls-at-location1.ll @@ -0,0 +1,38 @@ +; RUN: llc -O0 -mtriple=aarch64-linux-gnu -filetype=obj < %s \ +; RUN: | llvm-dwarfdump - | FileCheck %s + +; CHECK: .debug_info contents: +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("tls_var") +; CHECK-NEXT: DW_AT_type (0x{{.*}} "int") +; CHECK-NEXT: DW_AT_external (true) +; CHECK-NEXT: DW_AT_decl_file ("{{.*}}tls-location.c") +; CHECK-NEXT: DW_AT_decl_line (1) +; CHECK-NEXT: DW_AT_location (DW_OP_const8u 0x0, DW_OP_GNU_push_tls_address) + +@tls_var = hidden thread_local global i32 0, align 4, !dbg !0 + +define i32 @foo() !dbg !10 { +entry: + %0 = load i32, ptr @tls_var, align 4, !dbg !13 + ret i32 %0, !dbg !14 +} + +!llvm.dbg.cu = !{!1} +!llvm.module.flags = !{!6, !7} +!llvm.ident = !{!8} + +!0 = !DIGlobalVariableExpression(var: !2, expr: !DIExpression()) +!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4) +!2 = distinct !DIGlobalVariable(name: "tls_var", scope: !1, file: !3, line: 1, type: !5, isLocal: false, isDefinition: true) +!3 = !DIFile(filename: "tls-location.c", directory: "/tmp") +!4 = !{!0} +!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!6 = !{i32 2, !"Dwarf Version", i32 4} +!7 = !{i32 2, !"Debug Info Version", i32 3} +!8 = !{!"clang"} +!10 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 3, type: !11, unit: !1) +!11 = !DISubroutineType(types: !12) +!12 = !{!5} +!13 = !DILocation(line: 4, column: 10, scope: !10) +!14 = !DILocation(line: 4, column: 3, scope: !10) _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
