trace_processor: Improve support for syscalls

Syscall numbers are different on each platform.
This cl introduces SyscallTracker which maps the syscall numbers
onto the correct syscall for each platform. We use the SystemInfo
packet to work out which platform the trace is taken from.

Bug: 124099616
Change-Id: I0e829aa6fbea1a2d59c6af11879e82e372557181
diff --git a/Android.bp b/Android.bp
index 320c21a..bfdf51a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3167,6 +3167,7 @@
     "src/trace_processor/storage_table.cc",
     "src/trace_processor/string_pool.cc",
     "src/trace_processor/string_table.cc",
+    "src/trace_processor/syscall_tracker.cc",
     "src/trace_processor/table.cc",
     "src/trace_processor/thread_table.cc",
     "src/trace_processor/trace_processor.cc",
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 2b7790e..29dd3c0 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -107,6 +107,8 @@
     "string_pool.h",
     "string_table.cc",
     "string_table.h",
+    "syscall_tracker.cc",
+    "syscall_tracker.h",
     "table.cc",
     "table.h",
     "thread_table.cc",
@@ -208,6 +210,7 @@
     "span_join_operator_table_unittest.cc",
     "sqlite3_str_split_unittest.cc",
     "string_pool_unittest.cc",
+    "syscall_tracker_unittest.cc",
     "thread_table_unittest.cc",
     "trace_processor_impl_unittest.cc",
     "trace_sorter_unittest.cc",
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index 8003b35..c6e4a75 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -33,6 +33,7 @@
 #include "src/trace_processor/ftrace_descriptors.h"
 #include "src/trace_processor/process_tracker.h"
 #include "src/trace_processor/slice_tracker.h"
+#include "src/trace_processor/syscall_tracker.h"
 #include "src/trace_processor/trace_processor_context.h"
 
 #include "perfetto/common/android_log_constants.pbzero.h"
@@ -58,6 +59,7 @@
 #include "perfetto/trace/ps/process_stats.pbzero.h"
 #include "perfetto/trace/ps/process_tree.pbzero.h"
 #include "perfetto/trace/sys_stats/sys_stats.pbzero.h"
+#include "perfetto/trace/system_info.pbzero.h"
 #include "perfetto/trace/trace.pbzero.h"
 #include "perfetto/trace/trace_packet.pbzero.h"
 
@@ -246,21 +248,6 @@
            context->storage->InternString("mem.mm.kern_alloc.max_lat"),
            context->storage->InternString("mem.mm.kern_alloc.avg_lat"))}};
 
-  // TODO(hjd): Add the missing syscalls + fix on over arch.
-  sys_name_ids_ = {{context->storage->InternString("sys_restart_syscall"),
-                    context->storage->InternString("sys_exit"),
-                    context->storage->InternString("sys_fork"),
-                    context->storage->InternString("sys_read"),
-                    context->storage->InternString("sys_write"),
-                    context->storage->InternString("sys_open"),
-                    context->storage->InternString("sys_close"),
-                    context->storage->InternString("sys_creat"),
-                    context->storage->InternString("sys_link"),
-                    context->storage->InternString("sys_unlink"),
-                    context->storage->InternString("sys_execve"),
-                    context->storage->InternString("sys_chdir"),
-                    context->storage->InternString("sys_time")}};
-
   // Build the lookup table for the strings inside ftrace events (e.g. the
   // name of ftrace event fields and the names of their args).
   for (size_t i = 0; i < GetDescriptorsSize(); i++) {
@@ -320,6 +307,9 @@
   if (packet.has_profile_packet())
     ParseProfilePacket(packet.profile_packet());
 
+  if (packet.has_system_info())
+    ParseSystemInfo(packet.system_info());
+
   // TODO(lalitm): maybe move this to the flush method in the trace processor
   // once we have it. This may reduce performance in the ArgsTracker though so
   // needs to be handled carefully.
@@ -919,24 +909,12 @@
                                      ConstBytes blob) {
   protos::pbzero::SysEnterFtraceEvent::Decoder evt(blob.data, blob.size);
   uint32_t syscall_num = static_cast<uint32_t>(evt.id());
-  if (syscall_num >= sys_name_ids_.size()) {
-    context_->storage->IncrementStats(stats::sys_unknown_syscall);
-    return;
-  }
-
-  // We see two write sys calls around each userspace slice that is going via
-  // trace_marker, this violates the assumption that userspace slices are
-  // perfectly nested. For the moment ignore all write sys calls.
-  // TODO(hjd): Remove this limitation.
-  if (syscall_num == 4 /*sys_write*/)
-    return;
-
-  StringId sys_name_id = sys_name_ids_[syscall_num];
   UniqueTid utid = context_->process_tracker->UpdateThread(ts, pid, 0);
+
   if (is_enter) {
-    context_->slice_tracker->Begin(ts, utid, 0 /* cat */, sys_name_id);
+    context_->syscall_tracker->Enter(ts, utid, syscall_num);
   } else {
-    context_->slice_tracker->End(ts, utid, 0 /* cat */, sys_name_id);
+    context_->syscall_tracker->Exit(ts, utid, syscall_num);
   }
 
   // We are reusing the same function for sys_enter and sys_exit.
@@ -1282,5 +1260,22 @@
   }
 }
 
