diff options
author | Srinath Parvathaneni <srinath.parvathaneni@arm.com> | 2019-07-23 11:21:11 +0100 |
---|---|---|
committer | Alan Hayward <alan.hayward@arm.com> | 2019-07-23 12:06:05 +0100 |
commit | 40eadf04ff1f0eaec82dc911cf079555cdbb03d0 (patch) | |
tree | 518b1243e229bed00187f5c6ce3f1d3764932bf8 /gdb/testsuite | |
parent | 8c728a9d93e2342c57039fcdd6e4a502875b9e09 (diff) | |
download | gdb-40eadf04ff1f0eaec82dc911cf079555cdbb03d0.zip gdb-40eadf04ff1f0eaec82dc911cf079555cdbb03d0.tar.gz gdb-40eadf04ff1f0eaec82dc911cf079555cdbb03d0.tar.bz2 |
[gdb][Arm]: gdb cannot step across CMSE secure entry function code.
GDB is not able to execute "step" command on function calls of Armv8-M cmse secure entry functions.
Everytime GNU linker come across definition of any cmse secure entry function in object file(s),
it creates two new instructions secure gateway (sg) and original branch destination (b.w),
place those two instructions in ".gnu.sgstubs" section of executable.
Any function calls to these cmse secure entry functions is re-directed through secure gateway (sg)
present in ".gnu.sgstubs" section.
Example:
Following is a function call to cmse secure entry function "foo":
...
bl xxxx <foo> --->(a)
...
<foo>
xxxx: push {r7, lr}
GNU linker on finding out "foo" is a cmse secure entry function, created sg and b.w instructions and
place them in ".gnu.sgstubs" section (marked by c).
The "bl" instruction (marked by a) which is a call to cmse secure entry function is modified by GNU linker
(as marked by b) and call flow is re-directly through secure gateway (sg) in ".gnu.sgstubs" section.
...
bl yyyy <foo> ---> (b)
...
section .gnu.sgstubs: ---> (c)
yyyy <foo>
yyyy: sg // secure gateway
b.w xxxx <__acle_se_foo> // original_branch_dest
...
0000xxxx <__acle_se_foo>
xxxx: push {r7, lr} ---> (d)
On invoking GDB, when the control is at "b" and we pass "step" command, the pc returns "yyyy"
(sg address) which is a trampoline and which does not exist in source code. So GDB jumps
to next line without jumping to "__acle_se_foo" (marked by d).
The above details are published on the Arm website [1], please refer to section 5.4 (Entry functions)
and section 3.4.4 (C level development flow of secure code).
[1] https://developer.arm.com/architectures/cpu-architecture/m-profile/docs/ecm0359818/latest/armv8-m-security-extensions-requirements-on-development-tools-engineering-specification
This patch fixes above problem by returning target pc "xxxx" to GDB on executing "step"
command at "b", so that the control jumps to "__acle_se_foo" (marked by d).
gdb/ChangeLog:
* arm-tdep.c (arm_skip_cmse_entry): New function.
(arm_is_sgstubs_section): New function.
(arm_skip_stub): Add call to arm_skip_cmse_entry function.
gdb/testsuite/ChangeLog:
* gdb.arch/arm-cmse-sgstubs.c: New test.
* gdb.arch/arm-cmse-sgstubs.exp: New file.
Diffstat (limited to 'gdb/testsuite')
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/arm-cmse-sgstubs.c | 50 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/arm-cmse-sgstubs.exp | 50 |
3 files changed, 105 insertions, 0 deletions
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 2f9c79a..00096c0 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-23 Srinath Parvathaneni <srinath.parvathaneni@arm.com> + + * gdb.arch/arm-cmse-sgstubs.c: New test. + * gdb.arch/arm-cmse-sgstubs.exp: New file. + 2019-07-23 Tom de Vries <tdevries@suse.de> PR testsuite/24711 diff --git a/gdb/testsuite/gdb.arch/arm-cmse-sgstubs.c b/gdb/testsuite/gdb.arch/arm-cmse-sgstubs.c new file mode 100644 index 0000000..3ac8e6e --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-cmse-sgstubs.c @@ -0,0 +1,50 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2019 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/>. */ + +#include <stdio.h> +extern void func (); +void +__acle_se_func () +{ + printf ("__acle_se_func\n"); +} + +/* The following code is written using asm so that the instructions in function + * "func" will be placed in .gnu.sgstubs section of the executable. */ +asm ("\t.section .gnu.sgstubs,\"ax\",%progbits\n" + "\t.global func\n" + "\t.type func, %function\n" + "func:\n" + "\tnop @sg\n" + "\tb __acle_se_func @b.w"); + +void +fun1 () +{ + printf ("In fun1\n"); +} + +int +main (void) +{ + func (); + fun1 (); + __acle_se_func (); + func (); + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/arm-cmse-sgstubs.exp b/gdb/testsuite/gdb.arch/arm-cmse-sgstubs.exp new file mode 100644 index 0000000..42a265c --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-cmse-sgstubs.exp @@ -0,0 +1,50 @@ +# Copyright 2019 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/>. + +# This file is part of the gdb testsuite. + +if { ![istarget "arm*-*-*"]} { + return 1 +} + +standard_testfile +if { [prepare_for_testing "failed to prepare" $testfile $srcfile ]} { + return -1 +} + +if ![runto_main] { + untested "could not run to main" + return -1 +} + +gdb_test "si" "0x.*" "branch to func from main" + +gdb_test "ni" "0x.*" "next instruction in func" + +gdb_test "ni" "__acle_se_func ().*" "branch to __acle_se_func from func" + +gdb_test "next" "23 .*" "next in __acle_se_func function" + +gdb_test "next" "__acle_se_func.*" "next in __acle_se_func function outputs __acle_se_func" + +gdb_test "next" "main ().*" "next in __acle_se_func function controls returns to main" + +gdb_test "next" "In fun1.*" "next in main outputs In fun1" + +gdb_test "next" "__acle_se_func.*" "next in main outputs __acle_se_func" + +gdb_test "step" "__acle_se_func ().*" "control jumps to __acle_se_func from main via func" + +gdb_test "next" "__acle_se_func.*" "next in __acle_se_func function via func" |