From patchwork Fri Dec 1 16:27:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81158 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 828DA3857C65 for ; Fri, 1 Dec 2023 16:34:23 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id C6E803858C2C for ; Fri, 1 Dec 2023 16:34:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C6E803858C2C Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C6E803858C2C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448445; cv=none; b=h/rRZIiyTPzE4Ox4NXNYoHEVxKEDTsM/E6YqFqTHnvx9Zte6J9wHd3m342Jzkh7GfAnBmv6SvBBfedBCbd2FolNkXJu0YURLl40JXQ6AbQz440hcb+B9ZJY/wuIvFfLN9d7tuMdDd0ItksGu6vtY57faaufrgNQoeL8OQ979YsA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448445; c=relaxed/simple; bh=Am3w7n/WReh2rOTW/YGYPry7Hui7/IBTALMAwQUdSoA=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=C7PsQ4KCJw+D2LfBMsvZi0BD9n1in2LVMegMYrq0iFyQ3X3XC87MudEZivj6FXDA+IOa5NeW76zqWSdNGWn2On1TwHUyO1SwEhwKpKpdUeHBZi6cmWEb4kE41Nv+4wtWEtvuEN/U+8NLW0HUWiXEN9YWpkQLHKSanpeHtgdszFk= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPSA id 361B91E091; Fri, 1 Dec 2023 11:34:01 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 24/24] gdb/testsuite: add tests for unwinding of pseudo registers Date: Fri, 1 Dec 2023 11:27:37 -0500 Message-ID: <20231201162751.741751-25-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org From: Simon Marchi New in v2: - Switched to using x19/w19 in the aarch64 test This patch adds tests to exercise the previous patches' changes. All three tests: - aarch64-pseudo-unwind - amd64-pseudo-unwind - arm-pseudo-unwind follow the same pattern, just with different registers. The other test, arm-pseudo-unwind-legacy, tests the special case where the unwind information contains an entry for a register considered a pseudo-register by GDB. Change-Id: Ic29ac040c5eb087b4a0d79f9d02f65b7979df30f Reviewed-By: John Baldwin Reviewed-by: Luis Machado Tested-By: Luis Machado (aarch64/arm) --- .../gdb.arch/aarch64-pseudo-unwind-asm.S | 82 +++++++++++++++++ .../gdb.arch/aarch64-pseudo-unwind.c | 33 +++++++ .../gdb.arch/aarch64-pseudo-unwind.exp | 88 ++++++++++++++++++ .../gdb.arch/amd64-pseudo-unwind-asm.S | 66 ++++++++++++++ gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c | 33 +++++++ .../gdb.arch/amd64-pseudo-unwind.exp | 91 +++++++++++++++++++ .../gdb.arch/arm-pseudo-unwind-asm.S | 79 ++++++++++++++++ .../gdb.arch/arm-pseudo-unwind-legacy-asm.S | 84 +++++++++++++++++ .../gdb.arch/arm-pseudo-unwind-legacy.c | 33 +++++++ .../gdb.arch/arm-pseudo-unwind-legacy.exp | 86 ++++++++++++++++++ gdb/testsuite/gdb.arch/arm-pseudo-unwind.c | 33 +++++++ gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp | 88 ++++++++++++++++++ 12 files changed, 796 insertions(+) create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind-asm.S create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-asm.S create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy-asm.S create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind.c create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp diff --git a/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind-asm.S b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind-asm.S new file mode 100644 index 000000000000..575ed75ae9f5 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind-asm.S @@ -0,0 +1,82 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +.section .note.GNU-stack,"",%progbits + +.data +value_callee: +.quad 0x2021222324252627 +value_caller: +.quad 0x1011121314151617 + +.text +.global callee +callee: + /* Standard prologue: + - push fp (x29) and lr (x30) to the stack. + - mov sp to fp */ +.cfi_startproc + stp x29, x30, [sp, -16]! +.cfi_def_cfa 29, 16 +.cfi_offset 29, -16 +.cfi_offset 30, -8 + mov x29, sp + + /* Save caller's x19 value on the stack. */ +.cfi_offset 19, -32 + str x19, [sp, -16]! + + /* Put our own x19 value. */ + adr x0, value_callee + ldr x19, [x0] + +break_here_asm: + + /* Restore caller's x19 value. */ + ldr x19, [sp], 16 + + /* Standard epilogue: + - pop fp (x29) and lr (x30) from the stack */ + ldp x29, x30, [sp], 16 + ret +.cfi_endproc + + +.global caller +caller: + /* Standard prologue. */ +.cfi_startproc + stp x29, x30, [sp, -16]! +.cfi_def_cfa 29, 16 +.cfi_offset x29, -16 +.cfi_offset x30, -8 + add x29, sp, 0 + + /* Put our own x19 value. */ + adr x0, value_caller + ldr x19, [x0] + + /* Call callee. */ + bl callee + + /* Store our x19 value in x0 to return it. */ + mov x0, x19 + + /* Standard epilogue. */ + ldp x29, x30, [sp], 16 + ret +.cfi_endproc diff --git a/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.c b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.c new file mode 100644 index 000000000000..d18876fe3be3 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.c @@ -0,0 +1,33 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +uint64_t caller (void); + +static void +break_here_c (uint64_t value) +{ +} + +int +main (void) +{ + uint64_t value = caller (); + break_here_c (value); + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp new file mode 100644 index 000000000000..62b3f8c4337c --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp @@ -0,0 +1,88 @@ +# Copyright 2018-2023 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This test is equivalent to amd64-pseudo-unwind, but specific to AArch64. We +# use the raw register x19 which is 64 bits long and pseudo register w19, which +# is the bottom half of x19. + +if { ![istarget aarch64-*-* ] } { + verbose "Skipping aarch64 pseudo register unwind." + return +} + +standard_testfile aarch64-pseudo-unwind.c aarch64-pseudo-unwind-asm.S + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + "${srcfile} ${srcfile2}" {debug}] } { + return -1 +} + +clean_restart ${binfile} + +if ![runto_main] then { + fail "could not run to main" +} + +gdb_breakpoint break_here_asm temporary +gdb_continue_to_breakpoint "continue to callee" + +# Verify the value of x19/w19 in the inner frame (callee). +with_test_prefix "callee, before change" { + gdb_test "p/x \$x19" " = 0x2021222324252627" + gdb_test "p/x \$w19" " = 0x24252627" +} + +# Verify that we can change the value of the pseudo register (w19) in the inner +# frame (callee). +gdb_test_no_output "set \$w19 = 0x34353637" + +# Verify the value of x19/w19 in the inner frame (callee) after the change. +with_test_prefix "callee, after change" { + gdb_test "p/x \$x19" " = 0x34353637" + gdb_test "p/x \$w19" " = 0x34353637" +} + +# Go up one frame (to caller) and do the same. +gdb_test "up" + +# Verify the value of x19/w19 in the outer frame (caller). +with_test_prefix "caller, before change" { + gdb_test "p/x \$x19" " = 0x1011121314151617" + gdb_test "p/x \$w19" " = 0x14151617" +} + +# Verify that we can change the value of the pseudo register (w19) in the outer +# frame (caller). +gdb_test_no_output "set \$w19 = 0x44454647" + +# Verify the value of x19/w19 in the outer frame (caller) after the change. +with_test_prefix "caller, after change" { + gdb_test "p/x \$x19" " = 0x44454647" + gdb_test "p/x \$w19" " = 0x44454647" +} + +# Go back to frame 0 (callee), check that the change to the outer frame didn't +# mess up anything there. +gdb_test "down" +with_test_prefix "callee, after change in caller" { + gdb_test "p/x \$x19" " = 0x34353637" + gdb_test "p/x \$w19" " = 0x34353637" +} + +# Verify that the value of the saved x19 we changed is correctly seen by the +# inferior. +gdb_breakpoint break_here_c temporary +gdb_continue_to_breakpoint "continue to break_here_c" +gdb_test "p/x value" " = 0x44454647" diff --git a/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S new file mode 100644 index 000000000000..c306b82e4864 --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S @@ -0,0 +1,66 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +.section .note.GNU-stack,"",%progbits + +.text +.global callee +callee: + /* Standard prologue. */ +.cfi_startproc + push %rbp +.cfi_def_cfa rbp, 16 + mov %rsp, %rbp + + /* Save caller's rbx value on the stack. */ +.cfi_offset rbx, -24 + push %rbx + + /* Put our own rbx value. */ + mov $0x2021222324252627, %rbx +break_here_asm: + + /* Restore caller's rbx value. */ + pop %rbx + + /* Standard epilogue. */ + pop %rbp + ret +.cfi_endproc + + +.global caller +caller: +.cfi_startproc + /* Standard prologue. */ + push %rbp +.cfi_def_cfa_offset 16 + mov %rsp, %rbp + + /* Put our own rbx value. */ + mov $0x1011121314151617, %rbx + + /* Call callee. */ + call callee + + /* Store our rbx value in rax to return it. */ + mov %rbx, %rax + + /* Standard epilogue. */ + pop %rbp + ret +.cfi_endproc diff --git a/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c new file mode 100644 index 000000000000..d18876fe3be3 --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c @@ -0,0 +1,33 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +uint64_t caller (void); + +static void +break_here_c (uint64_t value) +{ +} + +int +main (void) +{ + uint64_t value = caller (); + break_here_c (value); + return 0; +} diff --git a/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp new file mode 100644 index 000000000000..45e9a3c96224 --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp @@ -0,0 +1,91 @@ +# Copyright 2018-2023 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This test verifies that we can read and write the value of a pseudo register +# in unwound frames. For the test, we choose one raw register, rbx, and one +# pseudo register that is backed by rbx, ebx. We have two frames (the inner one, +# #0 and the outer one, #1) that each set a value for rbx. We verify that we +# can read both rbx and ebx correctly for each frame, and that when we write to +# ebx, rbx for that frame is correctly updated. + +if { ![istarget x86_64-*-* ] || ![is_lp64_target] } { + verbose "Skipping amd64 pseudo register unwind." + return +} + +standard_testfile amd64-pseudo-unwind.c amd64-pseudo-unwind-asm.S + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + "${srcfile} ${srcfile2}" {debug}] } { + return -1 +} + +clean_restart ${binfile} + +if ![runto_main] then { + fail "could not run to main" +} + +gdb_breakpoint break_here_asm temporary +gdb_continue_to_breakpoint "continue to callee" + +# Verify the value of rbx/ebx in the inner frame (callee). +with_test_prefix "callee, before change" { + gdb_test "p/x \$rbx" " = 0x2021222324252627" + gdb_test "p/x \$ebx" " = 0x24252627" +} + +# Verify that we can change the value of the pseudo register (ebx) in the inner +# frame (callee). +gdb_test_no_output "set \$ebx = 0x34353637" + +# Verify the value of rbx/ebx in the inner frame (callee) after the change. +with_test_prefix "callee, after change" { + gdb_test "p/x \$rbx" " = 0x2021222334353637" + gdb_test "p/x \$ebx" " = 0x34353637" +} + +# Go up one frame, and do the same. +gdb_test "up" + +# Verify the value of rbx/ebx in the outer frame (caller). +with_test_prefix "caller, before change" { + gdb_test "p/x \$rbx" " = 0x1011121314151617" + gdb_test "p/x \$ebx" " = 0x14151617" +} + +# Verify that we can change the value of the pseudo register (ebx) in the outer +# frame (caller). +gdb_test_no_output "set \$ebx = 0x44454647" + +# Verify the value of rbx/ebx in the outer frame (caller) after the change. +with_test_prefix "caller, after change" { + gdb_test "p/x \$rbx" " = 0x1011121344454647" + gdb_test "p/x \$ebx" " = 0x44454647" +} + +# Go back to frame 0 (callee), check that the change to the outer frame didn't +# mess up anything there. +gdb_test "down" +with_test_prefix "callee, after change in caller" { + gdb_test "p/x \$rbx" " = 0x2021222334353637" + gdb_test "p/x \$ebx" " = 0x34353637" +} + +# Verify that the value of the saved rbx we changed is correctly seen by the +# inferior. +gdb_breakpoint break_here_c temporary +gdb_continue_to_breakpoint "continue to break_here_c" +gdb_test "p/x value" " = 0x1011121344454647" diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind-asm.S b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-asm.S new file mode 100644 index 000000000000..0e5ad1b9bee1 --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-asm.S @@ -0,0 +1,79 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +.section .note.GNU-stack,"",%progbits + +.data +value_callee: +.quad 0x2021222324252627 +value_caller: +.quad 0x1011121314151617 + +.text +.arm +.global callee +callee: + /* Standard prologue. */ +.cfi_startproc + push {fp, lr} +.cfi_def_cfa fp, 4 +.cfi_offset fp, -8 +.cfi_offset lr, -4 + add fp, sp, #4 + + /* Save caller's d8 value on the stack. */ +.cfi_offset d8, -16 + vpush {d8} + + /* Put our own d8 value. */ + ldr r0, =value_callee + vldr d8, [r0] +break_here_asm: + + /* Restore caller's d8 value. */ + vpop {d8} + + /* Standard epilogue. */ + pop {fp, pc} +.cfi_endproc + + +.global caller +caller: + /* Standard prologue. */ +.cfi_startproc + push {fp, lr} +.cfi_def_cfa fp, 4 +.cfi_offset fp, -8 +.cfi_offset lr, -4 + add fp, sp, #4 + + /* Put our own d8 value. */ + ldr r0, =value_caller + vldr d8, [r0] + + /* Call callee. */ + bl callee + + /* Store our d8 value in r0-r1 to return it. */ + vpush {d8} + pop {r0} + pop {r1} + + /* Standard epilogue. */ + pop {fp, pc} +.cfi_endproc diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy-asm.S b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy-asm.S new file mode 100644 index 000000000000..786e79a0543e --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy-asm.S @@ -0,0 +1,84 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* The difference between this and arm-pseudo-unwind is that here, the CFI + directives use the obsolete DWARF number for the s16 register (a + pseudo-register in GDB), whereas arm-pseudo-unwind uses the number for the d8 + register (the underlying raw register for s16). */ + +.section .note.GNU-stack,"",%progbits + +.data +value_callee: +.quad 0x20212223 +value_caller: +.quad 0x10111213 + +.text +.arm +.global callee +callee: +.cfi_startproc + /* Standard prologue. */ + push {fp, lr} +.cfi_def_cfa fp, 4 +.cfi_offset fp, -8 +.cfi_offset lr, -4 + add fp, sp, #4 + + /* Save caller's s16 value on the stack. */ +.cfi_offset 80, -12 + vpush {s16} + + /* Put our own s16 value. */ + ldr r0, =value_callee + vldr s16, [r0] +break_here_asm: + + /* Restore caller's s16 value. */ + vpop {s16} + + /* Standard epilogue. */ + pop {fp, pc} +.cfi_endproc + + +.global caller +caller: +.cfi_startproc + /* Standard prologue. */ + push {fp, lr} +.cfi_def_cfa fp, 4 +.cfi_offset fp, -8 +.cfi_offset lr, -4 + add fp, sp, #4 + + /* Put our own s16 value. */ + ldr r0, =value_caller + vldr s16, [r0] + + /* Call callee. */ + bl callee + + /* Store our s16 value in r0-r1 to return it. */ + vpush {s16} + pop {r0} + mov r1, #0 + + /* Standard epilogue. */ + pop {fp, pc} +.cfi_endproc diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c new file mode 100644 index 000000000000..d18876fe3be3 --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c @@ -0,0 +1,33 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +uint64_t caller (void); + +static void +break_here_c (uint64_t value) +{ +} + +int +main (void) +{ + uint64_t value = caller (); + break_here_c (value); + return 0; +} diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp new file mode 100644 index 000000000000..c3d0979799dc --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp @@ -0,0 +1,86 @@ +# Copyright 2018-2023 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This test is in the same vein as amd64-pseudo-unwind, making sure we can +# read write pseudo registers in outer frames. However, it tests a special +# case where the debug info includes unwind information for a pseudo register +# but not the underlying raw register. This can happen for the pseudo register +# s16, which is the bottom half of the raw register d8. +# +# See "DWARF for the ARM architecture": +# https://github.com/ARM-software/abi-aa/releases/download/2023Q3/aadwarf32.pdf + +if { ![istarget arm*-*-* ] } { + verbose "Skipping arm pseudo register unwind." + return +} + +standard_testfile arm-pseudo-unwind-legacy.c arm-pseudo-unwind-legacy-asm.S + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + "${srcfile} ${srcfile2}" {debug additional_flags=-marm}] } { + return -1 +} + +clean_restart ${binfile} + +if ![runto_main] then { + fail "could not run to main" +} + +gdb_breakpoint break_here_asm temporary +gdb_continue_to_breakpoint "continue to callee" + +# Verify the value of s16 in the inner frame (callee). +with_test_prefix "callee, before change" { + gdb_test "p/x \$s16" " = 0x20212223" +} + +# Verify that we can change the value of s16 in the inner frame (callee). +gdb_test_no_output "set \$s16 = 1.0" + +# Verify the value of s16 in the inner frame (callee) after the change. +with_test_prefix "callee, after change" { + gdb_test "p/x \$s16" " = 0x3f800000" +} + +# Go up one frame, and do the same. +gdb_test "up" + +# Verify the value of s16 in the outer frame (caller). +with_test_prefix "caller, before change" { + gdb_test "p/x \$s16" " = 0x10111213" +} + +# Verify that we can change the value of s16 in the outer frame (caller). +gdb_test_no_output "set \$s16 = 2.0" + +# Verify the value of s16 in the outer frame (caller) after the change. +with_test_prefix "caller, after change" { + gdb_test "p/x \$s16" " = 0x40000000" +} + +# Go back to frame 0 (callee), check that the change to the outer frame didn't +# mess up anything there. +gdb_test "down" +with_test_prefix "callee, after change in caller" { + gdb_test "p/x \$s16" " = 0x3f800000" +} + +# Verify that the value of the saved s16 we changed is correctly seen by the +# inferior. +gdb_breakpoint break_here_c temporary +gdb_continue_to_breakpoint "continue to break_here_c" +gdb_test "p/x value" " = 0x40000000" diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind.c b/gdb/testsuite/gdb.arch/arm-pseudo-unwind.c new file mode 100644 index 000000000000..d18876fe3be3 --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind.c @@ -0,0 +1,33 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +uint64_t caller (void); + +static void +break_here_c (uint64_t value) +{ +} + +int +main (void) +{ + uint64_t value = caller (); + break_here_c (value); + return 0; +} diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp b/gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp new file mode 100644 index 000000000000..bfe81b7d5f21 --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp @@ -0,0 +1,88 @@ +# Copyright 2018-2023 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This test is equivalent to amd64-pseudo-unwind, but specific to ARM. We +# use the raw register d8 which is 64 bits long. We use pseudo register s16, +# which is the low 32 bits of d8. + +if { ![istarget arm*-*-* ] } { + verbose "Skipping arm pseudo register unwind." + return +} + +standard_testfile arm-pseudo-unwind.c arm-pseudo-unwind-asm.S + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + "${srcfile} ${srcfile2}" {debug additional_flags=-marm}] } { + return -1 +} + +clean_restart ${binfile} + +if ![runto_main] then { + fail "could not run to main" +} + +gdb_breakpoint break_here_asm temporary +gdb_continue_to_breakpoint "continue to callee" + +# Verify the value of d8/s16 in the inner frame (callee). +with_test_prefix "callee, before change" { + gdb_test "p/x \$d8" " = 0x2021222324252627" + gdb_test "p/x \$s16" " = 0x24252627" +} + +# Verify that we can change the value of the pseudo register (s16) in the inner +# frame (callee). +gdb_test_no_output "set \$s16 = 1.0" + +# Verify the value of d8/s16 in the inner frame (callee) after the change. +with_test_prefix "callee, after change" { + gdb_test "p/x \$d8" " = 0x202122233f800000" + gdb_test "p/x \$s16" " = 0x3f800000" +} + +# Go up one frame (to caller), and do the same. +gdb_test "up" + +# Verify the value of d8/s16 in the outer frame (caller). +with_test_prefix "caller, before change" { + gdb_test "p/x \$d8" " = 0x1011121314151617" + gdb_test "p/x \$s16" " = 0x14151617" +} + +# Verify that we can change the value of the pseudo register (s16) in the outer +# frame (caller). +gdb_test_no_output "set \$s16 = 2.0" + +# Verify the value of d8/s16 in the outer frame (caller) after the change. +with_test_prefix "caller, after change" { + gdb_test "p/x \$d8" " = 0x1011121340000000" + gdb_test "p/x \$s16" " = 0x40000000" +} + +# Go back to frame 0 (callee), check that the change to the outer frame didn't +# mess up anything there. +gdb_test "down" +with_test_prefix "callee, after change in caller" { + gdb_test "p/x \$d8" " = 0x202122233f800000" + gdb_test "p/x \$s16" " = 0x3f800000" +} + +# Verify that the value of the saved d8 we changed is correctly seen by the +# inferior. +gdb_breakpoint break_here_c temporary +gdb_continue_to_breakpoint "continue to break_here_c" +gdb_test "p/x value" " = 0x1011121340000000"