+void ProtoTraceParser::ParseSystemInfo(ConstBytes blob) {
+  protos::pbzero::SystemInfo::Decoder packet(blob.data, blob.size);
+  if (packet.has_utsname()) {
+    ConstBytes utsname_blob = packet.utsname();
+    protos::pbzero::Utsname::Decoder utsname(utsname_blob.data,
+                                             utsname_blob.size);
+    base::StringView machine = utsname.machine();
+    if (machine == "aarch64" || machine == "armv8l") {
+      context_->syscall_tracker->SetArchitecture(kAarch64);
+    } else if (machine == "x86_64") {
+      context_->syscall_tracker->SetArchitecture(kX86_64);
+    } else {
+      PERFETTO_ELOG("Unknown architecture %s", machine.ToStdString().c_str());
+    }
+  }
+}
+
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/proto_trace_parser.h b/src/trace_processor/proto_trace_parser.h
index 77ccdd2..b3a0ebb 100644
--- a/src/trace_processor/proto_trace_parser.h
+++ b/src/trace_processor/proto_trace_parser.h
@@ -102,6 +102,7 @@
   void ParseTraceStats(ConstBytes);
   void ParseFtraceStats(ConstBytes);
   void ParseProfilePacket(ConstBytes);
+  void ParseSystemInfo(ConstBytes);
 
  private:
   TraceProcessorContext* context_;
@@ -164,9 +165,6 @@
   static constexpr size_t kMmEventCounterSize = 7;
   std::array<MmEventCounterNames, kMmEventCounterSize> mm_event_counter_names_;
 
