From patchwork Tue May 19 13:22:30 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 48742 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f71.google.com (mail-la0-f71.google.com [209.85.215.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 68ED9214BA for ; Tue, 19 May 2015 13:23:21 +0000 (UTC) Received: by lagv1 with SMTP id v1sf5902861lag.1 for ; Tue, 19 May 2015 06:23:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:mailing-list :precedence:list-id:list-unsubscribe:list-subscribe:list-archive :list-post:list-help:sender:delivered-to:from:to:subject:date :message-id:in-reply-to:references:x-original-sender :x-original-authentication-results; bh=sWRrMiltywfhoqFWzInqnpcgJ3oKZJV1uyRM8o4qtp0=; b=cQe93F7J6eZ/j5K8zYAT6a753FWsY2wEluKdKqxmFvqfaLlh/Yt0oluRsCB+9BeTXG GV79KIwPdnpBDZIyuUO89mp1v5K+x9inQUkOqlH9sHdfEDsdqKNCeh7FSTYKVrTjgL9w h8Pa8EtNjYUlszSAVQu3t8djSDzSRrhg/Ble2QNEaPCZTj3KMfPZsOWQ5qfwLvAeSWu3 HPe4BcHBPpJiG5K2/F6nAomZ16qJT1AFgKLM9tXm28WIsjDnmZWbHX+6H8D8jQxxoG89 WNYnz54XCxfeE0WwLwKQ/C6uig2IJIWZkl1VlS6JxD8iM/uGTM8Jw8RtIXxztijwxYC5 xU5w== X-Gm-Message-State: ALoCoQkaJrUmVXd3Dgd/gi0tEaPsPcI8fOWsuytxhgkhfBvvzVduYE7Bl3v6gQBZ1vkPGiM9WdZ3 X-Received: by 10.112.93.203 with SMTP id cw11mr21936085lbb.0.1432041799178; Tue, 19 May 2015 06:23:19 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.204.103 with SMTP id kx7ls59171lac.62.gmail; Tue, 19 May 2015 06:23:19 -0700 (PDT) X-Received: by 10.152.21.5 with SMTP id r5mr12108631lae.24.1432041799024; Tue, 19 May 2015 06:23:19 -0700 (PDT) Received: from mail-la0-x22e.google.com (mail-la0-x22e.google.com. [2a00:1450:4010:c03::22e]) by mx.google.com with ESMTPS id sa9si8947318lbb.132.2015.05.19.06.23.18 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 19 May 2015 06:23:18 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2a00:1450:4010:c03::22e as permitted sender) client-ip=2a00:1450:4010:c03::22e; Received: by lagr1 with SMTP id r1so23757195lag.0 for ; Tue, 19 May 2015 06:23:18 -0700 (PDT) X-Received: by 10.152.2.227 with SMTP id 3mr21659996lax.73.1432041797213; Tue, 19 May 2015 06:23:17 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.108.230 with SMTP id hn6csp804145lbb; Tue, 19 May 2015 06:23:14 -0700 (PDT) X-Received: by 10.70.129.172 with SMTP id nx12mr54016856pdb.157.1432041793941; Tue, 19 May 2015 06:23:13 -0700 (PDT) Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id ot4si21190311pbb.88.2015.05.19.06.23.12 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 19 May 2015 06:23:13 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-return-123009-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Received: (qmail 128539 invoked by alias); 19 May 2015 13:22:59 -0000 Mailing-List: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org Precedence: list List-Id: List-Unsubscribe: , List-Subscribe: List-Archive: List-Post: , List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 128461 invoked by uid 89); 19 May 2015 13:22:58 -0000 X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.3 required=5.0 tests=AWL, BAYES_50, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pd0-f179.google.com Received: from mail-pd0-f179.google.com (HELO mail-pd0-f179.google.com) (209.85.192.179) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Tue, 19 May 2015 13:22:46 +0000 Received: by pdea3 with SMTP id a3so25309211pde.2 for ; Tue, 19 May 2015 06:22:44 -0700 (PDT) X-Received: by 10.68.235.38 with SMTP id uj6mr21158127pbc.57.1432041764555; Tue, 19 May 2015 06:22:44 -0700 (PDT) Received: from E107787-LIN.cambridge.arm.com (gcc1-power7.osuosl.org. [140.211.15.137]) by mx.google.com with ESMTPSA id v7sm13157386pde.81.2015.05.19.06.22.41 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 19 May 2015 06:22:43 -0700 (PDT) From: Yao Qi To: gdb-patches@sourceware.org Subject: [PATCH 2/4] Implements aarch64 process record and reverse debugging support Date: Tue, 19 May 2015 14:22:30 +0100 Message-Id: <1432041752-4638-3-git-send-email-yao.qi@linaro.org> In-Reply-To: <1432041752-4638-1-git-send-email-yao.qi@linaro.org> References: <1432041752-4638-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes X-Original-Sender: qiyaoltc@gmail.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2a00:1450:4010:c03::22e as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org; dkim=pass header.i=@sourceware.org; dmarc=fail (p=NONE dis=NONE) header.from=gmail.com X-Google-Group-Id: 836684582541 From: Omair Javaid This patch adds the support of aarch64-linux process record and reverse debugging. The implementation is similar to ARM's counterpart. 2015-06-19 Omair Javaid Yao Qi * aarch64-linux-tdep.c: Include linux-record.h and record-full.h. (struct linux_record_tdep aarch64_linux_record_tdep): Declare. (aarch64_syscall): New enum. (aarch64_canonicalize_syscall): New function. (aarch64_all_but_pc_registers_record): New function. (aarch64_linux_syscall_record): New function. (aarch64_linux_init_abi): Install AArch64 process record handler. Update to handle syscall recording. * aarch64-tdep.c: Include record.h and record-full.h. (submask, bit, bits, REG_ALLOC, MEM_ALLOC): New macros. (struct aarch64_mem_r): Define. (aarch64_record_result): New enum. (struct insn_decode_record): Define. (insn_decode_record): New typedef. (aarch64_record_data_proc_reg): New function. (aarch64_record_data_proc_imm): New function. (aarch64_record_branch_except_sys): New function. (aarch64_record_load_store): New function. (aarch64_record_data_proc_simd_fp): New function. (aarch64_record_asimd_load_store): New function. (aarch64_record_decode_insn_handler): New function. (deallocate_reg_mem): New function. (aarch64_process_record): New function. * aarch64-tdep.h (struct gdbarch_tdep) : New field. (aarch64_process_record): New extern declaration. * configure.tgt: Add linux-record.o to gdb_target_obs. * linux-record.h (struct linux_record_tdep): Add two more syscall argument fields. --- gdb/aarch64-linux-tdep.c | 739 ++++++++++++++++++++++++++++++++++++ gdb/aarch64-tdep.c | 967 +++++++++++++++++++++++++++++++++++++++++++++++ gdb/aarch64-tdep.h | 6 + gdb/configure.tgt | 2 +- gdb/linux-record.h | 1 + 5 files changed, 1714 insertions(+), 1 deletion(-) diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index 0ee5ecb..2f93846 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -42,6 +42,9 @@ #include "xml-syscall.h" #include +#include "record-full.h" +#include "linux-record.h" + /* Signal frame handling. +------------+ ^ @@ -364,6 +367,576 @@ aarch64_linux_get_syscall_number (struct gdbarch *gdbarch, return ret; } +/* AArch64 process record-replay constructs: syscall, signal etc. */ + +struct linux_record_tdep aarch64_linux_record_tdep; + +/* Enum that defines the AArch64 linux specific syscall identifiers used for + process record/replay. */ + +enum aarch64_syscall { + aarch64_sys_io_setup = 0, + aarch64_sys_io_destroy = 1, + aarch64_sys_io_submit = 2, + aarch64_sys_io_cancel = 3, + aarch64_sys_io_getevents = 4, + aarch64_sys_setxattr = 5, + aarch64_sys_lsetxattr = 6, + aarch64_sys_fsetxattr = 7, + aarch64_sys_getxattr = 8, + aarch64_sys_lgetxattr = 9, + aarch64_sys_fgetxattr = 10, + aarch64_sys_listxattr = 11, + aarch64_sys_llistxattr = 12, + aarch64_sys_flistxattr = 13, + aarch64_sys_removexattr = 14, + aarch64_sys_lremovexattr = 15, + aarch64_sys_fremovexattr = 16, + aarch64_sys_getcwd = 17, + aarch64_sys_lookup_dcookie = 18, + aarch64_sys_eventfd2 = 19, + aarch64_sys_epoll_create1 = 20, + aarch64_sys_epoll_ctl = 21, + aarch64_sys_epoll_pwait = 22, + aarch64_sys_dup = 23, + aarch64_sys_dup3 = 24, + aarch64_sys_fcntl = 25, + aarch64_sys_inotify_init1 = 26, + aarch64_sys_inotify_add_watch = 27, + aarch64_sys_inotify_rm_watch = 28, + aarch64_sys_ioctl = 29, + aarch64_sys_ioprio_set = 30, + aarch64_sys_ioprio_get = 31, + aarch64_sys_flock = 32, + aarch64_sys_mknod = 33, + aarch64_sys_mkdir = 34, + aarch64_sys_unlink = 35, + aarch64_sys_symlink = 36, + aarch64_sys_link = 37, + aarch64_sys_rename = 38, + aarch64_sys_umount2 = 39, + aarch64_sys_mount = 40, + aarch64_sys_pivot_root = 41, + aarch64_sys_nfsservctl = 42, + aarch64_sys_statfs = 43, + aarch64_sys_fstatfs = 44, + aarch64_sys_truncate = 45, + aarch64_sys_ftruncate = 46, + aarch64_sys_fallocate = 47, + aarch64_sys_faccess = 48, + aarch64_sys_chdir = 49, + aarch64_sys_fchdir = 50, + aarch64_sys_chroot = 51, + aarch64_sys_fchmod = 52, + aarch64_sys_fchmodat = 53, + aarch64_sys_fchownat = 54, + aarch64_sys_fchown = 55, + aarch64_sys_open = 56, + aarch64_sys_close = 57, + aarch64_sys_vhangup = 58, + aarch64_sys_pipe2 = 59, + aarch64_sys_quotactl = 60, + aarch64_sys_getdents64 = 61, + aarch64_sys_lseek = 62, + aarch64_sys_read = 63, + aarch64_sys_write = 64, + aarch64_sys_readv = 65, + aarch64_sys_writev = 66, + aarch64_sys_pread64 = 67, + aarch64_sys_pwrite64 = 68, + aarch64_sys_preadv = 69, + aarch64_sys_pwritev = 70, + aarch64_sys_sendfile = 71, + aarch64_sys_pselect6 = 72, + aarch64_sys_ppoll = 73, + aarch64_sys_signalfd4 = 74, + aarch64_sys_vmsplice = 75, + aarch64_sys_splice = 76, + aarch64_sys_tee = 77, + aarch64_sys_readlink = 78, + aarch64_sys_fstatat = 79, + aarch64_sys_fstat = 80, + aarch64_sys_sync = 81, + aarch64_sys_fsync = 82, + aarch64_sys_fdatasync = 83, + aarch64_sys_sync_file_range2 = 84, + aarch64_sys_sync_file_range = 84, + aarch64_sys_timerfd_create = 85, + aarch64_sys_timerfd_settime = 86, + aarch64_sys_timerfd_gettime = 87, + aarch64_sys_utimensat = 88, + aarch64_sys_acct = 89, + aarch64_sys_capget = 90, + aarch64_sys_capset = 91, + aarch64_sys_personality = 92, + aarch64_sys_exit = 93, + aarch64_sys_exit_group = 94, + aarch64_sys_waitid = 95, + aarch64_sys_set_tid_address = 96, + aarch64_sys_unshare = 97, + aarch64_sys_futex = 98, + aarch64_sys_set_robust_list = 99, + aarch64_sys_get_robust_list = 100, + aarch64_sys_nanosleep = 101, + aarch64_sys_getitimer = 102, + aarch64_sys_setitimer = 103, + aarch64_sys_kexec_load = 104, + aarch64_sys_init_module = 105, + aarch64_sys_delete_module = 106, + aarch64_sys_timer_create = 107, + aarch64_sys_timer_gettime = 108, + aarch64_sys_timer_getoverrun = 109, + aarch64_sys_timer_settime = 110, + aarch64_sys_timer_delete = 111, + aarch64_sys_clock_settime = 112, + aarch64_sys_clock_gettime = 113, + aarch64_sys_clock_getres = 114, + aarch64_sys_clock_nanosleep = 115, + aarch64_sys_syslog = 116, + aarch64_sys_ptrace = 117, + aarch64_sys_sched_setparam = 118, + aarch64_sys_sched_setscheduler = 119, + aarch64_sys_sched_getscheduler = 120, + aarch64_sys_sched_getparam = 121, + aarch64_sys_sched_setaffinity = 122, + aarch64_sys_sched_getaffinity = 123, + aarch64_sys_sched_yield = 124, + aarch64_sys_sched_get_priority_max = 125, + aarch64_sys_sched_get_priority_min = 126, + aarch64_sys_sched_rr_get_interval = 127, + aarch64_sys_kill = 129, + aarch64_sys_tkill = 130, + aarch64_sys_tgkill = 131, + aarch64_sys_sigaltstack = 132, + aarch64_sys_rt_sigsuspend = 133, + aarch64_sys_rt_sigaction = 134, + aarch64_sys_rt_sigprocmask = 135, + aarch64_sys_rt_sigpending = 136, + aarch64_sys_rt_sigtimedwait = 137, + aarch64_sys_rt_sigqueueinfo = 138, + aarch64_sys_rt_sigreturn = 139, + aarch64_sys_setpriority = 140, + aarch64_sys_getpriority = 141, + aarch64_sys_reboot = 142, + aarch64_sys_setregid = 143, + aarch64_sys_setgid = 144, + aarch64_sys_setreuid = 145, + aarch64_sys_setuid = 146, + aarch64_sys_setresuid = 147, + aarch64_sys_getresuid = 148, + aarch64_sys_setresgid = 149, + aarch64_sys_getresgid = 150, + aarch64_sys_setfsuid = 151, + aarch64_sys_setfsgid = 152, + aarch64_sys_times = 153, + aarch64_sys_setpgid = 154, + aarch64_sys_getpgid = 155, + aarch64_sys_getsid = 156, + aarch64_sys_setsid = 157, + aarch64_sys_getgroups = 158, + aarch64_sys_setgroups = 159, + aarch64_sys_uname = 160, + aarch64_sys_sethostname = 161, + aarch64_sys_setdomainname = 162, + aarch64_sys_getrlimit = 163, + aarch64_sys_setrlimit = 164, + aarch64_sys_getrusage = 165, + aarch64_sys_umask = 166, + aarch64_sys_prctl = 167, + aarch64_sys_getcpu = 168, + aarch64_sys_gettimeofday = 169, + aarch64_sys_settimeofday = 170, + aarch64_sys_adjtimex = 171, + aarch64_sys_getpid = 172, + aarch64_sys_getppid = 173, + aarch64_sys_getuid = 174, + aarch64_sys_geteuid = 175, + aarch64_sys_getgid = 176, + aarch64_sys_getegid = 177, + aarch64_sys_gettid = 178, + aarch64_sys_sysinfo = 179, + aarch64_sys_mq_open = 180, + aarch64_sys_mq_unlink = 181, + aarch64_sys_mq_timedsend = 182, + aarch64_sys_mq_timedreceive = 183, + aarch64_sys_mq_notify = 184, + aarch64_sys_mq_getsetattr = 185, + aarch64_sys_msgget = 186, + aarch64_sys_msgctl = 187, + aarch64_sys_msgrcv = 188, + aarch64_sys_msgsnd = 189, + aarch64_sys_semget = 190, + aarch64_sys_semctl = 191, + aarch64_sys_semtimedop = 192, + aarch64_sys_semop = 193, + aarch64_sys_shmget = 194, + aarch64_sys_shmctl = 195, + aarch64_sys_shmat = 196, + aarch64_sys_shmdt = 197, + aarch64_sys_socket = 198, + aarch64_sys_socketpair = 199, + aarch64_sys_bind = 200, + aarch64_sys_listen = 201, + aarch64_sys_accept = 202, + aarch64_sys_connect = 203, + aarch64_sys_getsockname = 204, + aarch64_sys_getpeername = 205, + aarch64_sys_sendto = 206, + aarch64_sys_recvfrom = 207, + aarch64_sys_setsockopt = 208, + aarch64_sys_getsockopt = 209, + aarch64_sys_shutdown = 210, + aarch64_sys_sendmsg = 211, + aarch64_sys_recvmsg = 212, + aarch64_sys_readahead = 213, + aarch64_sys_brk = 214, + aarch64_sys_munmap = 215, + aarch64_sys_mremap = 216, + aarch64_sys_add_key = 217, + aarch64_sys_request_key = 218, + aarch64_sys_keyctl = 219, + aarch64_sys_clone = 220, + aarch64_sys_execve = 221, + aarch64_sys_mmap = 222, + aarch64_sys_fadvise64 = 223, + aarch64_sys_swapon = 224, + aarch64_sys_swapoff = 225, + aarch64_sys_mprotect = 226, + aarch64_sys_msync = 227, + aarch64_sys_mlock = 228, + aarch64_sys_munlock = 229, + aarch64_sys_mlockall = 230, + aarch64_sys_munlockall = 231, + aarch64_sys_mincore = 232, + aarch64_sys_madvise = 233, + aarch64_sys_remap_file_pages = 234, + aarch64_sys_mbind = 235, + aarch64_sys_get_mempolicy = 236, + aarch64_sys_set_mempolicy = 237, + aarch64_sys_migrate_pages = 238, + aarch64_sys_move_pages = 239, + aarch64_sys_rt_tgsigqueueinfo = 240, + aarch64_sys_perf_event_open = 241, + aarch64_sys_accept4 = 242, + aarch64_sys_recvmmsg = 243, + aarch64_sys_wait4 = 260, + aarch64_sys_prlimit64 = 261, + aarch64_sys_fanotify_init = 262, + aarch64_sys_fanotify_mark = 263, + aarch64_sys_name_to_handle_at = 264, + aarch64_sys_open_by_handle_at = 265, + aarch64_sys_clock_adjtime = 266, + aarch64_sys_syncfs = 267, + aarch64_sys_setns = 268, + aarch64_sys_sendmmsg = 269, + aarch64_sys_process_vm_readv = 270, + aarch64_sys_process_vm_writev = 271, + aarch64_sys_kcmp = 272, + aarch64_sys_finit_module = 273, + aarch64_sys_sched_setattr = 274, + aarch64_sys_sched_getattr = 275, +}; + +/* aarch64_canonicalize_syscall maps syscall ids from the native AArch64 + linux set of syscall ids into a canonical set of syscall ids used by + process record. */ + +static enum gdb_syscall +aarch64_canonicalize_syscall (enum aarch64_syscall syscall_number) +{ +#define SYSCALL_MAP(SYSCALL) case aarch64_sys_##SYSCALL: \ + return gdb_sys_##SYSCALL + + switch (syscall_number) + { + SYSCALL_MAP (io_setup); + SYSCALL_MAP (io_destroy); + SYSCALL_MAP (io_submit); + SYSCALL_MAP (io_cancel); + SYSCALL_MAP (io_getevents); + + SYSCALL_MAP (setxattr); + SYSCALL_MAP (lsetxattr); + SYSCALL_MAP (fsetxattr); + SYSCALL_MAP (getxattr); + SYSCALL_MAP (lgetxattr); + SYSCALL_MAP (fgetxattr); + SYSCALL_MAP (listxattr); + SYSCALL_MAP (llistxattr); + SYSCALL_MAP (flistxattr); + SYSCALL_MAP (removexattr); + SYSCALL_MAP (lremovexattr); + SYSCALL_MAP (fremovexattr); + SYSCALL_MAP (getcwd); + SYSCALL_MAP (lookup_dcookie); + + case aarch64_sys_epoll_create1: + return gdb_sys_epoll_create; + + SYSCALL_MAP (epoll_ctl); + SYSCALL_MAP (epoll_pwait); + SYSCALL_MAP (dup); + SYSCALL_MAP (fcntl); + SYSCALL_MAP (inotify_add_watch); + SYSCALL_MAP (inotify_rm_watch); + SYSCALL_MAP (ioctl); + SYSCALL_MAP (ioprio_set); + SYSCALL_MAP (ioprio_get); + SYSCALL_MAP (flock); + SYSCALL_MAP (mount); + SYSCALL_MAP (nfsservctl); + SYSCALL_MAP (statfs); + SYSCALL_MAP (truncate); + SYSCALL_MAP (ftruncate); + SYSCALL_MAP (fchdir); + SYSCALL_MAP (chroot); + SYSCALL_MAP (fchmod); + SYSCALL_MAP (fchmodat); + SYSCALL_MAP (fchownat); + SYSCALL_MAP (fchown); + SYSCALL_MAP (close); + SYSCALL_MAP (vhangup); + SYSCALL_MAP (quotactl); + SYSCALL_MAP (getdents64); + SYSCALL_MAP (lseek); + SYSCALL_MAP (read); + SYSCALL_MAP (write); + SYSCALL_MAP (readv); + SYSCALL_MAP (writev); + SYSCALL_MAP (pread64); + SYSCALL_MAP (pwrite64); + SYSCALL_MAP (sendfile); + SYSCALL_MAP (pselect6); + SYSCALL_MAP (ppoll); + SYSCALL_MAP (vmsplice); + SYSCALL_MAP (splice); + SYSCALL_MAP (tee); + SYSCALL_MAP (fstat); + SYSCALL_MAP (sync); + SYSCALL_MAP (fsync); + SYSCALL_MAP (fdatasync); + SYSCALL_MAP (sync_file_range); + SYSCALL_MAP (acct); + SYSCALL_MAP (capget); + SYSCALL_MAP (capset); + SYSCALL_MAP (personality); + SYSCALL_MAP (exit); + SYSCALL_MAP (exit_group); + SYSCALL_MAP (waitid); + SYSCALL_MAP (set_tid_address); + SYSCALL_MAP (unshare); + SYSCALL_MAP (futex); + SYSCALL_MAP (set_robust_list); + SYSCALL_MAP (get_robust_list); + SYSCALL_MAP (nanosleep); + + SYSCALL_MAP (getitimer); + SYSCALL_MAP (setitimer); + SYSCALL_MAP (kexec_load); + SYSCALL_MAP (init_module); + SYSCALL_MAP (delete_module); + SYSCALL_MAP (timer_create); + SYSCALL_MAP (timer_settime); + SYSCALL_MAP (timer_gettime); + SYSCALL_MAP (timer_getoverrun); + SYSCALL_MAP (timer_delete); + SYSCALL_MAP (clock_settime); + SYSCALL_MAP (clock_gettime); + SYSCALL_MAP (clock_getres); + SYSCALL_MAP (clock_nanosleep); + SYSCALL_MAP (syslog); + SYSCALL_MAP (ptrace); + SYSCALL_MAP (sched_setparam); + SYSCALL_MAP (sched_setscheduler); + SYSCALL_MAP (sched_getscheduler); + SYSCALL_MAP (sched_getparam); + SYSCALL_MAP (sched_setaffinity); + SYSCALL_MAP (sched_getaffinity); + SYSCALL_MAP (sched_yield); + SYSCALL_MAP (sched_get_priority_max); + SYSCALL_MAP (sched_get_priority_min); + SYSCALL_MAP (sched_rr_get_interval); + SYSCALL_MAP (kill); + SYSCALL_MAP (tkill); + SYSCALL_MAP (tgkill); + SYSCALL_MAP (sigaltstack); + SYSCALL_MAP (rt_sigsuspend); + SYSCALL_MAP (rt_sigaction); + SYSCALL_MAP (rt_sigprocmask); + SYSCALL_MAP (rt_sigpending); + SYSCALL_MAP (rt_sigtimedwait); + SYSCALL_MAP (rt_sigqueueinfo); + SYSCALL_MAP (rt_sigreturn); + SYSCALL_MAP (setpriority); + SYSCALL_MAP (getpriority); + SYSCALL_MAP (reboot); + SYSCALL_MAP (setregid); + SYSCALL_MAP (setgid); + SYSCALL_MAP (setreuid); + SYSCALL_MAP (setuid); + SYSCALL_MAP (setresuid); + SYSCALL_MAP (getresuid); + SYSCALL_MAP (setresgid); + SYSCALL_MAP (getresgid); + SYSCALL_MAP (setfsuid); + SYSCALL_MAP (setfsgid); + SYSCALL_MAP (times); + SYSCALL_MAP (setpgid); + SYSCALL_MAP (getpgid); + SYSCALL_MAP (getsid); + SYSCALL_MAP (setsid); + SYSCALL_MAP (getgroups); + SYSCALL_MAP (setgroups); + SYSCALL_MAP (uname); + SYSCALL_MAP (sethostname); + SYSCALL_MAP (setdomainname); + SYSCALL_MAP (getrlimit); + SYSCALL_MAP (setrlimit); + SYSCALL_MAP (getrusage); + SYSCALL_MAP (umask); + SYSCALL_MAP (prctl); + SYSCALL_MAP (gettimeofday); + SYSCALL_MAP (settimeofday); + SYSCALL_MAP (adjtimex); + SYSCALL_MAP (getpid); + SYSCALL_MAP (getppid); + SYSCALL_MAP (getuid); + SYSCALL_MAP (geteuid); + SYSCALL_MAP (getgid); + SYSCALL_MAP (getegid); + SYSCALL_MAP (gettid); + SYSCALL_MAP (sysinfo); + SYSCALL_MAP (mq_open); + SYSCALL_MAP (mq_unlink); + SYSCALL_MAP (mq_timedsend); + SYSCALL_MAP (mq_timedreceive); + SYSCALL_MAP (mq_notify); + SYSCALL_MAP (mq_getsetattr); + SYSCALL_MAP (msgget); + SYSCALL_MAP (msgctl); + SYSCALL_MAP (msgrcv); + SYSCALL_MAP (msgsnd); + SYSCALL_MAP (semget); + SYSCALL_MAP (semctl); + SYSCALL_MAP (semtimedop); + SYSCALL_MAP (semop); + SYSCALL_MAP (shmget); + SYSCALL_MAP (shmctl); + SYSCALL_MAP (shmat); + SYSCALL_MAP (shmdt); + SYSCALL_MAP (socket); + SYSCALL_MAP (socketpair); + SYSCALL_MAP (bind); + SYSCALL_MAP (listen); + SYSCALL_MAP (accept); + SYSCALL_MAP (connect); + SYSCALL_MAP (getsockname); + SYSCALL_MAP (getpeername); + SYSCALL_MAP (sendto); + SYSCALL_MAP (recvfrom); + SYSCALL_MAP (setsockopt); + SYSCALL_MAP (getsockopt); + SYSCALL_MAP (shutdown); + SYSCALL_MAP (sendmsg); + SYSCALL_MAP (recvmsg); + SYSCALL_MAP (readahead); + SYSCALL_MAP (brk); + SYSCALL_MAP (munmap); + SYSCALL_MAP (mremap); + SYSCALL_MAP (add_key); + SYSCALL_MAP (request_key); + SYSCALL_MAP (keyctl); + SYSCALL_MAP (clone); + SYSCALL_MAP (execve); + + case aarch64_sys_mmap: + return gdb_sys_mmap2; + + SYSCALL_MAP (fadvise64); + SYSCALL_MAP (swapon); + SYSCALL_MAP (swapoff); + SYSCALL_MAP (mprotect); + SYSCALL_MAP (msync); + SYSCALL_MAP (mlock); + SYSCALL_MAP (munlock); + SYSCALL_MAP (mlockall); + SYSCALL_MAP (munlockall); + SYSCALL_MAP (mincore); + SYSCALL_MAP (madvise); + SYSCALL_MAP (remap_file_pages); + SYSCALL_MAP (mbind); + SYSCALL_MAP (get_mempolicy); + SYSCALL_MAP (set_mempolicy); + SYSCALL_MAP (migrate_pages); + SYSCALL_MAP (move_pages); + + default: + return -1; + } +} + +/* Record all registers but PC register for process-record. */ + +static int +aarch64_all_but_pc_registers_record (struct regcache *regcache) +{ + int i; + + for (i = AARCH64_X0_REGNUM; i < AARCH64_PC_REGNUM; i++) + if (record_full_arch_list_add_reg (regcache, i)) + return -1; + + if (record_full_arch_list_add_reg (regcache, AARCH64_CPSR_REGNUM)) + return -1; + + return 0; +} + +/* Handler for aarch64 system call instruction recording. */ + +static int +aarch64_linux_syscall_record (struct regcache *regcache, + unsigned long svc_number) +{ + int ret = 0; + enum gdb_syscall syscall_gdb; + + syscall_gdb = aarch64_canonicalize_syscall (svc_number); + + if (syscall_gdb < 0) + { + printf_unfiltered (_("Process record and replay target doesn't " + "support syscall number %s\n"), + plongest (svc_number)); + return -1; + } + + if (syscall_gdb == gdb_sys_sigreturn + || syscall_gdb == gdb_sys_rt_sigreturn) + { + if (aarch64_all_but_pc_registers_record (regcache)) + return -1; + return 0; + } + + ret = record_linux_system_call (syscall_gdb, regcache, + &aarch64_linux_record_tdep); + if (ret != 0) + return ret; + + /* Record the return value of the system call. */ + if (record_full_arch_list_add_reg (regcache, AARCH64_X0_REGNUM)) + return -1; + /* Record LR. */ + if (record_full_arch_list_add_reg (regcache, AARCH64_LR_REGNUM)) + return -1; + /* Record CPSR. */ + if (record_full_arch_list_add_reg (regcache, AARCH64_CPSR_REGNUM)) + return -1; + + return 0; +} + static void aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -409,6 +982,172 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_stap_parse_special_token (gdbarch, aarch64_stap_parse_special_token); + /* Reversible debugging, process record. */ + set_gdbarch_process_record (gdbarch, aarch64_process_record); + /* Syscall record. */ + tdep->aarch64_syscall_record = aarch64_linux_syscall_record; + + /* Initialize the aarch64_linux_record_tdep. */ + /* These values are the size of the type that will be used in a system + call. They are obtained from Linux Kernel source. */ + aarch64_linux_record_tdep.size_pointer + = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; + aarch64_linux_record_tdep.size__old_kernel_stat = 32; + aarch64_linux_record_tdep.size_tms = 32; + aarch64_linux_record_tdep.size_loff_t = 8; + aarch64_linux_record_tdep.size_flock = 32; + aarch64_linux_record_tdep.size_oldold_utsname = 45; + aarch64_linux_record_tdep.size_ustat = 32; + aarch64_linux_record_tdep.size_old_sigaction = 152; + aarch64_linux_record_tdep.size_old_sigset_t = 128; + aarch64_linux_record_tdep.size_rlimit = 16; + aarch64_linux_record_tdep.size_rusage = 144; + aarch64_linux_record_tdep.size_timeval = 16; + aarch64_linux_record_tdep.size_timezone = 8; + aarch64_linux_record_tdep.size_old_gid_t = 2; + aarch64_linux_record_tdep.size_old_uid_t = 2; + aarch64_linux_record_tdep.size_fd_set = 128; + aarch64_linux_record_tdep.size_dirent = 280; + aarch64_linux_record_tdep.size_dirent64 = 280; + aarch64_linux_record_tdep.size_statfs = 120; + aarch64_linux_record_tdep.size_statfs64 = 120; + aarch64_linux_record_tdep.size_sockaddr = 16; + aarch64_linux_record_tdep.size_int + = gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT; + aarch64_linux_record_tdep.size_long + = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT; + aarch64_linux_record_tdep.size_ulong + = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT; + aarch64_linux_record_tdep.size_msghdr = 56; + aarch64_linux_record_tdep.size_itimerval = 32; + aarch64_linux_record_tdep.size_stat = 144; + aarch64_linux_record_tdep.size_old_utsname = 325; + aarch64_linux_record_tdep.size_sysinfo = 112; + aarch64_linux_record_tdep.size_msqid_ds = 120; + aarch64_linux_record_tdep.size_shmid_ds = 112; + aarch64_linux_record_tdep.size_new_utsname = 390; + aarch64_linux_record_tdep.size_timex = 208; + aarch64_linux_record_tdep.size_mem_dqinfo = 24; + aarch64_linux_record_tdep.size_if_dqblk = 72; + aarch64_linux_record_tdep.size_fs_quota_stat = 80; + aarch64_linux_record_tdep.size_timespec = 16; + aarch64_linux_record_tdep.size_pollfd = 8; + aarch64_linux_record_tdep.size_NFS_FHSIZE = 32; + aarch64_linux_record_tdep.size_knfsd_fh = 132; + aarch64_linux_record_tdep.size_TASK_COMM_LEN = 16; + aarch64_linux_record_tdep.size_sigaction = 152; + aarch64_linux_record_tdep.size_sigset_t = 128; + aarch64_linux_record_tdep.size_siginfo_t = 128; + aarch64_linux_record_tdep.size_cap_user_data_t = 8; + aarch64_linux_record_tdep.size_stack_t = 24; + aarch64_linux_record_tdep.size_off_t = 8; + aarch64_linux_record_tdep.size_stat64 = 144; + aarch64_linux_record_tdep.size_gid_t = 4; + aarch64_linux_record_tdep.size_uid_t = 4; + aarch64_linux_record_tdep.size_PAGE_SIZE = 4096; + aarch64_linux_record_tdep.size_flock64 = 32; + aarch64_linux_record_tdep.size_user_desc = 16; + aarch64_linux_record_tdep.size_io_event = 32; + aarch64_linux_record_tdep.size_iocb = 64; + aarch64_linux_record_tdep.size_epoll_event = 12; + aarch64_linux_record_tdep.size_itimerspec = 32; + aarch64_linux_record_tdep.size_mq_attr = 64; + aarch64_linux_record_tdep.size_siginfo = 128; + aarch64_linux_record_tdep.size_termios = 60; + aarch64_linux_record_tdep.size_termios2 = 44; + aarch64_linux_record_tdep.size_pid_t = 4; + aarch64_linux_record_tdep.size_winsize = 8; + aarch64_linux_record_tdep.size_serial_struct = 72; + aarch64_linux_record_tdep.size_serial_icounter_struct = 80; + aarch64_linux_record_tdep.size_hayes_esp_config = 12; + aarch64_linux_record_tdep.size_size_t = 8; + aarch64_linux_record_tdep.size_iovec = 16; + + /* These values are the second argument of system call "sys_ioctl". + They are obtained from Linux Kernel source. */ + aarch64_linux_record_tdep.ioctl_TCGETS = 0x5401; + aarch64_linux_record_tdep.ioctl_TCSETS = 0x5402; + aarch64_linux_record_tdep.ioctl_TCSETSW = 0x5403; + aarch64_linux_record_tdep.ioctl_TCSETSF = 0x5404; + aarch64_linux_record_tdep.ioctl_TCGETA = 0x5405; + aarch64_linux_record_tdep.ioctl_TCSETA = 0x5406; + aarch64_linux_record_tdep.ioctl_TCSETAW = 0x5407; + aarch64_linux_record_tdep.ioctl_TCSETAF = 0x5408; + aarch64_linux_record_tdep.ioctl_TCSBRK = 0x5409; + aarch64_linux_record_tdep.ioctl_TCXONC = 0x540a; + aarch64_linux_record_tdep.ioctl_TCFLSH = 0x540b; + aarch64_linux_record_tdep.ioctl_TIOCEXCL = 0x540c; + aarch64_linux_record_tdep.ioctl_TIOCNXCL = 0x540d; + aarch64_linux_record_tdep.ioctl_TIOCSCTTY = 0x540e; + aarch64_linux_record_tdep.ioctl_TIOCGPGRP = 0x540f; + aarch64_linux_record_tdep.ioctl_TIOCSPGRP = 0x5410; + aarch64_linux_record_tdep.ioctl_TIOCOUTQ = 0x5411; + aarch64_linux_record_tdep.ioctl_TIOCSTI = 0x5412; + aarch64_linux_record_tdep.ioctl_TIOCGWINSZ = 0x5413; + aarch64_linux_record_tdep.ioctl_TIOCSWINSZ = 0x5414; + aarch64_linux_record_tdep.ioctl_TIOCMGET = 0x5415; + aarch64_linux_record_tdep.ioctl_TIOCMBIS = 0x5416; + aarch64_linux_record_tdep.ioctl_TIOCMBIC = 0x5417; + aarch64_linux_record_tdep.ioctl_TIOCMSET = 0x5418; + aarch64_linux_record_tdep.ioctl_TIOCGSOFTCAR = 0x5419; + aarch64_linux_record_tdep.ioctl_TIOCSSOFTCAR = 0x541a; + aarch64_linux_record_tdep.ioctl_FIONREAD = 0x541b; + aarch64_linux_record_tdep.ioctl_TIOCINQ = 0x541b; + aarch64_linux_record_tdep.ioctl_TIOCLINUX = 0x541c; + aarch64_linux_record_tdep.ioctl_TIOCCONS = 0x541d; + aarch64_linux_record_tdep.ioctl_TIOCGSERIAL = 0x541e; + aarch64_linux_record_tdep.ioctl_TIOCSSERIAL = 0x541f; + aarch64_linux_record_tdep.ioctl_TIOCPKT = 0x5420; + aarch64_linux_record_tdep.ioctl_FIONBIO = 0x5421; + aarch64_linux_record_tdep.ioctl_TIOCNOTTY = 0x5422; + aarch64_linux_record_tdep.ioctl_TIOCSETD = 0x5423; + aarch64_linux_record_tdep.ioctl_TIOCGETD = 0x5424; + aarch64_linux_record_tdep.ioctl_TCSBRKP = 0x5425; + aarch64_linux_record_tdep.ioctl_TIOCTTYGSTRUCT = 0x5426; + aarch64_linux_record_tdep.ioctl_TIOCSBRK = 0x5427; + aarch64_linux_record_tdep.ioctl_TIOCCBRK = 0x5428; + aarch64_linux_record_tdep.ioctl_TIOCGSID = 0x5429; + aarch64_linux_record_tdep.ioctl_TCGETS2 = 0x802c542a; + aarch64_linux_record_tdep.ioctl_TCSETS2 = 0x402c542b; + aarch64_linux_record_tdep.ioctl_TCSETSW2 = 0x402c542c; + aarch64_linux_record_tdep.ioctl_TCSETSF2 = 0x402c542d; + aarch64_linux_record_tdep.ioctl_TIOCGPTN = 0x80045430; + aarch64_linux_record_tdep.ioctl_TIOCSPTLCK = 0x40045431; + aarch64_linux_record_tdep.ioctl_FIONCLEX = 0x5450; + aarch64_linux_record_tdep.ioctl_FIOCLEX = 0x5451; + aarch64_linux_record_tdep.ioctl_FIOASYNC = 0x5452; + aarch64_linux_record_tdep.ioctl_TIOCSERCONFIG = 0x5453; + aarch64_linux_record_tdep.ioctl_TIOCSERGWILD = 0x5454; + aarch64_linux_record_tdep.ioctl_TIOCSERSWILD = 0x5455; + aarch64_linux_record_tdep.ioctl_TIOCGLCKTRMIOS = 0x5456; + aarch64_linux_record_tdep.ioctl_TIOCSLCKTRMIOS = 0x5457; + aarch64_linux_record_tdep.ioctl_TIOCSERGSTRUCT = 0x5458; + aarch64_linux_record_tdep.ioctl_TIOCSERGETLSR = 0x5459; + aarch64_linux_record_tdep.ioctl_TIOCSERGETMULTI = 0x545a; + aarch64_linux_record_tdep.ioctl_TIOCSERSETMULTI = 0x545b; + aarch64_linux_record_tdep.ioctl_TIOCMIWAIT = 0x545c; + aarch64_linux_record_tdep.ioctl_TIOCGICOUNT = 0x545d; + aarch64_linux_record_tdep.ioctl_TIOCGHAYESESP = 0x545e; + aarch64_linux_record_tdep.ioctl_TIOCSHAYESESP = 0x545f; + aarch64_linux_record_tdep.ioctl_FIOQSIZE = 0x5460; + + /* These values are the second argument of system call "sys_fcntl" + and "sys_fcntl64". They are obtained from Linux Kernel source. */ + aarch64_linux_record_tdep.fcntl_F_GETLK = 5; + aarch64_linux_record_tdep.fcntl_F_GETLK64 = 12; + aarch64_linux_record_tdep.fcntl_F_SETLK64 = 13; + aarch64_linux_record_tdep.fcntl_F_SETLKW64 = 14; + + /* The AArch64 syscall calling convention: reg x0-x6 for arguments, + reg x8 for syscall number and return value in reg x0. */ + aarch64_linux_record_tdep.arg1 = AARCH64_X0_REGNUM + 0; + aarch64_linux_record_tdep.arg2 = AARCH64_X0_REGNUM + 1; + aarch64_linux_record_tdep.arg3 = AARCH64_X0_REGNUM + 2; + aarch64_linux_record_tdep.arg4 = AARCH64_X0_REGNUM + 3; + aarch64_linux_record_tdep.arg5 = AARCH64_X0_REGNUM + 4; + aarch64_linux_record_tdep.arg6 = AARCH64_X0_REGNUM + 5; + aarch64_linux_record_tdep.arg7 = AARCH64_X0_REGNUM + 6; + /* `catch syscall' */ set_xml_syscall_file_name (gdbarch, "syscalls/aarch64-linux.xml"); set_gdbarch_get_syscall_number (gdbarch, aarch64_linux_get_syscall_number); diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index ddc9022..8597497 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -50,6 +50,9 @@ #include "vec.h" +#include "record.h" +#include "record-full.h" + #include "features/aarch64.c" /* Pseudo register base numbers. */ @@ -2803,3 +2806,967 @@ When on, AArch64 specific debugging is enabled."), show_aarch64_debug, &setdebuglist, &showdebuglist); } + +/* AArch64 process record-replay related structures, defines etc. */ + +#define submask(x) ((1L << ((x) + 1)) - 1) +#define bit(obj,st) (((obj) >> (st)) & 1) +#define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st))) + +#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \ + do \ + { \ + unsigned int reg_len = LENGTH; \ + if (reg_len) \ + { \ + REGS = XNEWVEC (uint32_t, reg_len); \ + memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \ + } \ + } \ + while (0) + +#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \ + do \ + { \ + unsigned int mem_len = LENGTH; \ + if (mem_len) \ + { \ + MEMS = XNEWVEC (struct aarch64_mem_r, mem_len); \ + memcpy(&MEMS->len, &RECORD_BUF[0], \ + sizeof(struct aarch64_mem_r) * LENGTH); \ + } \ + } \ + while (0) + +/* AArch64 record/replay structures and enumerations. */ + +struct aarch64_mem_r +{ + uint64_t len; /* Record length. */ + uint64_t addr; /* Memory address. */ +}; + +enum aarch64_record_result +{ + AARCH64_RECORD_SUCCESS, + AARCH64_RECORD_FAILURE, + AARCH64_RECORD_UNSUPPORTED, + AARCH64_RECORD_UNKNOWN +}; + +typedef struct insn_decode_record_t +{ + struct gdbarch *gdbarch; + struct regcache *regcache; + CORE_ADDR this_addr; /* Address of insn to be recorded. */ + uint32_t aarch64_insn; /* Insn to be recorded. */ + uint32_t mem_rec_count; /* Count of memory records. */ + uint32_t reg_rec_count; /* Count of register records. */ + uint32_t *aarch64_regs; /* Registers to be recorded. */ + struct aarch64_mem_r *aarch64_mems; /* Memory locations to be recorded. */ +} insn_decode_record; + +/* Record handler for data processing - register instructions. */ + +static unsigned int +aarch64_record_data_proc_reg (insn_decode_record *aarch64_insn_r) +{ + uint8_t reg_rd, insn_bits24_27, insn_bits21_23; + uint32_t record_buf[4]; + + reg_rd = bits (aarch64_insn_r->aarch64_insn, 0, 4); + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27); + insn_bits21_23 = bits (aarch64_insn_r->aarch64_insn, 21, 23); + + if (!bit (aarch64_insn_r->aarch64_insn, 28)) + { + uint8_t setflags; + + /* Logical (shifted register). */ + if (insn_bits24_27 == 0x0a) + setflags = (bits (aarch64_insn_r->aarch64_insn, 29, 30) == 0x03); + /* Add/subtract. */ + else if (insn_bits24_27 == 0x0b) + setflags = bit (aarch64_insn_r->aarch64_insn, 29); + else + return AARCH64_RECORD_UNKNOWN; + + record_buf[0] = reg_rd; + aarch64_insn_r->reg_rec_count = 1; + if (setflags) + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM; + } + else + { + if (insn_bits24_27 == 0x0b) + { + /* Data-processing (3 source). */ + record_buf[0] = reg_rd; + aarch64_insn_r->reg_rec_count = 1; + } + else if (insn_bits24_27 == 0x0a) + { + if (insn_bits21_23 == 0x00) + { + /* Add/subtract (with carry). */ + record_buf[0] = reg_rd; + aarch64_insn_r->reg_rec_count = 1; + if (bit (aarch64_insn_r->aarch64_insn, 29)) + { + record_buf[1] = AARCH64_CPSR_REGNUM; + aarch64_insn_r->reg_rec_count = 2; + } + } + else if (insn_bits21_23 == 0x02) + { + /* Conditional compare (register) and conditional compare + (immediate) instructions. */ + record_buf[0] = AARCH64_CPSR_REGNUM; + aarch64_insn_r->reg_rec_count = 1; + } + else if (insn_bits21_23 == 0x04 || insn_bits21_23 == 0x06) + { + /* CConditional select. */ + /* Data-processing (2 source). */ + /* Data-processing (1 source). */ + record_buf[0] = reg_rd; + aarch64_insn_r->reg_rec_count = 1; + } + else + return AARCH64_RECORD_UNKNOWN; + } + } + + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count, + record_buf); + return AARCH64_RECORD_SUCCESS; +} + +/* Record handler for data processing - immediate instructions. */ + +static unsigned int +aarch64_record_data_proc_imm (insn_decode_record *aarch64_insn_r) +{ + uint8_t reg_rd, insn_bit28, insn_bit23, insn_bits24_27, setflags; + uint32_t record_buf[4]; + + reg_rd = bits (aarch64_insn_r->aarch64_insn, 0, 4); + insn_bit28 = bit (aarch64_insn_r->aarch64_insn, 28); + insn_bit23 = bit (aarch64_insn_r->aarch64_insn, 23); + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27); + + if (insn_bits24_27 == 0x00 /* PC rel addressing. */ + || insn_bits24_27 == 0x03 /* Bitfield and Extract. */ + || (insn_bits24_27 == 0x02 && insn_bit23)) /* Move wide (immediate). */ + { + record_buf[0] = reg_rd; + aarch64_insn_r->reg_rec_count = 1; + } + else if (insn_bits24_27 == 0x01) + { + /* Add/Subtract (immediate). */ + setflags = bit (aarch64_insn_r->aarch64_insn, 29); + record_buf[0] = reg_rd; + aarch64_insn_r->reg_rec_count = 1; + if (setflags) + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM; + } + else if (insn_bits24_27 == 0x02 && !insn_bit23) + { + /* Logical (immediate). */ + setflags = bits (aarch64_insn_r->aarch64_insn, 29, 30) == 0x03; + record_buf[0] = reg_rd; + aarch64_insn_r->reg_rec_count = 1; + if (setflags) + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM; + } + else + return AARCH64_RECORD_UNKNOWN; + + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count, + record_buf); + return AARCH64_RECORD_SUCCESS; +} + +/* Record handler for branch, exception generation and system instructions. */ + +static unsigned int +aarch64_record_branch_except_sys (insn_decode_record *aarch64_insn_r) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (aarch64_insn_r->gdbarch); + uint8_t insn_bits24_27, insn_bits28_31, insn_bits22_23; + uint32_t record_buf[4]; + + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27); + insn_bits28_31 = bits (aarch64_insn_r->aarch64_insn, 28, 31); + insn_bits22_23 = bits (aarch64_insn_r->aarch64_insn, 22, 23); + + if (insn_bits28_31 == 0x0d) + { + /* Exception generation instructions. */ + if (insn_bits24_27 == 0x04) + { + if (!bits (aarch64_insn_r->aarch64_insn, 2, 4) && + !bits (aarch64_insn_r->aarch64_insn, 21, 23) && + bits (aarch64_insn_r->aarch64_insn, 0, 1) == 0x01) + { + ULONGEST svc_number; + + regcache_raw_read_unsigned (aarch64_insn_r->regcache, 8, + &svc_number); + return tdep->aarch64_syscall_record (aarch64_insn_r->regcache, + svc_number); + } + else + return AARCH64_RECORD_UNSUPPORTED; + } + /* System instructions. */ + else if (insn_bits24_27 == 0x05 && insn_bits22_23 == 0x00) + { + uint32_t reg_rt, reg_crn; + + reg_rt = bits (aarch64_insn_r->aarch64_insn, 0, 4); + reg_crn = bits (aarch64_insn_r->aarch64_insn, 12, 15); + + /* Record rt in case of sysl and mrs instructions. */ + if (bit (aarch64_insn_r->aarch64_insn, 21)) + { + record_buf[0] = reg_rt; + aarch64_insn_r->reg_rec_count = 1; + } + /* Record cpsr for hint and msr(immediate) instructions. */ + else if (reg_crn == 0x02 || reg_crn == 0x04) + { + record_buf[0] = AARCH64_CPSR_REGNUM; + aarch64_insn_r->reg_rec_count = 1; + } + } + /* Unconditional branch (register). */ + else if((insn_bits24_27 & 0x0e) == 0x06) + { + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM; + if (bits (aarch64_insn_r->aarch64_insn, 21, 22) == 0x01) + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_LR_REGNUM; + } + else + return AARCH64_RECORD_UNKNOWN; + } + /* Unconditional branch (immediate). */ + else if ((insn_bits28_31 & 0x07) == 0x01 && (insn_bits24_27 & 0x0c) == 0x04) + { + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM; + if (bit (aarch64_insn_r->aarch64_insn, 31)) + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_LR_REGNUM; + } + else + /* Compare & branch (immediate), Test & branch (immediate) and + Conditional branch (immediate). */ + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM; + + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count, + record_buf); + return AARCH64_RECORD_SUCCESS; +} + +/* Record handler for advanced SIMD load and store instructions. */ + +static unsigned int +aarch64_record_asimd_load_store (insn_decode_record *aarch64_insn_r) +{ + CORE_ADDR address; + uint64_t addr_offset = 0; + uint32_t record_buf[24]; + uint64_t record_buf_mem[24]; + uint32_t reg_rn, reg_rt; + uint32_t reg_index = 0, mem_index = 0; + uint8_t opcode_bits, size_bits; + + reg_rt = bits (aarch64_insn_r->aarch64_insn, 0, 4); + reg_rn = bits (aarch64_insn_r->aarch64_insn, 5, 9); + size_bits = bits (aarch64_insn_r->aarch64_insn, 10, 11); + opcode_bits = bits (aarch64_insn_r->aarch64_insn, 12, 15); + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn, &address); + + if (record_debug) + { + fprintf_unfiltered (gdb_stdlog, + "Process record: Advanced SIMD load/store\n"); + } + + /* Load/store single structure. */ + if (bit (aarch64_insn_r->aarch64_insn, 24)) + { + uint8_t sindex, scale, selem, esize, replicate = 0; + scale = opcode_bits >> 2; + selem = ((opcode_bits & 0x02) | + bit (aarch64_insn_r->aarch64_insn, 21)) + 1; + switch (scale) + { + case 1: + if (size_bits & 0x01) + return AARCH64_RECORD_UNKNOWN; + break; + case 2: + if ((size_bits >> 1) & 0x01) + return AARCH64_RECORD_UNKNOWN; + if (size_bits & 0x01) + { + if (!((opcode_bits >> 1) & 0x01)) + scale = 3; + else + return AARCH64_RECORD_UNKNOWN; + } + break; + case 3: + if (bit (aarch64_insn_r->aarch64_insn, 22) && !(opcode_bits & 0x01)) + { + scale = size_bits; + replicate = 1; + break; + } + else + return AARCH64_RECORD_UNKNOWN; + default: + break; + } + esize = 8 << scale; + if (replicate) + for (sindex = 0; sindex < selem; sindex++) + { + record_buf[reg_index++] = reg_rt + AARCH64_V0_REGNUM; + reg_rt = (reg_rt + 1) % 32; + } + else + { + for (sindex = 0; sindex < selem; sindex++) + if (bit (aarch64_insn_r->aarch64_insn, 22)) + record_buf[reg_index++] = reg_rt + AARCH64_V0_REGNUM; + else + { + record_buf_mem[mem_index++] = esize / 8; + record_buf_mem[mem_index++] = address + addr_offset; + } + addr_offset = addr_offset + (esize / 8); + reg_rt = (reg_rt + 1) % 32; + } + } + /* Load/store multiple structure. */ + else + { + uint8_t selem, esize, rpt, elements; + uint8_t eindex, rindex; + + esize = 8 << size_bits; + if (bit (aarch64_insn_r->aarch64_insn, 30)) + elements = 128 / esize; + else + elements = 64 / esize; + + switch (opcode_bits) + { + /*LD/ST4 (4 Registers). */ + case 0: + rpt = 1; + selem = 4; + break; + /*LD/ST1 (4 Registers). */ + case 2: + rpt = 4; + selem = 1; + break; + /*LD/ST3 (3 Registers). */ + case 4: + rpt = 1; + selem = 3; + break; + /*LD/ST1 (3 Registers). */ + case 6: + rpt = 3; + selem = 1; + break; + /*LD/ST1 (1 Register). */ + case 7: + rpt = 1; + selem = 1; + break; + /*LD/ST2 (2 Registers). */ + case 8: + rpt = 1; + selem = 2; + break; + /*LD/ST1 (2 Registers). */ + case 10: + rpt = 2; + selem = 1; + break; + default: + return AARCH64_RECORD_UNSUPPORTED; + break; + } + for (rindex = 0; rindex < rpt; rindex++) + for (eindex = 0; eindex < elements; eindex++) + { + uint8_t reg_tt, sindex; + reg_tt = (reg_rt + rindex) % 32; + for (sindex = 0; sindex < selem; sindex++) + { + if (bit (aarch64_insn_r->aarch64_insn, 22)) + record_buf[reg_index++] = reg_tt + AARCH64_V0_REGNUM; + else + { + record_buf_mem[mem_index++] = esize / 8; + record_buf_mem[mem_index++] = address + addr_offset; + } + addr_offset = addr_offset + (esize / 8); + reg_tt = (reg_tt + 1) % 32; + } + } + } + + if (bit (aarch64_insn_r->aarch64_insn, 23)) + record_buf[reg_index++] = reg_rn; + + aarch64_insn_r->reg_rec_count = reg_index; + aarch64_insn_r->mem_rec_count = mem_index / 2; + MEM_ALLOC (aarch64_insn_r->aarch64_mems, aarch64_insn_r->mem_rec_count, + record_buf_mem); + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count, + record_buf); + return AARCH64_RECORD_SUCCESS; +} + +/* Record handler for load and store instructions. */ + +static unsigned int +aarch64_record_load_store (insn_decode_record *aarch64_insn_r) +{ + uint8_t insn_bits24_27, insn_bits28_29, insn_bits10_11; + uint8_t insn_bit23, insn_bit21; + uint8_t opc, size_bits, ld_flag, vector_flag; + uint32_t reg_rn, reg_rt, reg_rt2; + uint64_t datasize, offset; + uint32_t record_buf[8]; + uint64_t record_buf_mem[8]; + CORE_ADDR address; + + insn_bits10_11 = bits (aarch64_insn_r->aarch64_insn, 10, 11); + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27); + insn_bits28_29 = bits (aarch64_insn_r->aarch64_insn, 28, 29); + insn_bit21 = bit (aarch64_insn_r->aarch64_insn, 21); + insn_bit23 = bit (aarch64_insn_r->aarch64_insn, 23); + ld_flag = bit (aarch64_insn_r->aarch64_insn, 22); + vector_flag = bit (aarch64_insn_r->aarch64_insn, 26); + reg_rt = bits (aarch64_insn_r->aarch64_insn, 0, 4); + reg_rn = bits (aarch64_insn_r->aarch64_insn, 5, 9); + reg_rt2 = bits (aarch64_insn_r->aarch64_insn, 10, 14); + size_bits = bits (aarch64_insn_r->aarch64_insn, 30, 31); + + /* Load/store exclusive. */ + if (insn_bits24_27 == 0x08 && insn_bits28_29 == 0x00) + { + if (record_debug) + { + fprintf_unfiltered (gdb_stdlog, + "Process record: load/store exclusive\n"); + } + + if (ld_flag) + { + record_buf[0] = reg_rt; + aarch64_insn_r->reg_rec_count = 1; + if (insn_bit21) + { + record_buf[1] = reg_rt2; + aarch64_insn_r->reg_rec_count = 2; + } + } + else + { + if (insn_bit21) + datasize = (8 << size_bits) * 2; + else + datasize = (8 << size_bits); + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn, + &address); + record_buf_mem[0] = datasize / 8; + record_buf_mem[1] = address; + aarch64_insn_r->mem_rec_count = 1; + if (!insn_bit23) + { + /* Save register rs. */ + record_buf[0] = bits (aarch64_insn_r->aarch64_insn, 16, 20); + aarch64_insn_r->reg_rec_count = 1; + } + } + } + /* Load register (literal) instructions decoding. */ + else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x01) + { + if (record_debug) + { + fprintf_unfiltered (gdb_stdlog, + "Process record: load register (literal)\n"); + } + if (vector_flag) + record_buf[0] = reg_rt + AARCH64_V0_REGNUM; + else + record_buf[0] = reg_rt; + aarch64_insn_r->reg_rec_count = 1; + } + /* All types of load/store pair instructions decoding. */ + else if ((insn_bits24_27 & 0x0a) == 0x08 && insn_bits28_29 == 0x02) + { + if (record_debug) + { + fprintf_unfiltered (gdb_stdlog, + "Process record: load/store pair\n"); + } + + if (ld_flag) + { + if (vector_flag) + { + record_buf[0] = reg_rt + AARCH64_V0_REGNUM; + record_buf[1] = reg_rt2 + AARCH64_V0_REGNUM; + } + else + { + record_buf[0] = reg_rt; + record_buf[1] = reg_rt2; + } + aarch64_insn_r->reg_rec_count = 2; + } + else + { + uint16_t imm7_off; + imm7_off = bits (aarch64_insn_r->aarch64_insn, 15, 21); + if (!vector_flag) + size_bits = size_bits >> 1; + datasize = 8 << (2 + size_bits); + offset = (imm7_off & 0x40) ? (~imm7_off & 0x007f) + 1 : imm7_off; + offset = offset << (2 + size_bits); + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn, + &address); + if (!((insn_bits24_27 & 0x0b) == 0x08 && insn_bit23)) + { + if (imm7_off & 0x40) + address = address - offset; + else + address = address + offset; + } + + record_buf_mem[0] = datasize / 8; + record_buf_mem[1] = address; + record_buf_mem[2] = datasize / 8; + record_buf_mem[3] = address + (datasize / 8); + aarch64_insn_r->mem_rec_count = 2; + } + if (bit (aarch64_insn_r->aarch64_insn, 23)) + record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn; + } + /* Load/store register (unsigned immediate) instructions. */ + else if ((insn_bits24_27 & 0x0b) == 0x09 && insn_bits28_29 == 0x03) + { + opc = bits (aarch64_insn_r->aarch64_insn, 22, 23); + if (!(opc >> 1)) + if (opc & 0x01) + ld_flag = 0x01; + else + ld_flag = 0x0; + else + if (size_bits != 0x03) + ld_flag = 0x01; + else + return AARCH64_RECORD_UNKNOWN; + + if (record_debug) + { + fprintf_unfiltered (gdb_stdlog, + "Process record: load/store (unsigned immediate):" + " size %x V %d opc %x\n", size_bits, vector_flag, + opc); + } + + if (!ld_flag) + { + offset = bits (aarch64_insn_r->aarch64_insn, 10, 21); + datasize = 8 << size_bits; + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn, + &address); + offset = offset << size_bits; + address = address + offset; + + record_buf_mem[0] = datasize >> 3; + record_buf_mem[1] = address; + aarch64_insn_r->mem_rec_count = 1; + } + else + { + if (vector_flag) + record_buf[0] = reg_rt + AARCH64_V0_REGNUM; + else + record_buf[0] = reg_rt; + aarch64_insn_r->reg_rec_count = 1; + } + } + /* Load/store register (register offset) instructions. */ + else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03 && + insn_bits10_11 == 0x02 && insn_bit21) + { + if (record_debug) + { + fprintf_unfiltered (gdb_stdlog, + "Process record: load/store (register offset)\n"); + } + opc = bits (aarch64_insn_r->aarch64_insn, 22, 23); + if (!(opc >> 1)) + if (opc & 0x01) + ld_flag = 0x01; + else + ld_flag = 0x0; + else + if (size_bits != 0x03) + ld_flag = 0x01; + else + return AARCH64_RECORD_UNKNOWN; + + if (!ld_flag) + { + uint64_t reg_rm_val; + regcache_raw_read_unsigned (aarch64_insn_r->regcache, + bits (aarch64_insn_r->aarch64_insn, 16, 20), ®_rm_val); + if (bit (aarch64_insn_r->aarch64_insn, 12)) + offset = reg_rm_val << size_bits; + else + offset = reg_rm_val; + datasize = 8 << size_bits; + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn, + &address); + address = address + offset; + record_buf_mem[0] = datasize >> 3; + record_buf_mem[1] = address; + aarch64_insn_r->mem_rec_count = 1; + } + else + { + if (vector_flag) + record_buf[0] = reg_rt + AARCH64_V0_REGNUM; + else + record_buf[0] = reg_rt; + aarch64_insn_r->reg_rec_count = 1; + } + } + /* Load/store register (immediate and unprivileged) instructions. */ + else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03 && + !insn_bit21) + { + if (record_debug) + { + fprintf_unfiltered (gdb_stdlog, + "Process record: load/store (immediate and unprivileged)\n"); + } + opc = bits (aarch64_insn_r->aarch64_insn, 22, 23); + if (!(opc >> 1)) + if (opc & 0x01) + ld_flag = 0x01; + else + ld_flag = 0x0; + else + if (size_bits != 0x03) + ld_flag = 0x01; + else + return AARCH64_RECORD_UNKNOWN; + + if (!ld_flag) + { + uint16_t imm9_off; + imm9_off = bits (aarch64_insn_r->aarch64_insn, 12, 20); + offset = (imm9_off & 0x0100) ? (((~imm9_off) & 0x01ff) + 1) : imm9_off; + datasize = 8 << size_bits; + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn, + &address); + if (insn_bits10_11 != 0x01) + { + if (imm9_off & 0x0100) + address = address - offset; + else + address = address + offset; + } + record_buf_mem[0] = datasize >> 3; + record_buf_mem[1] = address; + aarch64_insn_r->mem_rec_count = 1; + } + else + { + if (vector_flag) + record_buf[0] = reg_rt + AARCH64_V0_REGNUM; + else + record_buf[0] = reg_rt; + aarch64_insn_r->reg_rec_count = 1; + } + if (insn_bits10_11 == 0x01 || insn_bits10_11 == 0x03) + record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn; + } + /* Advanced SIMD load/store instructions. */ + else + return aarch64_record_asimd_load_store (aarch64_insn_r); + + MEM_ALLOC (aarch64_insn_r->aarch64_mems, aarch64_insn_r->mem_rec_count, + record_buf_mem); + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count, + record_buf); + return AARCH64_RECORD_SUCCESS; +} + +/* Record handler for data processing SIMD and floating point instructions. */ + +static unsigned int +aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r) +{ + uint8_t insn_bit21, opcode, rmode, reg_rd; + uint8_t insn_bits24_27, insn_bits28_31, insn_bits10_11, insn_bits12_15; + uint8_t insn_bits11_14; + uint32_t record_buf[2]; + + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27); + insn_bits28_31 = bits (aarch64_insn_r->aarch64_insn, 28, 31); + insn_bits10_11 = bits (aarch64_insn_r->aarch64_insn, 10, 11); + insn_bits12_15 = bits (aarch64_insn_r->aarch64_insn, 12, 15); + insn_bits11_14 = bits (aarch64_insn_r->aarch64_insn, 11, 14); + opcode = bits (aarch64_insn_r->aarch64_insn, 16, 18); + rmode = bits (aarch64_insn_r->aarch64_insn, 19, 20); + reg_rd = bits (aarch64_insn_r->aarch64_insn, 0, 4); + insn_bit21 = bit (aarch64_insn_r->aarch64_insn, 21); + + if (record_debug) + { + fprintf_unfiltered (gdb_stdlog, + "Process record: data processing SIMD/FP: "); + } + + if ((insn_bits28_31 & 0x05) == 0x01 && insn_bits24_27 == 0x0e) + { + /* Floating point - fixed point conversion instructions. */ + if (!insn_bit21) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, "FP - fixed point conversion"); + + if ((opcode >> 1) == 0x0 && rmode == 0x03) + record_buf[0] = reg_rd; + else + record_buf[0] = reg_rd + AARCH64_V0_REGNUM; + } + /* Floating point - conditional compare instructions. */ + else if (insn_bits10_11 == 0x01) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, "FP - conditional compare"); + + record_buf[0] = AARCH64_CPSR_REGNUM; + } + /* Floating point - data processing (2-source) and + conditional select instructions. */ + else if (insn_bits10_11 == 0x02 || insn_bits10_11 == 0x03) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, "FP - DP (2-source)"); + + record_buf[0] = reg_rd + AARCH64_V0_REGNUM; + } + else if (insn_bits10_11 == 0x00) + { + /* Floating point - immediate instructions. */ + if ((insn_bits12_15 & 0x01) == 0x01 + || (insn_bits12_15 & 0x07) == 0x04) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, "FP - immediate"); + record_buf[0] = reg_rd + AARCH64_V0_REGNUM; + } + /* Floating point - compare instructions. */ + else if ((insn_bits12_15 & 0x03) == 0x02) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, "FP - immediate"); + record_buf[0] = AARCH64_CPSR_REGNUM; + } + /* Floating point - integer conversions instructions. */ + if (insn_bits12_15 == 0x00) + { + /* Convert float to integer instruction. */ + if (!(opcode >> 1) || ((opcode >> 1) == 0x02 && !rmode)) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, "float to int conversion"); + + record_buf[0] = reg_rd + AARCH64_X0_REGNUM; + } + /* Convert integer to float instruction. */ + else if ((opcode >> 1) == 0x01 && !rmode) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, "int to float conversion"); + + record_buf[0] = reg_rd + AARCH64_V0_REGNUM; + } + /* Move float to integer instruction. */ + else if ((opcode >> 1) == 0x03) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, "move float to int"); + + if (!(opcode & 0x01)) + record_buf[0] = reg_rd + AARCH64_X0_REGNUM; + else + record_buf[0] = reg_rd + AARCH64_V0_REGNUM; + } + } + } + } + else if ((insn_bits28_31 & 0x09) == 0x00 && insn_bits24_27 == 0x0e) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, "SIMD copy"); + + /* Advanced SIMD copy instructions. */ + if (!bits (aarch64_insn_r->aarch64_insn, 21, 23) + && !bit (aarch64_insn_r->aarch64_insn, 15) + && bit (aarch64_insn_r->aarch64_insn, 10)) + { + if (insn_bits11_14 == 0x05 || insn_bits11_14 == 0x07) + record_buf[0] = reg_rd + AARCH64_X0_REGNUM; + else + record_buf[0] = reg_rd + AARCH64_V0_REGNUM; + } + else + record_buf[0] = reg_rd + AARCH64_V0_REGNUM; + } + /* All remaining floating point or advanced SIMD instructions. */ + else + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, "all remain"); + + record_buf[0] = reg_rd + AARCH64_V0_REGNUM; + } + + if (record_debug) + fprintf_unfiltered (gdb_stdlog, "\n"); + + aarch64_insn_r->reg_rec_count++; + gdb_assert (aarch64_insn_r->reg_rec_count == 1); + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count, + record_buf); + return AARCH64_RECORD_SUCCESS; +} + +/* Decodes insns type and invokes its record handler. */ + +static unsigned int +aarch64_record_decode_insn_handler (insn_decode_record *aarch64_insn_r) +{ + uint32_t ins_bit25, ins_bit26, ins_bit27, ins_bit28; + + ins_bit25 = bit (aarch64_insn_r->aarch64_insn, 25); + ins_bit26 = bit (aarch64_insn_r->aarch64_insn, 26); + ins_bit27 = bit (aarch64_insn_r->aarch64_insn, 27); + ins_bit28 = bit (aarch64_insn_r->aarch64_insn, 28); + + /* Data processing - immediate instructions. */ + if (!ins_bit26 && !ins_bit27 && ins_bit28) + return aarch64_record_data_proc_imm (aarch64_insn_r); + + /* Branch, exception generation and system instructions. */ + if (ins_bit26 && !ins_bit27 && ins_bit28) + return aarch64_record_branch_except_sys (aarch64_insn_r); + + /* Load and store instructions. */ + if (!ins_bit25 && ins_bit27) + return aarch64_record_load_store (aarch64_insn_r); + + /* Data processing - register instructions. */ + if (ins_bit25 && !ins_bit26 && ins_bit27) + return aarch64_record_data_proc_reg (aarch64_insn_r); + + /* Data processing - SIMD and floating point instructions. */ + if (ins_bit25 && ins_bit26 && ins_bit27) + return aarch64_record_data_proc_simd_fp (aarch64_insn_r); + + return AARCH64_RECORD_UNSUPPORTED; +} + +/* Cleans up local record registers and memory allocations. */ + +static void +deallocate_reg_mem (insn_decode_record *record) +{ + xfree (record->aarch64_regs); + xfree (record->aarch64_mems); +} + +/* Parse the current instruction and record the values of the registers and + memory that will be changed in current instruction to record_arch_list + return -1 if something is wrong. */ + +int +aarch64_process_record (struct gdbarch *gdbarch, struct regcache *regcache, + CORE_ADDR insn_addr) +{ + uint32_t rec_no = 0; + uint8_t insn_size = 4; + uint32_t ret = 0; + ULONGEST t_bit = 0, insn_id = 0; + gdb_byte buf[insn_size]; + insn_decode_record aarch64_record; + + memset (&buf[0], 0, insn_size); + memset (&aarch64_record, 0, sizeof (insn_decode_record)); + target_read_memory (insn_addr, &buf[0], insn_size); + aarch64_record.aarch64_insn + = (uint32_t) extract_unsigned_integer (&buf[0], + insn_size, + gdbarch_byte_order (gdbarch)); + aarch64_record.regcache = regcache; + aarch64_record.this_addr = insn_addr; + aarch64_record.gdbarch = gdbarch; + + ret = aarch64_record_decode_insn_handler (&aarch64_record); + if (ret == AARCH64_RECORD_UNSUPPORTED) + { + printf_unfiltered (_("Process record does not support instruction " + "0x%0x at address %s.\n"), + aarch64_record.aarch64_insn, + paddress (gdbarch, insn_addr)); + ret = -1; + } + + if (0 == ret) + { + /* Record registers. */ + record_full_arch_list_add_reg (aarch64_record.regcache, + AARCH64_PC_REGNUM); + /* Always record register CPSR. */ + record_full_arch_list_add_reg (aarch64_record.regcache, + AARCH64_CPSR_REGNUM); + if (aarch64_record.aarch64_regs) + for (rec_no = 0; rec_no < aarch64_record.reg_rec_count; rec_no++) + if (record_full_arch_list_add_reg (aarch64_record.regcache, + aarch64_record.aarch64_regs[rec_no])) + ret = -1; + + /* Record memories. */ + if (aarch64_record.aarch64_mems) + for (rec_no = 0; rec_no < aarch64_record.mem_rec_count; rec_no++) + if (record_full_arch_list_add_mem + ((CORE_ADDR)aarch64_record.aarch64_mems[rec_no].addr, + aarch64_record.aarch64_mems[rec_no].len)) + ret = -1; + + if (record_full_arch_list_add_end ()) + ret = -1; + } + + deallocate_reg_mem (&aarch64_record); + return ret; +} diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h index 976ad32..af209a9 100644 --- a/gdb/aarch64-tdep.h +++ b/gdb/aarch64-tdep.h @@ -88,8 +88,14 @@ struct gdbarch_tdep struct type *vns_type; struct type *vnh_type; struct type *vnb_type; + + /* syscall record. */ + int (*aarch64_syscall_record) (struct regcache *regcache, unsigned long svc_number); }; extern struct target_desc *tdesc_aarch64; +extern int aarch64_process_record (struct gdbarch *gdbarch, + struct regcache *regcache, CORE_ADDR addr); + #endif /* aarch64-tdep.h */ diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 8feda7c..4e4d6a9 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -45,7 +45,7 @@ aarch64*-*-linux*) # Target: AArch64 linux gdb_target_obs="aarch64-tdep.o aarch64-linux-tdep.o \ glibc-tdep.o linux-tdep.o solib-svr4.o \ - symfile-mem.o" + symfile-mem.o linux-record.o" build_gdbserver=yes ;; diff --git a/gdb/linux-record.h b/gdb/linux-record.h index ab39cb9..27bb700 100644 --- a/gdb/linux-record.h +++ b/gdb/linux-record.h @@ -174,6 +174,7 @@ struct linux_record_tdep int arg4; int arg5; int arg6; + int arg7; }; /* Enum that defines the gdb-canonical set of Linux syscall identifiers.