gdb: handle endbr64 instruction in amd64_analyze_prologue
v2:
- test: build full executable instead of object
- test: add and use supports_fcf_protection
- test: use gdb_test_multiple's -wrap option
- test: don't execute gdb_assert if failed to get breakpoint address
Some GCCs now enable -fcf-protection by default. This is the case, for
example, with GCC 9.3.0 on Ubuntu 20.04. Enabling it causes the
`endbr64` instruction to be inserted at the beginning of all functions
and that breaks GDB's prologue analysis.
I noticed this because it gives many failures in gdb.base/break.exp.
But let's take this dummy program and put a breakpoint on main:
int main(void)
{
return 0;
}
Without -fcf-protection, the breakpoint is correctly put after the prologue:
$ gcc test.c -g3 -O0 -fcf-protection=none
$ ./gdb -q -nx --data-directory=data-directory a.out
Reading symbols from a.out...
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000001129 <+0>: push %rbp
0x000000000000112a <+1>: mov %rsp,%rbp
0x000000000000112d <+4>: mov $0x0,%eax
0x0000000000001132 <+9>: pop %rbp
0x0000000000001133 <+10>: retq
End of assembler dump.
(gdb) b main
Breakpoint 1 at 0x112d: file test.c, line 3.
With -fcf-protection, the breakpoint is incorrectly put on the first
byte of the function:
$ gcc test.c -g3 -O0 -fcf-protection=full
$ ./gdb -q -nx --data-directory=data-directory a.out
Reading symbols from a.out...
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000001129 <+0>: endbr64
0x000000000000112d <+4>: push %rbp
0x000000000000112e <+5>: mov %rsp,%rbp
0x0000000000001131 <+8>: mov $0x0,%eax
0x0000000000001136 <+13>: pop %rbp
0x0000000000001137 <+14>: retq
End of assembler dump.
(gdb) b main
Breakpoint 1 at 0x1129: file test.c, line 2.
Stepping in amd64_skip_prologue, we can see that the prologue analysis,
for GCC-compiled programs, is done in amd64_analyze_prologue by decoding
the instructions and looking for typical patterns. This patch changes
the analysis to check for a prologue starting with the `endbr64`
instruction, and skip it if it's there.
gdb/ChangeLog:
* amd64-tdep.c (amd64_analyze_prologue): Check for `endbr64`
instruction, skip it if it's there.
gdb/testsuite/ChangeLog:
* gdb.arch/amd64-prologue-skip-cf-protection.exp: New file.
* gdb.arch/amd64-prologue-skip-cf-protection.c: New file.