-  // Keep this in sync with the Linux syscall count.
-  static constexpr size_t kSysNameIdSize = 13;
-  std::array<StringId, kSysNameIdSize> sys_name_ids_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/slice_tracker.h b/src/trace_processor/slice_tracker.h
index bafada4..219bf3f 100644
--- a/src/trace_processor/slice_tracker.h
+++ b/src/trace_processor/slice_tracker.h
@@ -29,7 +29,7 @@
 class SliceTracker {
  public:
   explicit SliceTracker(TraceProcessorContext*);
-  ~SliceTracker();
+  virtual ~SliceTracker();
 
   void BeginAndroid(int64_t timestamp,
                     uint32_t ftrace_tid,
@@ -37,7 +37,11 @@
                     StringId cat,
                     StringId name);
 
-  void Begin(int64_t timestamp, UniqueTid utid, StringId cat, StringId name);
+  // virtual for testing
+  virtual void Begin(int64_t timestamp,
+                     UniqueTid utid,
+                     StringId cat,
+                     StringId name);
 
   void Scoped(int64_t timestamp,
               UniqueTid utid,
@@ -47,10 +51,11 @@
 
   void EndAndroid(int64_t timestamp, uint32_t ftrace_tid, uint32_t atrace_tgid);
 
-  void End(int64_t timestamp,
-           UniqueTid utid,
-           StringId opt_cat = {},
-           StringId opt_name = {});
+  // virtual for testing
+  virtual void End(int64_t timestamp,
+                   UniqueTid utid,
+                   StringId opt_cat = {},
+                   StringId opt_name = {});
 
  private:
   using SlicesStack = std::vector<size_t>;
diff --git a/src/trace_processor/syscall_tracker.cc b/src/trace_processor/syscall_tracker.cc
new file mode 100644
index 0000000..926166f
--- /dev/null
+++ b/src/trace_processor/syscall_tracker.cc
@@ -0,0 +1,681 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/syscall_tracker.h"
+
+#include <utility>
+
+#include <inttypes.h>
+
+#include "src/trace_processor/slice_tracker.h"
+#include "src/trace_processor/stats.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+// Syscall number to string.
+// https://thog.github.io/syscalls-table-aarch64/latest.html
+constexpr std::array<const char*, kSyscallCount> aarch64_to_syscall = {{
+    "sys_io_setup",                //
+    "sys_io_destroy",              //
+    "sys_io_submit",               //
+    "sys_io_cancel",               //
+    "sys_io_getevents",            //
+    "sys_setxattr",                //
+    "sys_lsetxattr",               //
+    "sys_fsetxattr",               //
+    "sys_getxattr",                //
+    "sys_lgetxattr",               //
+    "sys_fgetxattr",               //
+    "sys_listxattr",               //
+    "sys_llistxattr",              //
+    "sys_flistxattr",              //
+    "sys_removexattr",             //
+    "sys_lremovexattr",            //
+    "sys_fremovexattr",            //
+    "sys_getcwd",                  //
+    "sys_lookup_dcookie",          //
+    "sys_eventfd2",                //
+    "sys_epoll_create1",           //
+    "sys_epoll_ctl",               //
+    "sys_epoll_pwait",             //
+    "sys_dup",                     //
+    "sys_dup3",                    //
+    "sys_inotify_init1",           //
+    "sys_inotify_add_watch",       //
+    "sys_inotify_rm_watch",        //
+    "sys_ioctl",                   //
+    "sys_ioprio_set",              //
+    "sys_ioprio_get",              //
+    "sys_flock",                   //
+    "sys_mknodat",                 //
+    "sys_mkdirat",                 //
+    "sys_unlinkat",                //
+    "sys_symlinkat",               //
+    "sys_linkat",                  //
+    "sys_renameat",                //
+    "sys_umount2",                 //
+    "sys_mount",                   //
+    "sys_pivot_root",              //
+    "sys_nfsservctl",              //
+    "sys_fallocate",               //
+    "sys_faccessat",               //
+    "sys_chdir",                   //
+    "sys_fchdir",                  //
+    "sys_chroot",                  //
+    "sys_fchmod",                  //
+    "sys_fchmodat",                //
+    "sys_fchownat",                //
+    "sys_fchown",                  //
+    "sys_openat",                  //
+    "sys_close",                   //
+    "sys_vhangup",                 //
+    "sys_pipe2",                   //
+    "sys_quotactl",                //
+    "sys_getdents64",              //
+    "sys_read",                    //
+    "sys_write",                   //
+    "sys_readv",                   //
+    "sys_writev",                  //
+    "sys_pread64",                 //
+    "sys_pwrite64",                //
+    "sys_preadv",                  //
+    "sys_pwritev",                 //
+    "sys_pselect6",                //
+    "sys_ppoll",                   //
+    "sys_signalfd4",               //
+    "sys_vmsplice",                //
+    "sys_splice",                  //
+    "sys_tee",                     //
+    "sys_readlinkat",              //
+    "sys_sync",                    //
+    "sys_fsync",                   //
+    "sys_fdatasync",               //
+    "sys_sync_file_range2",        //
+    "sys_sync_file_range",         //
+    "sys_timerfd_create",          //
+    "sys_timerfd_settime",         //
+    "sys_timerfd_gettime",         //
+    "sys_utimensat",               //
+    "sys_acct",                    //
+    "sys_capget",                  //
+    "sys_capset",                  //
+    "sys_personality",             //
+    "sys_exit",                    //
+    "sys_exit_group",              //
+    "sys_waitid",                  //
+    "sys_set_tid_address",         //
+    "sys_unshare",                 //
+    "sys_futex",                   //
+    "sys_set_robust_list",         //
+    "sys_get_robust_list",         //
+    "sys_nanosleep",               //
+    "sys_getitimer",               //
+    "sys_setitimer",               //
+    "sys_kexec_load",              //
+    "sys_init_module",             //
+    "sys_delete_module",           //
+    "sys_timer_create",            //
+    "sys_timer_gettime",           //
+    "sys_timer_getoverrun",        //
+    "sys_timer_settime",           //
+    "sys_timer_delete",            //
+    "sys_clock_settime",           //
+    "sys_clock_gettime",           //
+    "sys_clock_getres",            //
+    "sys_clock_nanosleep",         //
+    "sys_syslog",                  //
+    "sys_ptrace",                  //
+    "sys_sched_setparam",          //
+    "sys_sched_setscheduler",      //
+    "sys_sched_getscheduler",      //
+    "sys_sched_getparam",          //
+    "sys_sched_setaffinity",       //
+    "sys_sched_getaffinity",       //
+    "sys_sched_yield",             //
+    "sys_sched_get_priority_max",  //
+    "sys_sched_get_priority_min",  //
+    "sys_sched_rr_get_interval",   //
+    "sys_restart_syscall",         //
+    "sys_kill",                    //
+    "sys_tkill",                   //
+    "sys_tgkill",                  //
+    "sys_sigaltstack",             //
+    "sys_rt_sigsuspend",           //
+    "sys_rt_sigaction",            //
+    "sys_rt_sigprocmask",          //
+    "sys_rt_sigpending",           //
+    "sys_rt_sigtimedwait",         //
+    "sys_rt_sigqueueinfo",         //
+    "sys_rt_sigreturn",            //
+    "sys_setpriority",             //
+    "sys_getpriority",             //
+    "sys_reboot",                  //
+    "sys_setregid",                //
+    "sys_setgid",                  //
+    "sys_setreuid",                //
+    "sys_setuid",                  //
+    "sys_setresuid",               //
+    "sys_getresuid",               //
+    "sys_setresgid",               //
+    "sys_getresgid",               //
+    "sys_setfsuid",                //
+    "sys_setfsgid",                //
+    "sys_times",                   //
+    "sys_setpgid",                 //
+    "sys_getpgid",                 //
+    "sys_getsid",                  //
+    "sys_setsid",                  //
+    "sys_getgroups",               //
+    "sys_setgroups",               //
+    "sys_uname",                   //
+    "sys_sethostname",             //
+    "sys_setdomainname",           //
+    "sys_getrlimit",               //
+    "sys_setrlimit",               //
+    "sys_getrusage",               //
+    "sys_umask",                   //
+    "sys_prctl",                   //
+    "sys_getcpu",                  //
+    "sys_gettimeofday",            //
+    "sys_settimeofday",            //
+    "sys_adjtimex",                //
+    "sys_getpid",                  //
+    "sys_getppid",                 //
+    "sys_getuid",                  //
+    "sys_geteuid",                 //
+    "sys_getgid",                  //
+    "sys_getegid",                 //
+    "sys_gettid",                  //
+    "sys_sysinfo",                 //
+    "sys_mq_open",                 //
+    "sys_mq_unlink",               //
+    "sys_mq_timedsend",            //
+    "sys_mq_timedreceive",         //
+    "sys_mq_notify",               //
+    "sys_mq_getsetattr",           //
+    "sys_msgget",                  //
+    "sys_msgctl",                  //
+    "sys_msgrcv",                  //
+    "sys_msgsnd",                  //
+    "sys_semget",                  //
+    "sys_semctl",                  //
+    "sys_semtimedop",              //
+    "sys_semop",                   //
+    "sys_shmget",                  //
+    "sys_shmctl",                  //
+    "sys_shmat",                   //
+    "sys_shmdt",                   //
+    "sys_socket",                  //
+    "sys_socketpair",              //
+    "sys_bind",                    //
+    "sys_listen",                  //
+    "sys_accept",                  //
+    "sys_connect",                 //
+    "sys_getsockname",             //
+    "sys_getpeername",             //
+    "sys_sendto",                  //
+    "sys_recvfrom",                //
+    "sys_setsockopt",              //
+    "sys_getsockopt",              //
+    "sys_shutdown",                //
+    "sys_sendmsg",                 //
+    "sys_recvmsg",                 //
+    "sys_readahead",               //
+    "sys_brk",                     //
+    "sys_munmap",                  //
+    "sys_mremap",                  //
+    "sys_add_key",                 //
+    "sys_request_key",             //
+    "sys_keyctl",                  //
+    "sys_clone",                   //
+    "sys_execve",                  //
+    "sys_swapon",                  //
+    "sys_swapoff",                 //
+    "sys_mprotect",                //
+    "sys_msync",                   //
+    "sys_mlock",                   //
+    "sys_munlock",                 //
+    "sys_mlockall",                //
+    "sys_munlockall",              //
+    "sys_mincore",                 //
+    "sys_madvise",                 //
+    "sys_remap_file_pages",        //
+    "sys_mbind",                   //
+    "sys_get_mempolicy",           //
+    "sys_set_mempolicy",           //
+    "sys_migrate_pages",           //
+    "sys_move_pages",              //
+    "sys_rt_tgsigqueueinfo",       //
+    "sys_perf_event_open",         //
+    "sys_accept4",                 //
+    "sys_recvmmsg",                //
+    "sys_arch_specific_syscall",   //
+    "sys_wait4",                   //
+    "sys_prlimit64",               //
+    "sys_fanotify_init",           //
+    "sys_fanotify_mark",           //
+    "sys_name_to_handle_at",       //
+    "sys_open_by_handle_at",       //
+    "sys_clock_adjtime",           //
+    "sys_syncfs",                  //
+    "sys_setns",                   //
+    "sys_sendmmsg",                //
+    "sys_process_vm_readv",        //
+    "sys_process_vm_writev",       //
+    "sys_kcmp",                    //
+    "sys_finit_module",            //
+    "sys_sched_setattr",           //
+    "sys_sched_getattr",           //
+    "sys_renameat2",               //
+    "sys_seccomp",                 //
+    "sys_getrandom",               //
+    "sys_memfd_create",            //
+    "sys_bpf",                     //
+    "sys_execveat",                //
+    "sys_userfaultfd",             //
+    "sys_membarrier",              //
+    "sys_mlock2",                  //
+    "sys_copy_file_range",         //
+    "sys_preadv2",                 //
+    "sys_pwritev2",                //
+    "sys_pkey_mprotect",           //
+    "sys_pkey_alloc",              //
+    "sys_pkey_free",               //
+    "sys_statx",                   //
+}};
+
+// Syscall number to string.
+// https://filippo.io/linux-syscall-table/
+// http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
+constexpr std::array<const char*, kSyscallCount> x86_64_to_syscall = {{
+    "sys_read",                    //
+    "sys_write",                   //
+    "sys_open",                    //
+    "sys_close",                   //
+    "sys_newstat",                 //
+    "sys_newfstat",                //
+    "sys_newlstat",                //
+    "sys_poll",                    //
+    "sys_lseek",                   //
+    "sys_mmap",                    //
+    "sys_mprotect",                //
+    "sys_munmap",                  //
+    "sys_brk",                     //
+    "sys_rt_sigaction",            //
+    "sys_rt_sigprocmask",          //
+    "stub_rt_sigreturn",           //
+    "sys_ioctl",                   //
+    "sys_pread64",                 //
+    "sys_pwrite64",                //
+    "sys_readv",                   //
+    "sys_writev",                  //
+    "sys_access",                  //
+    "sys_pipe",                    //
+    "sys_select",                  //
+    "sys_sched_yield",             //
+    "sys_mremap",                  //
+    "sys_msync",                   //
+    "sys_mincore",                 //
+    "sys_madvise",                 //
+    "sys_shmget",                  //
+    "sys_shmat",                   //
+    "sys_shmctl",                  //
+    "sys_dup",                     //
+    "sys_dup2",                    //
+    "sys_pause",                   //
+    "sys_nanosleep",               //
+    "sys_getitimer",               //
+    "sys_alarm",                   //
+    "sys_setitimer",               //
+    "sys_getpid",                  //
+    "sys_sendfile64",              //
+    "sys_socket",                  //
+    "sys_connect",                 //
+    "sys_accept",                  //
+    "sys_sendto",                  //
+    "sys_recvfrom",                //
+    "sys_sendmsg",                 //
+    "sys_recvmsg",                 //
+    "sys_shutdown",                //
+    "sys_bind",                    //
+    "sys_listen",                  //
+    "sys_getsockname",             //
+    "sys_getpeername",             //
+    "sys_socketpair",              //
+    "sys_setsockopt",              //
+    "sys_getsockopt",              //
+    "stub_clone",                  //
+    "stub_fork",                   //
+    "stub_vfork",                  //
+    "stub_execve",                 //
+    "sys_exit",                    //
+    "sys_wait4",                   //
+    "sys_kill",                    //
+    "sys_newuname",                //
+    "sys_semget",                  //
+    "sys_semop",                   //
+    "sys_semctl",                  //
+    "sys_shmdt",                   //
+    "sys_msgget",                  //
+    "sys_msgsnd",                  //
+    "sys_msgrcv",                  //
+    "sys_msgctl",                  //
+    "sys_fcntl",                   //
+    "sys_flock",                   //
+    "sys_fsync",                   //
+    "sys_fdatasync",               //
+    "sys_truncate",                //
+    "sys_ftruncate",               //
+    "sys_getdents",                //
+    "sys_getcwd",                  //
+    "sys_chdir",                   //
+    "sys_fchdir",                  //
+    "sys_rename",                  //
+    "sys_mkdir",                   //
+    "sys_rmdir",                   //
+    "sys_creat",                   //
+    "sys_link",                    //
+    "sys_unlink",                  //
+    "sys_symlink",                 //
+    "sys_readlink",                //
+    "sys_chmod",                   //
+    "sys_fchmod",                  //
+    "sys_chown",                   //
+    "sys_fchown",                  //
+    "sys_lchown",                  //
+    "sys_umask",                   //
+    "sys_gettimeofday",            //
+    "sys_getrlimit",               //
+    "sys_getrusage",               //
+    "sys_sysinfo",                 //
+    "sys_times",                   //
+    "sys_ptrace",                  //
+    "sys_getuid",                  //
+    "sys_syslog",                  //
+    "sys_getgid",                  //
+    "sys_setuid",                  //
+    "sys_setgid",                  //
+    "sys_geteuid",                 //
+    "sys_getegid",                 //
+    "sys_setpgid",                 //
+    "sys_getppid",                 //
+    "sys_getpgrp",                 //
+    "sys_setsid",                  //
+    "sys_setreuid",                //
+    "sys_setregid",                //
+    "sys_getgroups",               //
+    "sys_setgroups",               //
+    "sys_setresuid",               //
+    "sys_getresuid",               //
+    "sys_setresgid",               //
+    "sys_getresgid",               //
+    "sys_getpgid",                 //
+    "sys_setfsuid",                //
+    "sys_setfsgid",                //
+    "sys_getsid",                  //
+    "sys_capget",                  //
+    "sys_capset",                  //
+    "sys_rt_sigpending",           //
+    "sys_rt_sigtimedwait",         //
+    "sys_rt_sigqueueinfo",         //
+    "sys_rt_sigsuspend",           //
+    "sys_sigaltstack",             //
+    "sys_utime",                   //
+    "sys_mknod",                   //
+    "",                            // uselib
+    "sys_personality",             //
+    "sys_ustat",                   //
+    "sys_statfs",                  //
+    "sys_fstatfs",                 //
+    "sys_sysfs",                   //
+    "sys_getpriority",             //
+    "sys_setpriority",             //
+    "sys_sched_setparam",          //
+    "sys_sched_getparam",          //
+    "sys_sched_setscheduler",      //
+    "sys_sched_getscheduler",      //
+    "sys_sched_get_priority_max",  //
+    "sys_sched_get_priority_min",  //
+    "sys_sched_rr_get_interval",   //
+    "sys_mlock",                   //
+    "sys_munlock",                 //
+    "sys_mlockall",                //
+    "sys_munlockall",              //
+    "sys_vhangup",                 //
+    "sys_modify_ldt",              //
+    "sys_pivot_root",              //
+    "sys_sysctl",                  //
+    "sys_prctl",                   //
+    "sys_arch_prctl",              //
+    "sys_adjtimex",                //
+    "sys_setrlimit",               //
+    "sys_chroot",                  //
+    "sys_sync",                    //
+    "sys_acct",                    //
+    "sys_settimeofday",            //
+    "sys_mount",                   //
+    "sys_umount",                  //
+    "sys_swapon",                  //
+    "sys_swapoff",                 //
+    "sys_reboot",                  //
+    "sys_sethostname",             //
+    "sys_setdomainname",           //
+    "stub_iopl",                   //
+    "sys_ioperm",                  //
+    "",                            // create_module
+    "sys_init_module",             //
+    "sys_delete_module",           //
+    "",                            // get_kernel_syms
+    "",                            // query_module
+    "sys_quotactl",                //
+    "",                            // nfsservctl
+    "",                            // getpmsg
+    "",                            // putpmsg
+    "",                            // afs_syscall
+    "",                            // tuxcall
+    "",                            // security
+    "sys_gettid",                  //
+    "sys_readahead",               //
+    "sys_setxattr",                //
+    "sys_lsetxattr",               //
+    "sys_fsetxattr",               //
+    "sys_getxattr",                //
+    "sys_lgetxattr",               //
+    "sys_fgetxattr",               //
+    "sys_listxattr",               //
+    "sys_llistxattr",              //
+    "sys_flistxattr",              //
+    "sys_removexattr",             //
+    "sys_lremovexattr",            //
+    "sys_fremovexattr",            //
+    "sys_tkill",                   //
+    "sys_time",                    //
+    "sys_futex",                   //
+    "sys_sched_setaffinity",       //
+    "sys_sched_getaffinity",       //
+    "",                            // set_thread_area
+    "sys_io_setup",                //
+    "sys_io_destroy",              //
+    "sys_io_getevents",            //
+    "sys_io_submit",               //
+    "sys_io_cancel",               //
+    "",                            // get_thread_area
+    "sys_lookup_dcookie",          //
+    "sys_epoll_create",            //
+    "",                            // epoll_ctl_old
+    "",                            // epoll_wait_old
+    "sys_remap_file_pages",        //
+    "sys_getdents64",              //
+    "sys_set_tid_address",         //
+    "sys_restart_syscall",         //
+    "sys_semtimedop",              //
+    "sys_fadvise64",               //
+    "sys_timer_create",            //
+    "sys_timer_settime",           //
+    "sys_timer_gettime",           //
+    "sys_timer_getoverrun",        //
+    "sys_timer_delete",            //
+    "sys_clock_settime",           //
+    "sys_clock_gettime",           //
+    "sys_clock_getres",            //
+    "sys_clock_nanosleep",         //
+    "sys_exit_group",              //
+    "sys_epoll_wait",              //
+    "sys_epoll_ctl",               //
+    "sys_tgkill",                  //
+    "sys_utimes",                  //
+    "",                            // vserver
+    "sys_mbind",                   //
+    "sys_set_mempolicy",           //
+    "sys_get_mempolicy",           //
+    "sys_mq_open",                 //
+    "sys_mq_unlink",               //
+    "sys_mq_timedsend",            //
+    "sys_mq_timedreceive",         //
+    "sys_mq_notify",               //
+    "sys_mq_getsetattr",           //
+    "sys_kexec_load",              //
+    "sys_waitid",                  //
+    "sys_add_key",                 //
+    "sys_request_key",             //
+    "sys_keyctl",                  //
+    "sys_ioprio_set",              //
+    "sys_ioprio_get",              //
+    "sys_inotify_init",            //
+    "sys_inotify_add_watch",       //
+    "sys_inotify_rm_watch",        //
+    "sys_migrate_pages",           //
+    "sys_openat",                  //
+    "sys_mkdirat",                 //
+    "sys_mknodat",                 //
+    "sys_fchownat",                //
+    "sys_futimesat",               //
+    "sys_newfstatat",              //
+    "sys_unlinkat",                //
+    "sys_renameat",                //
+    "sys_linkat",                  //
+    "sys_symlinkat",               //
+    "sys_readlinkat",              //
+    "sys_fchmodat",                //
+    "sys_faccessat",               //
+    "sys_pselect6",                //
+    "sys_ppoll",                   //
+    "sys_unshare",                 //
+    "sys_set_robust_list",         //
+    "sys_get_robust_list",         //
+    "sys_splice",                  //
+    "sys_tee",                     //
+    "sys_sync_file_range",         //
+    "sys_vmsplice",                //
+    "sys_move_pages",              //
+    "sys_utimensat",               //
+    "sys_epoll_pwait",             //
+    "sys_signalfd",                //
+    "sys_timerfd_create",          //
+    "sys_eventfd",                 //
+    "sys_fallocate",               //
+    "sys_timerfd_settime",         //
+    "sys_timerfd_gettime",         //
+    "sys_accept4",                 //
+    "sys_signalfd4",               //
+    "sys_eventfd2",                //
+    "sys_epoll_create1",           //
+    "sys_dup3",                    //
+    "sys_pipe2",                   //
+    "sys_inotify_init1",           //
+    "sys_preadv",                  //
+    "sys_pwritev",                 //
+    "sys_rt_tgsigqueueinfo",       //
+    "sys_perf_event_open",         //
+    "sys_recvmmsg",                //
+    "sys_fanotify_init",           //
+    "sys_fanotify_mark",           //
+    "sys_prlimit64",               //
+    "sys_name_to_handle_at",       //
+    "sys_open_by_handle_at",       //
+    "sys_clock_adjtime",           //
+    "sys_syncfs",                  //
+    "sys_sendmmsg",                //
+    "sys_setns",                   //
+    "sys_getcpu",                  //
+    "sys_process_vm_readv",        //
+    "sys_process_vm_writev",       //
+    "sys_kcmp",                    //
+    "sys_finit_module",            //
+}};
+
+// When we don't know the architecture map every syscall number to
+// null string.
+constexpr std::array<const char*, kSyscallCount> unknown_to_syscall = {{}};
+
+}  // namespace
+
+SyscallTracker::SyscallTracker(TraceProcessorContext* context)
+    : context_(context) {
+  // This sets arch_syscall_to_string_id_
+  SetArchitecture(kUnknown);
+}
+
+SyscallTracker::~SyscallTracker() = default;
+
+void SyscallTracker::SetArchitecture(Architecture arch) {
+  const std::array<const char*, kSyscallCount>* arch_to_generic_syscall_number;
+  switch (arch) {
+    case kAarch64:
+      arch_to_generic_syscall_number = &aarch64_to_syscall;
+      break;
+    case kX86_64:
+      arch_to_generic_syscall_number = &x86_64_to_syscall;
+      break;
+    case kUnknown:
+      arch_to_generic_syscall_number = &unknown_to_syscall;
+      break;
+  }
+
+  for (size_t i = 0; i < kSyscallCount; i++) {
+    const char* name = (*arch_to_generic_syscall_number)[i];
+    StringId id =
+        context_->storage->InternString(name ? name : "UNKNOWN_SYSCALL");
+    arch_syscall_to_string_id_[i] = id;
+    if (name && !strcmp(name, "sys_write"))
+      sys_write_string_id_ = id;
+  }
+}
+
+void SyscallTracker::Enter(int64_t ts, UniqueTid utid, uint32_t syscall_num) {
+  StringId name = SyscallNumberToStringId(syscall_num);
+  if (!name) {
+    context_->storage->IncrementStats(stats::sys_unknown_syscall);
+    return;
+  }
+
+  context_->slice_tracker->Begin(ts, utid, 0 /* cat */, name);
+}
+
+void SyscallTracker::Exit(int64_t ts, UniqueTid utid, uint32_t syscall_num) {
+  StringId name = SyscallNumberToStringId(syscall_num);
+  if (!name) {
+    context_->storage->IncrementStats(stats::sys_unknown_syscall);
+    return;
+  }
+
+  context_->slice_tracker->End(ts, utid, 0 /* cat */, name);
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/syscall_tracker.h b/src/trace_processor/syscall_tracker.h
new file mode 100644
index 0000000..b6ed8b7
--- /dev/null
+++ b/src/trace_processor/syscall_tracker.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_SYSCALL_TRACKER_H_
+#define SRC_TRACE_PROCESSOR_SYSCALL_TRACKER_H_
+
+#include <tuple>
+
+#include "perfetto/base/string_view.h"
+#include "src/trace_processor/trace_processor_context.h"
+#include "src/trace_processor/trace_storage.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// Maximum syscall number known.
+static constexpr size_t kSyscallCount = 330;
+
+enum Architecture {
+  kUnknown = 0,
+  kAarch64,
+  kX86_64,
+};
+
+class SyscallTracker {
+ public:
+  explicit SyscallTracker(TraceProcessorContext*);
+  SyscallTracker(const SyscallTracker&) = delete;
+  SyscallTracker& operator=(const SyscallTracker&) = delete;
+  virtual ~SyscallTracker();
+
+  void SetArchitecture(Architecture architecture);
+  void Enter(int64_t ts, UniqueTid utid, uint32_t syscall_num);
+  void Exit(int64_t ts, UniqueTid utid, uint32_t syscall_num);
+
+ private:
+  TraceProcessorContext* const context_;
+
+  inline StringId SyscallNumberToStringId(uint32_t syscall) {
+    if (syscall > kSyscallCount)
+      return 0;
+    // We see two write sys calls around each userspace slice that is going via
+    // trace_marker, this violates the assumption that userspace slices are
+    // perfectly nested. For the moment ignore all write sys calls.
+    // TODO(hjd): Remove this limitation.
+    StringId id = arch_syscall_to_string_id_[syscall];
+    if (id == sys_write_string_id_)
+      return 0;
+    return id;
+  }
+
+  // This is table from platform specific syscall number directly to
+  // the relevent StringId (this avoids having to always do two conversions).
+  std::array<StringId, kSyscallCount> arch_syscall_to_string_id_;
+  StringId sys_write_string_id_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_SYSCALL_TRACKER_H_
diff --git a/src/trace_processor/syscall_tracker_unittest.cc b/src/trace_processor/syscall_tracker_unittest.cc
new file mode 100644
index 0000000..4b60dac
--- /dev/null
+++ b/src/trace_processor/syscall_tracker_unittest.cc
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/syscall_tracker.h"
+
+#include "src/trace_processor/slice_tracker.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+using ::testing::_;
+using ::testing::SaveArg;
+
+class MockSliceTracker : public SliceTracker {
+ public:
+  MockSliceTracker(TraceProcessorContext* context) : SliceTracker(context) {}
+  virtual ~MockSliceTracker() = default;
+
+  MOCK_METHOD4(
+      Begin,
+      void(int64_t timestamp, UniqueTid utid, StringId cat, StringId name));
+  MOCK_METHOD4(
+      End,
+      void(int64_t timestamp, UniqueTid utid, StringId cat, StringId name));
+};
+
+class SyscallTrackerTest : public ::testing::Test {
+ public:
+  SyscallTrackerTest() {
+    slice_tracker = new MockSliceTracker(&context);
+    context.storage.reset(new TraceStorage());
+    context.slice_tracker.reset(slice_tracker);
+    context.syscall_tracker.reset(new SyscallTracker(&context));
+  }
+
+ protected:
+  TraceProcessorContext context;
+  MockSliceTracker* slice_tracker;
+};
+
+TEST_F(SyscallTrackerTest, ReportUnknownSyscalls) {
+  StringId begin_name = 0;
+  StringId end_name = 0;
+  EXPECT_CALL(*slice_tracker, Begin(100, 42, 0, _))
+      .WillOnce(SaveArg<3>(&begin_name));
+  EXPECT_CALL(*slice_tracker, End(110, 42, 0, _))
+      .WillOnce(SaveArg<3>(&end_name));
+
+  context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 57 /*sys_read*/);
+  context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 57 /*sys_read*/);
+  EXPECT_EQ(context.storage->GetString(begin_name), "UNKNOWN_SYSCALL");
+  EXPECT_EQ(context.storage->GetString(end_name), "UNKNOWN_SYSCALL");
+}
+
+TEST_F(SyscallTrackerTest, IgnoreWriteSyscalls) {
+  context.syscall_tracker->SetArchitecture(kAarch64);
+  EXPECT_CALL(*slice_tracker, Begin(_, _, _, _)).Times(0);
+  EXPECT_CALL(*slice_tracker, End(_, _, _, _)).Times(0);
+
+  context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 58 /*sys_write*/);
+  context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 58 /*sys_write*/);
+}
+
+TEST_F(SyscallTrackerTest, Aarch64) {
+  StringId begin_name = 0;
+  StringId end_name = 0;
+  EXPECT_CALL(*slice_tracker, Begin(100, 42, 0, _))
+      .WillOnce(SaveArg<3>(&begin_name));
+  EXPECT_CALL(*slice_tracker, End(110, 42, 0, _))
+      .WillOnce(SaveArg<3>(&end_name));
+
+  context.syscall_tracker->SetArchitecture(kAarch64);
+  context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 57 /*sys_read*/);
+  context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 57 /*sys_read*/);
+  EXPECT_EQ(context.storage->GetString(begin_name), "sys_read");
+  EXPECT_EQ(context.storage->GetString(end_name), "sys_read");
+}
+
+TEST_F(SyscallTrackerTest, x8664) {
+  StringId begin_name = 0;
+  StringId end_name = 0;
+  EXPECT_CALL(*slice_tracker, Begin(100, 42, 0, _))
+      .WillOnce(SaveArg<3>(&begin_name));
+  EXPECT_CALL(*slice_tracker, End(110, 42, 0, _))
+      .WillOnce(SaveArg<3>(&end_name));
+
+  context.syscall_tracker->SetArchitecture(kX86_64);
+  context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 0 /*sys_read*/);
+  context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 0 /*sys_read*/);
+  EXPECT_EQ(context.storage->GetString(begin_name), "sys_read");
+  EXPECT_EQ(context.storage->GetString(end_name), "sys_read");
+}
+
+TEST_F(SyscallTrackerTest, SyscallNumberTooLarge) {
+  EXPECT_CALL(*slice_tracker, Begin(_, _, _, _)).Times(0);
+  EXPECT_CALL(*slice_tracker, End(_, _, _, _)).Times(0);
+
+  context.syscall_tracker->SetArchitecture(kAarch64);
+  context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 1024);
+  context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 1024);
+}
+
+}  // namespace
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc
index eb98878..7155348 100644
--- a/src/trace_processor/trace_processor_context.cc
+++ b/src/trace_processor/trace_processor_context.cc
@@ -24,6 +24,7 @@
 #include "src/trace_processor/process_tracker.h"
 #include "src/trace_processor/proto_trace_parser.h"
 #include "src/trace_processor/slice_tracker.h"
