[gdb][Arm]: gdb cannot step across CMSE secure entry function code.
authorSrinath Parvathaneni <srinath.parvathaneni@arm.com>
Tue, 23 Jul 2019 10:21:11 +0000 (11:21 +0100)
committerAlan Hayward <alan.hayward@arm.com>
Tue, 23 Jul 2019 11:06:05 +0000 (12:06 +0100)
commit40eadf04ff1f0eaec82dc911cf079555cdbb03d0
tree518b1243e229bed00187f5c6ce3f1d3764932bf8
parent8c728a9d93e2342c57039fcdd6e4a502875b9e09
[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.
gdb/ChangeLog
gdb/arm-tdep.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.arch/arm-cmse-sgstubs.c [new file with mode: 0644]
gdb/testsuite/gdb.arch/arm-cmse-sgstubs.exp [new file with mode: 0644]