gdb: Implement the init_reg dwarf2_frame_ops for amd64
Djordje
djordje.todorovic@syrmia.com
Mon Nov 8 12:20:29 GMT 2021
Hi,
Please consider these two files:
$ cat test2.c
void f1(int);
int f2();
void f3();
void f() {
f1(0);
int local = f2();
f1(local);
f3();
}
$ cat main-for-core.c
#include <stdio.h>
void f1(int param) {
if (param % 2 == 0)
return;
printf("HELLO\n");
abort();
}
int f2() {
int x;
scanf("%d", &x);
return x;
}
void f3() {
int y;
scanf("%d", &y);
printf("%d\n", y);
}
int main() {
f();
return 0;
}
Compilation of the files:
$ clang -g -O2 test2.c -c -o object-file-test2.o
$ clang -g -O2 main-for-core.c object-file-test2.o -o main-for-core
By examining debug_loc from object-file-test2.o for the `local` var we see:
00000000 000000000000000f 0000000000000016 (DW_OP_reg0 (rax))
And the code for the f() is:
0000000000000000 <f>:
0: push %rax
1: xor %edi,%edi
3: callq 8 <f+0x8>
8: xor %eax,%eax
a: callq f <f+0xf>
f: mov %eax,%edi
11: callq 16 <f+0x16>
16: xor %eax,%eax
18: pop %rcx
19: jmpq 1e <f+0x1e>
While debugging it, by loading the core file generated due to abort() (as an input I typed 5):
$ gdb main-for-core
...
(gdb) bt
#0 0x00007fb2d7aeb377 in raise () from /lib64/libc.so.6
#1 0x00007fb2d7aeca68 in abort () from /lib64/libc.so.6
#2 0x0000000000401197 in f1 (param=<optimized out>) at main-for-core.c:7
#3 0x0000000000401216 in f () at test2.c:8
#4 0x00000000004011f8 in main () at main-for-core.c:23
(gdb) f 3
#3 0x0000000000401216 in f () at test2.c:8
8 f1(local);
(gdb) disassemble
Dump of assembler code for function f:
0x0000000000401200 <+0>: push %rax
0x0000000000401201 <+1>: xor %edi,%edi
0x0000000000401203 <+3>: callq 0x401180 <f1>
0x0000000000401208 <+8>: xor %eax,%eax
0x000000000040120a <+10>: callq 0x4011a0 <f2>
0x000000000040120f <+15>: mov %eax,%edi
0x0000000000401211 <+17>: callq 0x401180 <f1>
=> 0x0000000000401216 <+22>: xor %eax,%eax
0x0000000000401218 <+24>: pop %rcx
0x0000000000401219 <+25>: jmpq 0x4011c0 <f3>
End of assembler dump.
(gdb) p local
$1 = 0
But it should be reported as <optimized_out>, because the %eax was clobbered by the call.
GCC produces different high pc address to keep GDB working properly:
00000000 000000000000000f 0000000000000015 (DW_OP_reg0 (rax))
This patch fixes the problem inside GDB itself for X86_64 target.
Bug: https://bugs.llvm.org/show_bug.cgi?id=49641
---
gdb/amd64-tdep.c | 37 +++++++++++++
gdb/frame.c | 9 +++-
.../gdb.arch/amd64-invalid-stack-middle.exp | 8 +--
gdb/testsuite/gdb.arch/amd64-not-saved-regs.c | 28 ++++++++++
.../gdb.arch/amd64-not-saved-regs.exp | 52 +++++++++++++++++++
gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp | 4 +-
.../gdb.dwarf2/dw2-reg-undefined.exp | 8 +--
gdb/testsuite/gdb.mi/mi-reg-undefined.exp | 4 +-
8 files changed, 136 insertions(+), 14 deletions(-)
create mode 100644 gdb/testsuite/gdb.arch/amd64-not-saved-regs.c
create mode 100644 gdb/testsuite/gdb.arch/amd64-not-saved-regs.exp
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 47761208088..a4ac36b18be 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -25,6 +25,8 @@
#include "arch-utils.h"
#include "block.h"
#include "dummy-frame.h"
+#include "dwarf2.h"
+#include "dwarf2/frame.h"
#include "frame.h"
#include "frame-base.h"
#include "frame-unwind.h"
@@ -3101,6 +3103,38 @@ amd64_in_indirect_branch_thunk (struct gdbarch *gdbarch, CORE_ADDR pc)
AMD64_RIP_REGNUM);
}
+/* Implement the "init_reg" dwarf2_frame_ops method. */
+
+static void
+amd64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+ struct dwarf2_frame_state_reg *reg,
+ struct frame_info *this_frame)
+{
+ switch (regnum)
+ {
+ case AMD64_RIP_REGNUM:
+ reg->how = DWARF2_FRAME_REG_FN;
+ return;
+
+ case AMD64_RSP_REGNUM:
+ reg->how = DWARF2_FRAME_REG_CFA;
+ return;
+
+ /* Caller-saved registers. */
+ case AMD64_RAX_REGNUM:
+ case AMD64_RDI_REGNUM:
+ case AMD64_RSI_REGNUM:
+ case AMD64_RDX_REGNUM:
+ case AMD64_RCX_REGNUM:
+ case AMD64_R8_REGNUM:
+ case AMD64_R9_REGNUM:
+ case AMD64_R10_REGNUM:
+ case AMD64_R11_REGNUM:
+ reg->how = DWARF2_FRAME_REG_UNDEFINED;
+ return;
+ }
+}
+
void
amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch,
const target_desc *default_tdesc)
@@ -3215,6 +3249,9 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch,
set_gdbarch_stab_reg_to_regnum (gdbarch, amd64_dwarf_reg_to_regnum);
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, amd64_dwarf_reg_to_regnum);
+ /* Frame handling. */
+ dwarf2_frame_set_init_reg (gdbarch, amd64_dwarf2_frame_init_reg);
+
/* We don't override SDB_REG_RO_REGNUM, since COFF doesn't seem to
be in use on any of the supported AMD64 targets. */
diff --git a/gdb/frame.c b/gdb/frame.c
index 16673258373..a5b43c3f949 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2312,9 +2312,14 @@ get_prev_frame_always (struct frame_info *this_frame)
}
catch (const gdb_exception_error &ex)
{
- if (ex.error == MEMORY_ERROR)
+ if (ex.error == MEMORY_ERROR || ex.error == GENERIC_ERROR)
{
- this_frame->stop_reason = UNWIND_MEMORY_ERROR;
+ if (ex.error == MEMORY_ERROR)
+ this_frame->stop_reason = UNWIND_MEMORY_ERROR;
+ else
+ /* This is for the GENERIC_ERROR case. */
+ this_frame->stop_reason = UNWIND_UNAVAILABLE;
+
if (ex.message != NULL)
{
char *stop_string;
diff --git a/gdb/testsuite/gdb.arch/amd64-invalid-stack-middle.exp b/gdb/testsuite/gdb.arch/amd64-invalid-stack-middle.exp
index f9e590d83bb..6ae1c9c1322 100644
--- a/gdb/testsuite/gdb.arch/amd64-invalid-stack-middle.exp
+++ b/gdb/testsuite/gdb.arch/amd64-invalid-stack-middle.exp
@@ -42,11 +42,11 @@ if ![runto breakpt] {
return -1
}
-gdb_test "bt" "^bt\r\n#0 +breakpt *\\(\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in func5\[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in func4\[^\r\n\]*\r\n#3 +0x\[0-9a-f\]+ in func3\[^\r\n\]*\r\nBacktrace stopped: Cannot access memory at address 0x\[0-9a-f\]+" \
- "first backtrace, with error message"
+gdb_test "bt" "^bt\r\n#0 +breakpt *\\(\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in func5\[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in func4\[^\r\n\]*\r\n#3 +0x\[0-9a-f\]+ in func3\[^\r\n\]*\r\nBacktrace stopped: value has been optimized out" \
+ "first backtrace, with error message"
-gdb_test "bt" "^bt\r\n#0 +breakpt *\\(\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in func5\[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in func4\[^\r\n\]*\r\n#3 +0x\[0-9a-f\]+ in func3\[^\r\n\]*\r\nBacktrace stopped: Cannot access memory at address 0x\[0-9a-f\]+" \
- "second backtrace, with error message"
+gdb_test "bt" "^bt\r\n#0 +breakpt *\\(\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in func5\[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in func4\[^\r\n\]*\r\n#3 +0x\[0-9a-f\]+ in func3\[^\r\n\]*\r\nBacktrace stopped: value has been optimized out" \
+ "second backtrace, with error message"
clean_restart ${binfile}
diff --git a/gdb/testsuite/gdb.arch/amd64-not-saved-regs.c b/gdb/testsuite/gdb.arch/amd64-not-saved-regs.c
new file mode 100644
index 00000000000..5698e549f00
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-not-saved-regs.c
@@ -0,0 +1,28 @@
+/* This test program is part of GDB, the GNU debugger.
+
+ Copyright 2019-2021 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 <http://www.gnu.org/licenses/>. */
+
+int
+foo (int a)
+{
+ return a; /* break here. */
+}
+
+int
+main ()
+{
+ return foo (5);
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-not-saved-regs.exp b/gdb/testsuite/gdb.arch/amd64-not-saved-regs.exp
new file mode 100644
index 00000000000..07b870b5d30
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-not-saved-regs.exp
@@ -0,0 +1,52 @@
+# Copyright 2010-2021 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 <http://www.gnu.org/licenses/>.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@gnu.org
+
+# This file is part of the gdb testsuite.
+
+if { ![istarget x86_64-*-* ]} {
+ verbose "Skipping ${gdb_test_file_name}."
+ return
+}
+
+# Build program with debug symbols.
+standard_testfile
+set compile_flags {debug}
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} ${compile_flags}] } {
+ return -1
+}
+
+if ![runto_main] {
+ untested "could not run to main"
+ return -1
+}
+
+gdb_breakpoint [ gdb_get_line_number "break here" ]
+gdb_continue_to_breakpoint "break here" ".*break here.*"
+
+# Switch to frame 1.
+gdb_test "frame 1" "#1.*in main ().*"
+
+gdb_test "info registers rax" "rax .* <not saved>"
+gdb_test "info registers rcx" "rcx .* <not saved>"
+gdb_test "info registers rdx" "rdx .* <not saved>"
+gdb_test "info registers rsi" "rsi .* <not saved>"
+gdb_test "info registers rdi" "rdi .* <not saved>"
+gdb_test "info registers r8" "r8 .* <not saved>"
+gdb_test "info registers r9" "r9 .* <not saved>"
+gdb_test "info registers r10" "r10 .* <not saved>"
+gdb_test "info registers r11" "r11 .* <not saved>"
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
index 238830e711e..70f22cb9efe 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
@@ -50,11 +50,11 @@ gdb_test "bt" "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?int_param_single_
# (2) struct_param_single_reg_loc
gdb_continue_to_breakpoint "Stop in breakpt for struct_param_single_reg_loc"
-gdb_test "bt" "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?struct_param_single_reg_loc \\(operand0={a = 0xdeadbe00deadbe01, b = <optimized out>}, operand1={a = <optimized out>, b = 0xdeadbe04deadbe05}, operand2=<optimized out>\\)\r\n#2 ($hex in )?main \\(\\)" "backtrace for test struct_param_single_reg_loc"
+gdb_test "bt" "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?struct_param_single_reg_loc \\(operand0={a = 0xdeadbe00deadbe01, b = <optimized out>}, operand1=<optimized out>, operand2=<optimized out>\\)\r\n#2 ($hex in )?main \\(\\)" "backtrace for test struct_param_single_reg_loc"
# (3) struct_param_two_reg_pieces
gdb_continue_to_breakpoint "Stop in breakpt for struct_param_two_reg_pieces"
-gdb_test "bt" "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?struct_param_two_reg_pieces \\(operand0={a = 0xdeadbe04deadbe05, b = <optimized out>}, operand1={a = <optimized out>, b = 0xdeadbe00deadbe01}, operand2=<optimized out>\\)\r\n#2 ($hex in )?main \\(\\)" "backtrace for test struct_param_two_reg_pieces"
+gdb_test "bt" "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?struct_param_two_reg_pieces \\(operand0=<optimized out>, operand1={a = <optimized out>, b = 0xdeadbe00deadbe01}, operand2=<optimized out>\\)\r\n#2 ($hex in )?main \\(\\)" "backtrace for test struct_param_two_reg_pieces"
# (4) int_param_two_reg_pieces
gdb_continue_to_breakpoint "Stop in breakpt for int_param_two_reg_pieces"
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp b/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp
index b1c28b2f41c..2b296c8d445 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp
@@ -47,8 +47,8 @@ for {set f 0} {$f < 3} {incr f} {
} else {
set pattern_rax_rbx_rcx_print "<not saved>"
set pattern_rax_rbx_rcx_info "<not saved>"
- set pattern_r8_r9_print "$hex"
- set pattern_r8_r9_info "$hex\\s+$decimal"
+ set pattern_r8_r9_print "<not saved>"
+ set pattern_r8_r9_info "<not saved>"
}
# Select frame.
@@ -79,8 +79,8 @@ for {set f 0} {$f < 3} {incr f} {
# "not saved" and not "optimized out".
gdb_test "set debug frame 1"
gdb_test {print $rax} [multi_line \
- { \[frame\] frame_unwind_register_value: frame=0, regnum=0\(rax\)} \
- { \[frame\] frame_unwind_register_value: -> <not saved>} \
+ { \[frame\] frame_unwind_register_value: frame=1, regnum=0\(rax\)} \
+ { \[frame\] frame_unwind_register_value: -> <not saved>} \
{.*}]
gdb_test "set debug frame 0"
diff --git a/gdb/testsuite/gdb.mi/mi-reg-undefined.exp b/gdb/testsuite/gdb.mi/mi-reg-undefined.exp
index f38e20003a3..3f193b1379b 100644
--- a/gdb/testsuite/gdb.mi/mi-reg-undefined.exp
+++ b/gdb/testsuite/gdb.mi/mi-reg-undefined.exp
@@ -62,10 +62,10 @@ for {set f 0} {$f < 3} {incr f} {
}
mi_gdb_test "22${f}-data-list-register-values --thread 1 --frame ${f} x 0 1 2 8 9" \
- "22${f}\\^done,register-values=\\\[\{number=\"0\",value=\"${pattern_0_1_2}\"\},\{number=\"1\",value=\"${pattern_0_1_2}\"\},\{number=\"2\",value=\"${pattern_0_1_2}\"\},\{number=\"8\",value=\"$hex\"\},\{number=\"9\",value=\"$hex\"\}\\\]" \
+ "22${f}\\^done,register-values=\\\[\{number=\"0\",value=\"${pattern_0_1_2}\"\},\{number=\"1\",value=\"${pattern_0_1_2}\"\},\{number=\"2\",value=\"${pattern_0_1_2}\"\},\{number=\"8\",value=\"${pattern_0_1_2}\"\},\{number=\"9\",value=\"${pattern_0_1_2}\"\}\\\]" \
"register values, format x, frame ${f}"
mi_gdb_test "33${f}-data-list-register-values --thread 1 --frame ${f} r 0 1 2 8 9" \
- "33${f}\\^done,register-values=\\\[\{number=\"0\",value=\"${pattern_0_1_2}\"\},\{number=\"1\",value=\"${pattern_0_1_2}\"\},\{number=\"2\",value=\"${pattern_0_1_2}\"\},\{number=\"8\",value=\"$hex\"\},\{number=\"9\",value=\"$hex\"\}\\\]" \
+ "33${f}\\^done,register-values=\\\[\{number=\"0\",value=\"${pattern_0_1_2}\"\},\{number=\"1\",value=\"${pattern_0_1_2}\"\},\{number=\"2\",value=\"${pattern_0_1_2}\"\},\{number=\"8\",value=\"${pattern_0_1_2}\"\},\{number=\"9\",value=\"${pattern_0_1_2}\"\}\\\]" \
"register values, format r, frame ${f}"
}
--
2.25.1
More information about the Gdb-patches
mailing list