+#include "src/trace_processor/syscall_tracker.h"
 #include "src/trace_processor/trace_sorter.h"
 
 namespace perfetto {
diff --git a/src/trace_processor/trace_processor_context.h b/src/trace_processor/trace_processor_context.h
index 3d4e3a0..8bbaf73 100644
--- a/src/trace_processor/trace_processor_context.h
+++ b/src/trace_processor/trace_processor_context.h
@@ -24,11 +24,12 @@
 
 class ArgsTracker;
 class ChunkedTraceReader;
+class ClockTracker;
 class EventTracker;
 class ProcessTracker;
 class ProtoTraceParser;
 class SliceTracker;
-class ClockTracker;
+class SyscallTracker;
 class TraceParser;
 class TraceSorter;
 class TraceStorage;
@@ -41,6 +42,7 @@
   std::unique_ptr<ArgsTracker> args_tracker;
   std::unique_ptr<SliceTracker> slice_tracker;
   std::unique_ptr<ProcessTracker> process_tracker;
+  std::unique_ptr<SyscallTracker> syscall_tracker;
   std::unique_ptr<EventTracker> event_tracker;
   std::unique_ptr<ClockTracker> clock_tracker;
   std::unique_ptr<TraceStorage> storage;
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index e4fb706..162baa4 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -43,6 +43,7 @@
 #include "src/trace_processor/sqlite3_str_split.h"
 #include "src/trace_processor/stats_table.h"
 #include "src/trace_processor/string_table.h"
+#include "src/trace_processor/syscall_tracker.h"
 #include "src/trace_processor/table.h"
 #include "src/trace_processor/thread_table.h"
 #include "src/trace_processor/trace_sorter.h"
@@ -167,6 +168,7 @@
   context_.event_tracker.reset(new EventTracker(&context_));
   context_.proto_parser.reset(new ProtoTraceParser(&context_));
   context_.process_tracker.reset(new ProcessTracker(&context_));
+  context_.syscall_tracker.reset(new SyscallTracker(&context_));
   context_.clock_tracker.reset(new ClockTracker(&context_));
   context_.sorter.reset(
       new TraceSorter(&context_, static_cast<int64_t>(cfg.window_size_ns)));
diff --git a/test/trace_processor/index b/test/trace_processor/index
index 2dd05b0..8dcc25a 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -52,7 +52,6 @@
 ../data/android_sched_and_ps.pb stats.sql android_sched_and_ps_stats.out
 
 # Syscalls
-../data/sys.pb sys_summary.sql sys_summary_sys.out
 syscall.py sys.sql sys_syscall.out
 
 # Power rails
diff --git a/test/trace_processor/synth_common.py b/test/trace_processor/synth_common.py
index 70d0cc1..c454b69 100644
--- a/test/trace_processor/synth_common.py
+++ b/test/trace_processor/synth_common.py
@@ -27,6 +27,10 @@
     self.proc_map = {}
     self.proc_map[0] = "idle_thread"
 
+  def add_system_info(self, arch=None):
+    self.packet = self.trace.packet.add()
+    self.packet.system_info.utsname.machine = arch
+
   def add_ftrace_packet(self, cpu):
     self.packet = self.trace.packet.add()
     self.packet.ftrace_events.cpu = cpu
diff --git a/test/trace_processor/sys_summary.sql b/test/trace_processor/sys_summary.sql
deleted file mode 100644
index 8129767..0000000
--- a/test/trace_processor/sys_summary.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-select name, count(*)
-from slices
-where name LIKE "sys_%"
-group by name
diff --git a/test/trace_processor/sys_summary_sys.out b/test/trace_processor/sys_summary_sys.out
deleted file mode 100644
index 5451e2f..0000000
--- a/test/trace_processor/sys_summary_sys.out
+++ /dev/null
@@ -1,13 +0,0 @@
-"name","count(*)"
-"sys_chdir",53
-"sys_close",88
-"sys_creat",429
-"sys_execve",262
-"sys_exit",3424
-"sys_fork",616
-"sys_link",1
-"sys_open",518
-"sys_read",579
-"sys_restart_syscall",4440
-"sys_time",23
-"sys_unlink",232
diff --git a/test/trace_processor/sys_syscall.out b/test/trace_processor/sys_syscall.out
index 4fbf1ad..d781668 100644
--- a/test/trace_processor/sys_syscall.out
+++ b/test/trace_processor/sys_syscall.out
@@ -1,3 +1,3 @@
 "ts","dur","name"
-100,6,"sys_restart_syscall"
-105,5,"sys_exit"
+100,6,"sys_io_setup"
+105,5,"sys_io_destroy"
diff --git a/test/trace_processor/syscall.py b/test/trace_processor/syscall.py
index 4211cec..64bde87 100644
--- a/test/trace_processor/syscall.py
+++ b/test/trace_processor/syscall.py
@@ -19,12 +19,15 @@
 import synth_common
 
 trace = synth_common.create_trace()
+trace.add_system_info(arch='aarch64')
+
 trace.add_process_tree_packet()
 trace.add_process(pid=1, ppid=0, cmdline="init")
 trace.add_process(pid=2, ppid=1, cmdline="two_thread_process")
 trace.add_process(pid=4, ppid=1, cmdline="single_thread_process")
 trace.add_thread(tid=3, tgid=2, cmdline="two_thread_process")
 
+
 trace.add_ftrace_packet(cpu=0)
 trace.add_sys_enter(ts=100, tid=1, id=0)
 trace.add_sys_enter(ts=105, tid=2, id=1)