This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH] AArch64: Detect exit from execve syscall
- From: Pedro Alves <palves at redhat dot com>
- To: Alan Hayward <Alan dot Hayward at arm dot com>, "gdb-patches at sourceware dot org" <gdb-patches at sourceware dot org>
- Cc: nd <nd at arm dot com>
- Date: Thu, 7 Feb 2019 17:40:44 +0000
- Subject: Re: [PATCH] AArch64: Detect exit from execve syscall
- References: <20190122111457.6589-1-alan.hayward@arm.com> <E8C550D6-523E-4115-9648-009CBD865B3F@arm.com>
LGTM.
Thanks,
Pedro Alves
On 01/31/2019 10:12 AM, Alan Hayward wrote:
> Ping.
>
>> On 22 Jan 2019, at 11:15, Alan Hayward <Alan.Hayward@arm.com> wrote:
>>
>> Checking the syscall number when stopped on entry/exit relies on checking
>> the value in register X8.
>>
>> However, on exit from an execve syscall, the registers will all be cleared.
>> Given this is only checked on syscall entry/exit, then a cleared register
>> state either means execve exit or syscall 0 (io_setup) entry with invalid
>> parameters and an invalid FR and LR, which in reality should never happen.
>> Use this to detect execve exit.
>>
>> Move function to allow use of aarch64_sys_execve enum, and use newer
>> regcache functions.
>>
>> Fixes gdb.base/catch-syscall.exp on Aarch64.
>>
>> gdb/ChangeLog:
>>
>> 2019-01-22 Alan Hayward <alan.hayward@arm.com>
>>
>> * aarch64-linux-tdep.c (aarch64_linux_get_syscall_number): Check
>> for execve.
>> ---
>> gdb/aarch64-linux-tdep.c | 56 ++++++++++++++++++++++++----------------
>> 1 file changed, 34 insertions(+), 22 deletions(-)
>>
>> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
>> index 62cfc76c82..39e607658f 100644
>> --- a/gdb/aarch64-linux-tdep.c
>> +++ b/gdb/aarch64-linux-tdep.c
>> @@ -757,28 +757,6 @@ aarch64_stap_parse_special_token (struct gdbarch *gdbarch,
>> return 1;
>> }
>>
>> -/* Implement the "get_syscall_number" gdbarch method. */
>> -
>> -static LONGEST
>> -aarch64_linux_get_syscall_number (struct gdbarch *gdbarch,
>> - thread_info *thread)
>> -{
>> - struct regcache *regs = get_thread_regcache (thread);
>> - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
>> -
>> - /* The content of register x8. */
>> - gdb_byte buf[X_REGISTER_SIZE];
>> - /* The result. */
>> - LONGEST ret;
>> -
>> - /* Getting the system call number from the register x8. */
>> - regs->cooked_read (AARCH64_DWARF_X0 + 8, buf);
>> -
>> - ret = extract_signed_integer (buf, X_REGISTER_SIZE, byte_order);
>> -
>> - return ret;
>> -}
>> -
>> /* AArch64 process record-replay constructs: syscall, signal etc. */
>>
>> struct linux_record_tdep aarch64_linux_record_tdep;
>> @@ -1334,6 +1312,40 @@ aarch64_canonicalize_syscall (enum aarch64_syscall syscall_number)
>> }
>> }
>>
>> +/* Retrieve the syscall number at a ptrace syscall-stop, either on syscall entry
>> + or exit. Return -1 upon error. */
>> +
>> +static LONGEST
>> +aarch64_linux_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread)
>> +{
>> + struct regcache *regs = get_thread_regcache (thread);
>> + LONGEST ret;
>> +
>> + /* Get the system call number from register x8. */
>> + regs->cooked_read (AARCH64_X0_REGNUM + 8, &ret);
>> +
>> + /* On exit from a successful execve, we will be in a new process and all the
>> + registers will be cleared - x0 to x30 will be 0, except for a 1 in x7.
>> + This function will only ever get called when stopped at the entry or exit
>> + of a syscall, so by checking for 0 in x0 (arg0/retval), x1 (arg1), x8
>> + (syscall), x29 (FP) and x30 (LR) we can infer:
>> + 1) Either inferior is at exit from sucessful execve.
>> + 2) Or inferior is at entry to a call to io_setup with invalid arguments and
>> + a corrupted FP and LR.
>> + It should be safe enough to assume case 1. */
>> + if (ret == 0)
>> + {
>> + LONGEST x1 = -1, fp = -1, lr = -1;
>> + regs->cooked_read (AARCH64_X0_REGNUM + 1, &x1);
>> + regs->cooked_read (AARCH64_FP_REGNUM, &fp);
>> + regs->cooked_read (AARCH64_LR_REGNUM, &lr);
>> + if (x1 == 0 && fp ==0 && lr == 0)
>> + return aarch64_sys_execve;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> /* Record all registers but PC register for process-record. */
>>
>> static int
>> --
>> 2.17.2 (Apple Git-113)
>>
>