[llvm] [BOLT][DWARF] Fix handling of DW_TAG_label (PR #86182)
Alexander Yermolovich via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 21 12:45:39 PDT 2024
https://github.com/ayermolo updated https://github.com/llvm/llvm-project/pull/86182
>From ad69ab9a7872070b549198ed26774a649c819779 Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Thu, 21 Mar 2024 12:13:39 -0700
Subject: [PATCH 1/2] [BOLT][DWARF] Fix handling of DW_TAG_label
Summary:
For DWARF5 BOLT was not retreiving address and instead was setting an index.
Changed so that an address is used, and added DWARF4 test because it was
missing.
Test Plan:
Reviewers:
Subscribers:
Tasks:
Tags:
Differential Revision: https://phabricator.intern.facebook.com/D55210197
---
bolt/lib/Rewrite/DWARFRewriter.cpp | 43 +++--
bolt/test/X86/dwarf4-label-low-pc.s | 263 ++++++++++++++++++++++++++++
bolt/test/X86/dwarf5-label-low-pc.s | 12 +-
3 files changed, 304 insertions(+), 14 deletions(-)
create mode 100644 bolt/test/X86/dwarf4-label-low-pc.s
diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp
index 8dc7b90a6e307e..601a2105fc264f 100644
--- a/bolt/lib/Rewrite/DWARFRewriter.cpp
+++ b/bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -375,12 +375,11 @@ static cl::opt<bool> AlwaysConvertToRanges(
extern cl::opt<std::string> CompDirOverride;
} // namespace opts
-static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU,
- uint64_t &LowPC, uint64_t &HighPC,
- uint64_t &SectionIndex) {
+/// If DW_AT_low_pc exists sets LowPC and returns true.
+static bool getLowPC(const DIE &Die, const DWARFUnit &DU, uint64_t &LowPC,
+ uint64_t &SectionIndex) {
DIEValue DvalLowPc = Die.findAttribute(dwarf::DW_AT_low_pc);
- DIEValue DvalHighPc = Die.findAttribute(dwarf::DW_AT_high_pc);
- if (!DvalLowPc || !DvalHighPc)
+ if (!DvalLowPc)
return false;
dwarf::Form Form = DvalLowPc.getForm();
@@ -403,14 +402,39 @@ static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU,
LowPC = LowPcValue;
SectionIndex = 0;
}
+ return true;
+}
+
+/// If DW_AT_high_pc exists sets HighPC and returns true.
+static bool getHighPC(const DIE &Die, const uint64_t LowPC, uint64_t &HighPC) {
+ DIEValue DvalHighPc = Die.findAttribute(dwarf::DW_AT_high_pc);
+ if (!DvalHighPc)
+ return false;
if (DvalHighPc.getForm() == dwarf::DW_FORM_addr)
HighPC = DvalHighPc.getDIEInteger().getValue();
else
HighPC = LowPC + DvalHighPc.getDIEInteger().getValue();
-
return true;
}
+/// If DW_AT_low_pc and DW_AT_high_pc exist sets LowPC and HighPC and returns
+/// true.
+static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU,
+ uint64_t &LowPC, uint64_t &HighPC,
+ uint64_t &SectionIndex) {
+ uint64_t TempLowPC = LowPC;
+ uint64_t TempHighPC = HighPC;
+ uint64_t TempSectionIndex = SectionIndex;
+ if (getLowPC(Die, DU, TempLowPC, TempSectionIndex) &&
+ getHighPC(Die, TempLowPC, TempHighPC)) {
+ LowPC = TempLowPC;
+ HighPC = TempHighPC;
+ SectionIndex = TempSectionIndex;
+ return true;
+ }
+ return false;
+}
+
static Expected<llvm::DWARFAddressRangesVector>
getDIEAddressRanges(const DIE &Die, DWARFUnit &DU) {
uint64_t LowPC, HighPC, Index;
@@ -1248,10 +1272,9 @@ void DWARFRewriter::updateUnitDebugInfo(
}
}
} else if (LowPCAttrInfo) {
- const std::optional<uint64_t> Result =
- LowPCAttrInfo.getDIEInteger().getValue();
- if (Result.has_value()) {
- const uint64_t Address = Result.value();
+ uint64_t Address = 0;
+ uint64_t SectionIndex = 0;
+ if (getLowPC(*Die, Unit, Address, SectionIndex)) {
uint64_t NewAddress = 0;
if (const BinaryFunction *Function =
BC.getBinaryFunctionContainingAddress(Address)) {
diff --git a/bolt/test/X86/dwarf4-label-low-pc.s b/bolt/test/X86/dwarf4-label-low-pc.s
new file mode 100644
index 00000000000000..2fb368329875d9
--- /dev/null
+++ b/bolt/test/X86/dwarf4-label-low-pc.s
@@ -0,0 +1,263 @@
+
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %s -o %tmain.o
+# RUN: %clang %cflags -dwarf-4 %tmain.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt > %t.txt
+# RUN: llvm-objdump -d %t.bolt >> %t.txt
+# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s
+
+# This test checks that we correctly handle DW_AT_low_pc [DW_FORM_addr] that is part of DW_TAG_label.
+
+# PRECHECK: version = 0x0004
+# PRECHECK: DW_TAG_label
+# PRECHECK-NEXT: DW_AT_name
+# PRECHECK-NEXT: DW_AT_decl_file
+# PRECHECK-NEXT: DW_AT_decl_line
+# PRECHECK-NEXT:DW_AT_low_pc [DW_FORM_addr]
+# PRECHECK: DW_TAG_label
+# PRECHECK-NEXT: DW_AT_name
+# PRECHECK-NEXT: DW_AT_decl_file
+# PRECHECK-NEXT: DW_AT_decl_line
+# PRECHECK-NEXT:DW_AT_low_pc [DW_FORM_addr]
+
+# POSTCHECK: version = 0x0004
+# POSTCHECK: DW_TAG_label
+# POSTCHECK-NEXT: DW_AT_name
+# POSTCHECK-NEXT: DW_AT_decl_file
+# POSTCHECK-NEXT: DW_AT_decl_line
+# POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addr] (0x[[ADDR:[1-9a-f]*]]
+# POSTCHECK: DW_TAG_label
+# POSTCHECK-NEXT: DW_AT_name
+# POSTCHECK-NEXT: DW_AT_decl_file
+# POSTCHECK-NEXT: DW_AT_decl_line
+# POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addr] (0x[[ADDR2:[1-9a-f]*]]
+
+# POSTCHECK: [[ADDR]]: 8b 45 f8
+# POSTCHECK: [[ADDR2]]: 8b 45 f8
+
+# clang++ main.cpp -g2 -gdwarf-4 -S
+# int main() {
+# int a = 4;
+# if (a == 5)
+# goto LABEL1;
+# else
+# goto LABEL2;
+# LABEL1:a++;
+# LABEL2:a--;
+# return 0;
+# }
+
+ .text
+ .file "main.cpp"
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .file 1 "/home" "main.cpp"
+ .loc 1 1 0 # main.cpp:1:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl $0, -4(%rbp)
+.Ltmp0:
+ .loc 1 2 7 prologue_end # main.cpp:2:7
+ movl $4, -8(%rbp)
+.Ltmp1:
+ .loc 1 3 9 # main.cpp:3:9
+ cmpl $5, -8(%rbp)
+.Ltmp2:
+ .loc 1 3 7 is_stmt 0 # main.cpp:3:7
+ jne .LBB0_2
+# %bb.1: # %if.then
+.Ltmp3:
+ .loc 1 4 5 is_stmt 1 # main.cpp:4:5
+ jmp .LBB0_3
+.LBB0_2: # %if.else
+ .loc 1 6 5 # main.cpp:6:5
+ jmp .LBB0_4
+.Ltmp4:
+.LBB0_3: # %LABEL1
+ #DEBUG_LABEL: main:LABEL1
+ .loc 1 7 11 # main.cpp:7:11
+ movl -8(%rbp), %eax
+ addl $1, %eax
+ movl %eax, -8(%rbp)
+.LBB0_4: # %LABEL2
+.Ltmp5:
+ #DEBUG_LABEL: main:LABEL2
+ .loc 1 8 11 # main.cpp:8:11
+ movl -8(%rbp), %eax
+ addl $-1, %eax
+ movl %eax, -8(%rbp)
+ .loc 1 9 3 # main.cpp:9:3
+ xorl %eax, %eax
+ .loc 1 9 3 epilogue_begin is_stmt 0 # main.cpp:9:3
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp6:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_abbrev,"", at progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 14 # DW_FORM_strp
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 14 # DW_FORM_strp
+ .byte 17 # DW_AT_low_pc
+ .byte 1 # DW_FORM_addr
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 1 # DW_FORM_addr
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 10 # DW_TAG_label
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 17 # DW_AT_low_pc
+ .byte 1 # DW_FORM_addr
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 4 # DWARF version number
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 8 # Address Size (in bytes)
+ .byte 1 # Abbrev [1] 0xb:0x6d DW_TAG_compile_unit
+ .long .Linfo_string0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .long .Linfo_string1 # DW_AT_name
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Linfo_string2 # DW_AT_comp_dir
+ .quad .Lfunc_begin0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 2 # Abbrev [2] 0x2a:0x46 DW_TAG_subprogram
+ .quad .Lfunc_begin0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .long .Linfo_string3 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .long 112 # DW_AT_type
+ # DW_AT_external
+ .byte 3 # Abbrev [3] 0x43:0xe DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 120
+ .long .Linfo_string5 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 112 # DW_AT_type
+ .byte 4 # Abbrev [4] 0x51:0xf DW_TAG_label
+ .long .Linfo_string6 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ .quad .Ltmp4 # DW_AT_low_pc
+ .byte 4 # Abbrev [4] 0x60:0xf DW_TAG_label
+ .long .Linfo_string7 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 8 # DW_AT_decl_line
+ .quad .Ltmp5 # DW_AT_low_pc
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x70:0x7 DW_TAG_base_type
+ .long .Linfo_string4 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=24
+.Linfo_string2:
+ .asciz "/home" # string offset=33
+.Linfo_string3:
+ .asciz "main" # string offset=71
+.Linfo_string4:
+ .asciz "int" # string offset=76
+.Linfo_string5:
+ .asciz "a" # string offset=80
+.Linfo_string6:
+ .asciz "LABEL1" # string offset=82
+.Linfo_string7:
+ .asciz "LABEL2" # string offset=89
+ .ident "clang version 19.0.0git"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/bolt/test/X86/dwarf5-label-low-pc.s b/bolt/test/X86/dwarf5-label-low-pc.s
index 890d9e024d1a0c..a1c03a6e2bbca4 100644
--- a/bolt/test/X86/dwarf5-label-low-pc.s
+++ b/bolt/test/X86/dwarf5-label-low-pc.s
@@ -8,6 +8,7 @@
# RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt > %t.txt
# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt
+# RUN: llvm-objdump -d %t.bolt >> %t.txt
# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s
# This test checks that we correctly handle DW_AT_low_pc [DW_FORM_addrx] that is part of DW_TAG_label.
@@ -28,8 +29,8 @@
# POSTCHECK: Addrs: [
# POSTCHECK-NEXT: 0x
# POSTCHECK-NEXT: 0x
-# POSTCHECK-NEXT: 0x[[#%.16x,ADDR:]]
-# POSTCHECK-NEXT: 0x[[#%.16x,ADDR2:]]
+# POSTCHECK-NEXT: 0x[[ADDR:[1-9a-f]*]]
+# POSTCHECK-NEXT: 0x[[ADDR2:[1-9a-f]*]]
# POSTCHECK: version = 0x0005
# POSTCHECK: DW_TAG_label
@@ -37,13 +38,16 @@
# POSTCHECK-NEXT: DW_AT_decl_file
# POSTCHECK-NEXT: DW_AT_decl_line
# POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addrx] (indexed (00000002)
-# POSTCHECK-SAME: 0x[[#ADDR]]
+# POSTCHECK-SAME: 0x[[ADDR]]
# POSTCHECK: DW_TAG_label
# POSTCHECK-NEXT: DW_AT_name
# POSTCHECK-NEXT: DW_AT_decl_file
# POSTCHECK-NEXT: DW_AT_decl_line
# POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003)
-# POSTCHECK-SAME: 0x[[#ADDR2]]
+# POSTCHECK-SAME: 0x[[ADDR2]]
+
+# POSTCHECK: [[ADDR]]: 8b 45 f8
+# POSTCHECK: [[ADDR2]]: 8b 45 f8
# clang++ main.cpp -g -S
# int main() {
>From 48dbba2b5ba00cc5fe3b50bf6da3a13bd8cbe715 Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Thu, 21 Mar 2024 12:45:25 -0700
Subject: [PATCH 2/2] added double hashes
---
bolt/test/X86/dwarf4-label-low-pc.s | 24 ++++++++++++------------
bolt/test/X86/dwarf5-label-low-pc.s | 24 ++++++++++++------------
2 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/bolt/test/X86/dwarf4-label-low-pc.s b/bolt/test/X86/dwarf4-label-low-pc.s
index 2fb368329875d9..dfd5af18c09b75 100644
--- a/bolt/test/X86/dwarf4-label-low-pc.s
+++ b/bolt/test/X86/dwarf4-label-low-pc.s
@@ -9,7 +9,7 @@
# RUN: llvm-objdump -d %t.bolt >> %t.txt
# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s
-# This test checks that we correctly handle DW_AT_low_pc [DW_FORM_addr] that is part of DW_TAG_label.
+## This test checks that we correctly handle DW_AT_low_pc [DW_FORM_addr] that is part of DW_TAG_label.
# PRECHECK: version = 0x0004
# PRECHECK: DW_TAG_label
@@ -38,17 +38,17 @@
# POSTCHECK: [[ADDR]]: 8b 45 f8
# POSTCHECK: [[ADDR2]]: 8b 45 f8
-# clang++ main.cpp -g2 -gdwarf-4 -S
-# int main() {
-# int a = 4;
-# if (a == 5)
-# goto LABEL1;
-# else
-# goto LABEL2;
-# LABEL1:a++;
-# LABEL2:a--;
-# return 0;
-# }
+## clang++ main.cpp -g2 -gdwarf-4 -S
+## int main() {
+## int a = 4;
+## if (a == 5)
+## goto LABEL1;
+## else
+## goto LABEL2;
+## LABEL1:a++;
+## LABEL2:a--;
+## return 0;
+## }
.text
.file "main.cpp"
diff --git a/bolt/test/X86/dwarf5-label-low-pc.s b/bolt/test/X86/dwarf5-label-low-pc.s
index a1c03a6e2bbca4..1e3fc17ad516ac 100644
--- a/bolt/test/X86/dwarf5-label-low-pc.s
+++ b/bolt/test/X86/dwarf5-label-low-pc.s
@@ -11,7 +11,7 @@
# RUN: llvm-objdump -d %t.bolt >> %t.txt
# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s
-# This test checks that we correctly handle DW_AT_low_pc [DW_FORM_addrx] that is part of DW_TAG_label.
+## This test checks that we correctly handle DW_AT_low_pc [DW_FORM_addrx] that is part of DW_TAG_label.
# PRECHECK: version = 0x0005
# PRECHECK: DW_TAG_label
@@ -49,17 +49,17 @@
# POSTCHECK: [[ADDR]]: 8b 45 f8
# POSTCHECK: [[ADDR2]]: 8b 45 f8
-# clang++ main.cpp -g -S
-# int main() {
-# int a = 4;
-# if (a == 5)
-# goto LABEL1;
-# else
-# goto LABEL2;
-# LABEL1:a++;
-# LABEL2:a--;
-# return 0;
-# }
+## clang++ main.cpp -g -S
+## int main() {
+## int a = 4;
+## if (a == 5)
+## goto LABEL1;
+## else
+## goto LABEL2;
+## LABEL1:a++;
+## LABEL2:a--;
+## return 0;
+## }
.text
.file "main.cpp"
More information about the llvm-commits
mailing list