linux-perf-0.3: ghc-events-perf/ghc-events-perf-record.hs
-----------------------------------------------------------------------------
-- |
-- Copyright : (c) 2012 Bernie Pope, Mikolaj Konarski
-- License : BSD-style
-- Maintainer : florbitous@gmail.com
-- Stability : experimental
-- Portability : ghc
--
-- A tool to @perf record@ a trace of another program.
--
-- The Linux performance counter tool @perf@ can record events for a given
-- Haskell program (profilee). This tool runs @perf@, adding our default set
-- of options. In particular, it specifies our default set
-- of events to be recorded.
--
-- Usage:
--
-- > ghc-events-perf-record [--RTS]
-- > [ +GhcEventsPerf [record-args ... ] -GhcEventsPerf ]
-- > program-name [program-args ... ]
--
-- Getting help:
--
-- > ghc-events-perf-record +GhcEventsPerf -h
--
-- The --RTS is to stop ghc from grabbing any +RTS ... -RTS commands from
-- the command line.
--
-----------------------------------------------------------------------------
module Main where
import System.Posix.Process
import System.Environment
import System.Exit
import System.Console.GetOpt
import Data.Char (isDigit)
import System.Directory
(findExecutable, getPermissions, executable, doesFileExist)
import System.FilePath (splitFileName)
-- | Process arguments and run the main machinery.
main :: IO ()
main = getArgs >>= command
command :: [String] -> IO ()
command argv = do
let (recPerfArgv, profileeArgv) = grabGhcEventsPerfArgv argv
recPerfOptions <- parseGhcEventsPerfOptions recPerfArgv
profile recPerfOptions profileeArgv
-- | Profile the given program with the given options.
profile :: Options -> [String] -> IO ()
profile _options [] = ioError $ userError ("You did not supply a name of a program to profile")
profile options (profileeCommand:profileeArgs) = do
profileePath <- checkProfilee profileeCommand
-- run perf record with the profilee command
perfProcess options profileePath profileeArgs
-- | Check if the profilee program exists and is executable.
checkProfilee :: FilePath -> IO FilePath
checkProfilee profileeCommand = do
let (profileeDir, _profileeFile) = splitFileName profileeCommand
profileePath <-
if null profileeDir
-- profilee program name was not prefixed with a directory path
then do
-- try to look up the program name in the PATH environment
maybeProfileePath <- findExecutable profileeCommand
case maybeProfileePath of
Nothing -> ioError $ userError ("Command: " ++ profileeCommand ++ " not found")
Just profileePath -> return profileePath
else
return profileeCommand
exists <- doesFileExist profileePath
if exists
then do
-- check if we can execute the profilee program
perms <- getPermissions profileePath
if executable perms
then return profileePath
else ioError $ userError ("You do not have permission to execute program: " ++ profileePath)
else ioError $ userError ("File: " ++ profileePath ++ " does not exist")
-- | Options for @ghc-events-perf-record@, some of which are passed on
-- to @perf record@.
data Options = Options
{ options_events :: [String]
, options_mmap :: String
, options_output :: FilePath
, options_help :: Bool
} deriving Show
defaultOptions :: Options
defaultOptions = Options
{ options_events = []
, options_mmap = ""
, options_output = defaultPerfOutputFile
, options_help = False
}
defaultPerfOutputFile :: FilePath
defaultPerfOutputFile = "perf.data"
-- | Parse the command line arguments that appeared between
-- +GhcEventsPerf and -GhcEventsPerf.
parseGhcEventsPerfOptions :: [String] -> IO Options
parseGhcEventsPerfOptions argv =
case getOpt Permute recOptions argv of
(foundOptions, _unknowns, _errors@[]) -> do
let options = foldl (flip id) defaultOptions foundOptions
if options_help options
then putStrLn usage >> exitSuccess
else return options
(_flags, _unknowns , errs@(_:_)) ->
ioError $ userError (concat errs ++ usage)
usage :: String
usage = usageInfo header recOptions
header :: String
header = "Usage: ghc-events-perf-record [--RTS] [ +GhcEventsPerf [record-args ... ] -GhcEventsPerf ] program-name [program-args ... ]"
recOptions :: [OptDescr (Options -> Options)]
recOptions =
[ Option
"e" ["event"]
(ReqArg (\e opts -> opts { options_events = e : options_events opts }) "E")
"Event to trace, instead of default events. Can be specified multiple times."
, Option
"h" ["help"]
(NoArg $ \opts -> opts { options_help = True })
("Display a help message for this program.")
, Option
"o" ["output"]
(ReqArg (\f opts -> opts { options_output = f }) "OUT")
("Output file to store perf record data. " ++
"Defaults to " ++ show defaultPerfOutputFile ++ ".")
, Option
"m" ["mmap-pages"]
(ReqArg (\mm opts -> opts {options_mmap = mm }) "MM")
("Number of mmap data pages. " ++
"Defaults to " ++ defaultMmap ++ ".")
]
-- | Check that a string can be safely intepreted as an integer,
-- otherwise fail with an error message.
safeReadInt :: String -> String -> Int
safeReadInt option cs
| length cs > 0 && all isDigit cs = read cs
| otherwise =
error ("The argument for option " ++ option ++
" should be an integer, but it was " ++ cs)
-- | Cut out all the arguments between +GhcEventsPerf -GhcEventsPerf from the command
-- line. Return two lists: 1) everything between the markers,
-- and 2) everything else.
grabGhcEventsPerfArgv :: [String] -> ([String], [String])
grabGhcEventsPerfArgv cmdline =
(reverse cmdIns, reverse cmdOuts)
where
(cmdIns, cmdOuts) = outside cmdline ([], [])
outside, inside :: [String] -> ([String], [String]) -> ([String], [String])
outside [] acc = acc
outside ("+GhcEventsPerf":rest) acc = inside rest acc
outside (str:rest) (ins, outs) = outside rest (ins, str:outs)
inside [] acc = acc
inside ("-GhcEventsPerf":rest) acc = outside rest acc
inside (str:rest) (ins, outs) = inside rest (str:ins, outs)
-- | Run @perf record@ with our options and the profilee program.
perfProcess :: Options -> FilePath -> [String] -> IO ()
perfProcess options profileeProgram profileeArgs = do
executeFile "perf" True (perfCommand ++ args) Nothing
where
perfCommand = ["record"]
args =
concat [output, frequency, moreTimestamps, mmap, selectedEvents, profilee]
output = ["-o", options_output options]
-- Value 1 means hIgh frequency, needed for tracepoints,
-- but too much traffic for counters/
frequency = ["-c", "1"]
-- From linux-perf-users@vger.kernel.org:
-- The "--timestamp" option adds the timestamps to the samples
-- if it were not otherwise added.
moreTimestamps = ["--timestamp"]
profilee = profileeProgram : profileeArgs
-- If no events were specified on the command line then use the defaults.
selectedEvents
| null optionEvents = mkEventFlags defaultEvents
| otherwise = mkEventFlags optionEvents
where
optionEvents = options_events options
-- If no mmap pages were specified on the command line, use the defaults.
selectedMmap
| null optionMmap = defaultMmap
| otherwise = optionMmap
where
optionMmap = options_mmap options
mmap = ["--mmap-pages", selectedMmap]
mkEventFlags :: [String] -> [String]
mkEventFlags = alternate (repeat "-e")
-- | The default value of the mmap-pages setting.
-- That's an order of magnitude too little to avoid IO/CPU overload
-- with typical examples, but that's the highest permitted value,
-- unless @ghc-events-perf-record@ is run as root.
-- Can be overridden by the user.
defaultMmap :: String
defaultMmap = "128"
-- | Record these events by default unless the user specifies alternatives.
defaultEvents :: [String]
defaultEvents =
[
-- scheduler events to record
"sched:sched_process_exit",
"sched:sched_kthread_stop",
"sched:sched_kthread_stop_ret",
"sched:sched_wakeup",
"sched:sched_wakeup_new",
"sched:sched_switch",
"sched:sched_migrate_task",
"sched:sched_process_free",
"sched:sched_process_exit",
"sched:sched_wait_task",
"sched:sched_process_wait",
"sched:sched_process_fork",
"sched:sched_stat_iowait",
"sched:sched_pi_setprio"
-- These are too frequent, mostly in COMM events, and cause IO/CPU overload:
-- "sched:sched_stat_wait",
-- "sched:sched_stat_sleep",
-- "sched:sched_stat_runtime",
-- system calls to record
-- For raw_syscalls, we currently don't indicate which system call is made.
-- These events are usually too dense, too.
-- "raw_syscalls:sys_enter",
-- "raw_syscalls:sys_exit"
] ++ syscalls3 ++ syscalls4 ++ syscalls5 ++ syscalls6 ++ syscalls7
++ syscalls8 ++ syscalls9 ++ syscalls10 ++ syscalls11
-- Tracing more syscalls causes
-- Error: sys_perf_event_open() syscall returned with 24 (Too many open files)
-- ++ syscalls1 ++ syscalls2
where
-- The list taken from http://www.berniepope.id.au/linuxPerfEvents.html.
syscalls1 =
[
"syscalls:sys_enter_socket",
"syscalls:sys_exit_socket",
"syscalls:sys_enter_socketpair",
"syscalls:sys_exit_socketpair",
"syscalls:sys_enter_bind",
"syscalls:sys_exit_bind",
"syscalls:sys_enter_listen",
"syscalls:sys_exit_listen",
"syscalls:sys_enter_accept4",
"syscalls:sys_exit_accept4",
"syscalls:sys_enter_accept",
"syscalls:sys_exit_accept",
"syscalls:sys_enter_connect",
"syscalls:sys_exit_connect",
"syscalls:sys_enter_getsockname",
"syscalls:sys_exit_getsockname",
"syscalls:sys_enter_getpeername",
"syscalls:sys_exit_getpeername",
"syscalls:sys_enter_sendto",
"syscalls:sys_exit_sendto",
"syscalls:sys_enter_recvfrom",
"syscalls:sys_exit_recvfrom",
"syscalls:sys_enter_setsockopt",
"syscalls:sys_exit_setsockopt",
"syscalls:sys_enter_getsockopt",
"syscalls:sys_exit_getsockopt",
"syscalls:sys_enter_shutdown",
"syscalls:sys_exit_shutdown",
"syscalls:sys_enter_sendmsg",
"syscalls:sys_exit_sendmsg",
"syscalls:sys_enter_sendmmsg",
"syscalls:sys_exit_sendmmsg",
"syscalls:sys_enter_recvmsg",
"syscalls:sys_exit_recvmsg",
"syscalls:sys_enter_recvmmsg",
"syscalls:sys_exit_recvmmsg",
"syscalls:sys_enter_add_key",
"syscalls:sys_exit_add_key",
"syscalls:sys_enter_request_key",
"syscalls:sys_exit_request_key",
"syscalls:sys_enter_keyctl",
"syscalls:sys_exit_keyctl",
"syscalls:sys_enter_mq_open",
"syscalls:sys_exit_mq_open",
"syscalls:sys_enter_mq_unlink",
"syscalls:sys_exit_mq_unlink",
"syscalls:sys_enter_mq_timedsend",
"syscalls:sys_exit_mq_timedsend",
"syscalls:sys_enter_mq_timedreceive",
"syscalls:sys_exit_mq_timedreceive"
]
syscalls2 =
[
"syscalls:sys_enter_mq_notify",
"syscalls:sys_exit_mq_notify",
"syscalls:sys_enter_mq_getsetattr",
"syscalls:sys_exit_mq_getsetattr",
"syscalls:sys_enter_shmget",
"syscalls:sys_exit_shmget",
"syscalls:sys_enter_shmctl",
"syscalls:sys_exit_shmctl",
"syscalls:sys_enter_shmat",
"syscalls:sys_exit_shmat",
"syscalls:sys_enter_shmdt",
"syscalls:sys_exit_shmdt",
"syscalls:sys_enter_semget",
"syscalls:sys_exit_semget",
"syscalls:sys_enter_semtimedop",
"syscalls:sys_exit_semtimedop",
"syscalls:sys_enter_semop",
"syscalls:sys_exit_semop",
"syscalls:sys_enter_msgget",
"syscalls:sys_exit_msgget",
"syscalls:sys_enter_msgctl",
"syscalls:sys_exit_msgctl",
"syscalls:sys_enter_msgsnd",
"syscalls:sys_exit_msgsnd",
"syscalls:sys_enter_msgrcv",
"syscalls:sys_exit_msgrcv",
"syscalls:sys_enter_quotactl",
"syscalls:sys_exit_quotactl",
"syscalls:sys_enter_name_to_handle_at",
"syscalls:sys_exit_name_to_handle_at",
"syscalls:sys_enter_open_by_handle_at",
"syscalls:sys_exit_open_by_handle_at",
-- Not present on some systems
-- "syscalls:sys_enter_nfsservctl",
-- "syscalls:sys_exit_nfsservctl",
"syscalls:sys_enter_flock",
"syscalls:sys_exit_flock",
"syscalls:sys_enter_io_setup",
"syscalls:sys_exit_io_setup",
"syscalls:sys_enter_io_destroy",
"syscalls:sys_exit_io_destroy",
"syscalls:sys_enter_io_submit",
"syscalls:sys_exit_io_submit",
"syscalls:sys_enter_io_cancel",
"syscalls:sys_exit_io_cancel",
"syscalls:sys_enter_io_getevents",
"syscalls:sys_exit_io_getevents",
"syscalls:sys_enter_eventfd2",
"syscalls:sys_exit_eventfd2",
"syscalls:sys_enter_eventfd",
"syscalls:sys_exit_eventfd"
]
syscalls3 =
[
"syscalls:sys_enter_timerfd_create",
"syscalls:sys_exit_timerfd_create",
"syscalls:sys_enter_timerfd_settime",
"syscalls:sys_exit_timerfd_settime",
"syscalls:sys_enter_timerfd_gettime",
"syscalls:sys_exit_timerfd_gettime",
"syscalls:sys_enter_signalfd4",
"syscalls:sys_exit_signalfd4",
"syscalls:sys_enter_signalfd",
"syscalls:sys_exit_signalfd",
"syscalls:sys_enter_epoll_create1",
"syscalls:sys_exit_epoll_create1",
"syscalls:sys_enter_epoll_create",
"syscalls:sys_exit_epoll_create",
"syscalls:sys_enter_epoll_ctl",
"syscalls:sys_exit_epoll_ctl",
"syscalls:sys_enter_epoll_wait",
"syscalls:sys_exit_epoll_wait",
"syscalls:sys_enter_epoll_pwait",
"syscalls:sys_exit_epoll_pwait",
"syscalls:sys_enter_fanotify_init",
"syscalls:sys_exit_fanotify_init",
"syscalls:sys_enter_inotify_init1",
"syscalls:sys_exit_inotify_init1",
"syscalls:sys_enter_inotify_init",
"syscalls:sys_exit_inotify_init",
"syscalls:sys_enter_inotify_add_watch",
"syscalls:sys_exit_inotify_add_watch",
"syscalls:sys_enter_inotify_rm_watch",
"syscalls:sys_exit_inotify_rm_watch",
"syscalls:sys_enter_ioprio_set",
"syscalls:sys_exit_ioprio_set",
"syscalls:sys_enter_ioprio_get",
"syscalls:sys_exit_ioprio_get",
"syscalls:sys_enter_statfs",
"syscalls:sys_exit_statfs",
"syscalls:sys_enter_fstatfs",
"syscalls:sys_exit_fstatfs",
"syscalls:sys_enter_ustat",
"syscalls:sys_exit_ustat",
"syscalls:sys_enter_utime",
"syscalls:sys_exit_utime",
"syscalls:sys_enter_utimensat",
"syscalls:sys_exit_utimensat",
"syscalls:sys_enter_futimesat",
"syscalls:sys_exit_futimesat",
"syscalls:sys_enter_utimes",
"syscalls:sys_exit_utimes",
"syscalls:sys_enter_sync",
"syscalls:sys_exit_sync"
]
syscalls4 =
[
"syscalls:sys_enter_syncfs",
"syscalls:sys_exit_syncfs",
"syscalls:sys_enter_fsync",
"syscalls:sys_exit_fsync",
"syscalls:sys_enter_fdatasync",
"syscalls:sys_exit_fdatasync",
"syscalls:sys_enter_vmsplice",
"syscalls:sys_exit_vmsplice",
"syscalls:sys_enter_splice",
"syscalls:sys_exit_splice",
"syscalls:sys_enter_tee",
"syscalls:sys_exit_tee",
"syscalls:sys_enter_setxattr",
"syscalls:sys_exit_setxattr",
"syscalls:sys_enter_lsetxattr",
"syscalls:sys_exit_lsetxattr",
"syscalls:sys_enter_fsetxattr",
"syscalls:sys_exit_fsetxattr",
"syscalls:sys_enter_getxattr",
"syscalls:sys_exit_getxattr",
"syscalls:sys_enter_lgetxattr",
"syscalls:sys_exit_lgetxattr",
"syscalls:sys_enter_fgetxattr",
"syscalls:sys_exit_fgetxattr",
"syscalls:sys_enter_listxattr",
"syscalls:sys_exit_listxattr",
"syscalls:sys_enter_llistxattr",
"syscalls:sys_exit_llistxattr",
"syscalls:sys_enter_flistxattr",
"syscalls:sys_exit_flistxattr",
"syscalls:sys_enter_removexattr",
"syscalls:sys_exit_removexattr",
"syscalls:sys_enter_lremovexattr",
"syscalls:sys_exit_lremovexattr",
"syscalls:sys_enter_fremovexattr",
"syscalls:sys_exit_fremovexattr",
"syscalls:sys_enter_umount",
"syscalls:sys_exit_umount",
"syscalls:sys_enter_mount",
"syscalls:sys_exit_mount",
"syscalls:sys_enter_pivot_root",
"syscalls:sys_exit_pivot_root",
"syscalls:sys_enter_sysfs",
"syscalls:sys_exit_sysfs",
"syscalls:sys_enter_getcwd",
"syscalls:sys_exit_getcwd",
"syscalls:sys_enter_select",
"syscalls:sys_exit_select",
"syscalls:sys_enter_pselect6",
"syscalls:sys_exit_pselect6"
]
syscalls5 =
[
"syscalls:sys_enter_poll",
"syscalls:sys_exit_poll",
"syscalls:sys_enter_ppoll",
"syscalls:sys_exit_ppoll",
"syscalls:sys_enter_getdents",
"syscalls:sys_exit_getdents",
"syscalls:sys_enter_getdents64",
"syscalls:sys_exit_getdents64",
"syscalls:sys_enter_ioctl",
"syscalls:sys_exit_ioctl",
"syscalls:sys_enter_dup3",
"syscalls:sys_exit_dup3",
"syscalls:sys_enter_dup2",
"syscalls:sys_exit_dup2",
"syscalls:sys_enter_dup",
"syscalls:sys_exit_dup",
"syscalls:sys_enter_fcntl",
"syscalls:sys_exit_fcntl",
"syscalls:sys_enter_mknodat",
"syscalls:sys_exit_mknodat",
"syscalls:sys_enter_mknod",
"syscalls:sys_exit_mknod",
"syscalls:sys_enter_mkdirat",
"syscalls:sys_exit_mkdirat",
"syscalls:sys_enter_mkdir",
"syscalls:sys_exit_mkdir",
"syscalls:sys_enter_rmdir",
"syscalls:sys_exit_rmdir",
"syscalls:sys_enter_unlinkat",
"syscalls:sys_exit_unlinkat",
"syscalls:sys_enter_unlink",
"syscalls:sys_exit_unlink",
"syscalls:sys_enter_symlinkat",
"syscalls:sys_exit_symlinkat",
"syscalls:sys_enter_symlink",
"syscalls:sys_exit_symlink",
"syscalls:sys_enter_linkat",
"syscalls:sys_exit_linkat",
"syscalls:sys_enter_link",
"syscalls:sys_exit_link",
"syscalls:sys_enter_renameat",
"syscalls:sys_exit_renameat",
"syscalls:sys_enter_rename",
"syscalls:sys_exit_rename",
"syscalls:sys_enter_pipe2",
"syscalls:sys_exit_pipe2",
"syscalls:sys_enter_pipe",
"syscalls:sys_exit_pipe"
]
syscalls6 =
[
"syscalls:sys_enter_newstat",
"syscalls:sys_exit_newstat",
"syscalls:sys_enter_newlstat",
"syscalls:sys_exit_newlstat",
"syscalls:sys_enter_newfstatat",
"syscalls:sys_exit_newfstatat",
"syscalls:sys_enter_newfstat",
"syscalls:sys_exit_newfstat",
"syscalls:sys_enter_readlinkat",
"syscalls:sys_exit_readlinkat",
"syscalls:sys_enter_readlink",
"syscalls:sys_exit_readlink",
"syscalls:sys_enter_lseek",
"syscalls:sys_exit_lseek",
"syscalls:sys_enter_read",
"syscalls:sys_exit_read",
"syscalls:sys_enter_write",
"syscalls:sys_exit_write",
"syscalls:sys_enter_readv",
"syscalls:sys_exit_readv",
"syscalls:sys_enter_writev",
"syscalls:sys_exit_writev",
"syscalls:sys_enter_preadv",
"syscalls:sys_exit_preadv",
"syscalls:sys_enter_pwritev",
"syscalls:sys_exit_pwritev",
"syscalls:sys_enter_sendfile64",
"syscalls:sys_exit_sendfile64",
"syscalls:sys_enter_truncate",
"syscalls:sys_exit_truncate",
"syscalls:sys_enter_ftruncate",
"syscalls:sys_exit_ftruncate",
"syscalls:sys_enter_faccessat",
"syscalls:sys_exit_faccessat",
"syscalls:sys_enter_access",
"syscalls:sys_exit_access",
"syscalls:sys_enter_chdir",
"syscalls:sys_exit_chdir",
"syscalls:sys_enter_fchdir",
"syscalls:sys_exit_fchdir",
"syscalls:sys_enter_chroot",
"syscalls:sys_exit_chroot",
"syscalls:sys_enter_fchmod",
"syscalls:sys_exit_fchmod",
"syscalls:sys_enter_fchmodat",
"syscalls:sys_exit_fchmodat",
"syscalls:sys_enter_chmod",
"syscalls:sys_exit_chmod",
"syscalls:sys_enter_chown",
"syscalls:sys_exit_chown",
"syscalls:sys_enter_fchownat",
"syscalls:sys_exit_fchownat"
]
syscalls7 =
[
"syscalls:sys_enter_lchown",
"syscalls:sys_exit_lchown",
"syscalls:sys_enter_fchown",
"syscalls:sys_exit_fchown",
"syscalls:sys_enter_open",
"syscalls:sys_exit_open",
"syscalls:sys_enter_openat",
"syscalls:sys_exit_openat",
"syscalls:sys_enter_creat",
"syscalls:sys_exit_creat",
"syscalls:sys_enter_close",
"syscalls:sys_exit_close",
"syscalls:sys_enter_vhangup",
"syscalls:sys_exit_vhangup",
"syscalls:sys_enter_move_pages",
"syscalls:sys_exit_move_pages",
"syscalls:sys_enter_mbind",
"syscalls:sys_exit_mbind",
"syscalls:sys_enter_set_mempolicy",
"syscalls:sys_exit_set_mempolicy",
"syscalls:sys_enter_migrate_pages",
"syscalls:sys_exit_migrate_pages",
"syscalls:sys_enter_get_mempolicy",
"syscalls:sys_exit_get_mempolicy",
"syscalls:sys_enter_swapoff",
"syscalls:sys_exit_swapoff",
"syscalls:sys_enter_swapon",
"syscalls:sys_exit_swapon",
"syscalls:sys_enter_msync",
"syscalls:sys_exit_msync",
"syscalls:sys_enter_mremap",
"syscalls:sys_exit_mremap",
"syscalls:sys_enter_mprotect",
"syscalls:sys_exit_mprotect",
"syscalls:sys_enter_brk",
"syscalls:sys_exit_brk",
"syscalls:sys_enter_munmap",
"syscalls:sys_exit_munmap",
"syscalls:sys_enter_mlock",
"syscalls:sys_exit_mlock",
"syscalls:sys_enter_munlock",
"syscalls:sys_exit_munlock",
"syscalls:sys_enter_mlockall",
"syscalls:sys_exit_mlockall",
"syscalls:sys_enter_munlockall",
"syscalls:sys_exit_munlockall",
"syscalls:sys_enter_mincore",
"syscalls:sys_exit_mincore",
"syscalls:sys_enter_madvise",
"syscalls:sys_exit_madvise",
"syscalls:sys_enter_remap_file_pages",
"syscalls:sys_exit_remap_file_pages"
]
syscalls8 =
[
"syscalls:sys_enter_perf_event_open",
"syscalls:sys_exit_perf_event_open",
"syscalls:sys_enter_kexec_load",
"syscalls:sys_exit_kexec_load",
"syscalls:sys_enter_acct",
"syscalls:sys_exit_acct",
"syscalls:sys_enter_delete_module",
"syscalls:sys_exit_delete_module",
"syscalls:sys_enter_init_module",
"syscalls:sys_exit_init_module",
"syscalls:sys_enter_set_robust_list",
"syscalls:sys_exit_set_robust_list",
"syscalls:sys_enter_get_robust_list",
"syscalls:sys_exit_get_robust_list",
"syscalls:sys_enter_futex",
"syscalls:sys_exit_futex",
"syscalls:sys_enter_getgroups",
"syscalls:sys_exit_getgroups",
"syscalls:sys_enter_setgroups",
"syscalls:sys_exit_setgroups",
"syscalls:sys_enter_setns",
"syscalls:sys_exit_setns",
"syscalls:sys_enter_nanosleep",
"syscalls:sys_exit_nanosleep",
"syscalls:sys_enter_timer_create",
"syscalls:sys_exit_timer_create",
"syscalls:sys_enter_timer_gettime",
"syscalls:sys_exit_timer_gettime",
"syscalls:sys_enter_timer_getoverrun",
"syscalls:sys_exit_timer_getoverrun",
"syscalls:sys_enter_timer_settime",
"syscalls:sys_exit_timer_settime",
"syscalls:sys_enter_timer_delete",
"syscalls:sys_exit_timer_delete",
"syscalls:sys_enter_clock_settime",
"syscalls:sys_exit_clock_settime",
-- Too common, crowds the display
-- "syscalls:sys_enter_clock_gettime",
-- "syscalls:sys_exit_clock_gettime",
"syscalls:sys_enter_clock_adjtime",
"syscalls:sys_exit_clock_adjtime",
"syscalls:sys_enter_clock_getres",
"syscalls:sys_exit_clock_getres",
"syscalls:sys_enter_clock_nanosleep",
"syscalls:sys_exit_clock_nanosleep",
"syscalls:sys_enter_setpriority",
"syscalls:sys_exit_setpriority",
"syscalls:sys_enter_getpriority",
"syscalls:sys_exit_getpriority",
"syscalls:sys_enter_reboot",
"syscalls:sys_exit_reboot",
"syscalls:sys_enter_setregid",
"syscalls:sys_exit_setregid"
]
syscalls9 =
[
"syscalls:sys_enter_setgid",
"syscalls:sys_exit_setgid",
"syscalls:sys_enter_setreuid",
"syscalls:sys_exit_setreuid",
"syscalls:sys_enter_setuid",
"syscalls:sys_exit_setuid",
"syscalls:sys_enter_setresuid",
"syscalls:sys_exit_setresuid",
"syscalls:sys_enter_getresuid",
"syscalls:sys_exit_getresuid",
"syscalls:sys_enter_setresgid",
"syscalls:sys_exit_setresgid",
"syscalls:sys_enter_getresgid",
"syscalls:sys_exit_getresgid",
"syscalls:sys_enter_setfsuid",
"syscalls:sys_exit_setfsuid",
"syscalls:sys_enter_setfsgid",
"syscalls:sys_exit_setfsgid",
"syscalls:sys_enter_times",
"syscalls:sys_exit_times",
"syscalls:sys_enter_setpgid",
"syscalls:sys_exit_setpgid",
"syscalls:sys_enter_getpgid",
"syscalls:sys_exit_getpgid",
"syscalls:sys_enter_getpgrp",
"syscalls:sys_exit_getpgrp",
"syscalls:sys_enter_getsid",
"syscalls:sys_exit_getsid",
"syscalls:sys_enter_setsid",
"syscalls:sys_exit_setsid",
"syscalls:sys_enter_newuname",
"syscalls:sys_exit_newuname",
"syscalls:sys_enter_sethostname",
"syscalls:sys_exit_sethostname",
"syscalls:sys_enter_setdomainname",
"syscalls:sys_exit_setdomainname",
"syscalls:sys_enter_getrlimit",
"syscalls:sys_exit_getrlimit",
"syscalls:sys_enter_prlimit64",
"syscalls:sys_exit_prlimit64",
"syscalls:sys_enter_setrlimit",
"syscalls:sys_exit_setrlimit",
"syscalls:sys_enter_getrusage",
"syscalls:sys_exit_getrusage",
"syscalls:sys_enter_umask",
"syscalls:sys_exit_umask",
"syscalls:sys_enter_prctl",
"syscalls:sys_exit_prctl",
"syscalls:sys_enter_restart_syscall",
"syscalls:sys_exit_restart_syscall"
]
syscalls10 =
[
"syscalls:sys_enter_rt_sigprocmask",
"syscalls:sys_exit_rt_sigprocmask",
"syscalls:sys_enter_rt_sigpending",
"syscalls:sys_exit_rt_sigpending",
"syscalls:sys_enter_rt_sigtimedwait",
"syscalls:sys_exit_rt_sigtimedwait",
"syscalls:sys_enter_kill",
"syscalls:sys_exit_kill",
"syscalls:sys_enter_tgkill",
"syscalls:sys_exit_tgkill",
"syscalls:sys_enter_tkill",
"syscalls:sys_exit_tkill",
"syscalls:sys_enter_rt_sigqueueinfo",
"syscalls:sys_exit_rt_sigqueueinfo",
"syscalls:sys_enter_rt_tgsigqueueinfo",
"syscalls:sys_exit_rt_tgsigqueueinfo",
"syscalls:sys_enter_rt_sigaction",
"syscalls:sys_exit_rt_sigaction",
"syscalls:sys_enter_pause",
"syscalls:sys_exit_pause",
"syscalls:sys_enter_rt_sigsuspend",
"syscalls:sys_exit_rt_sigsuspend",
"syscalls:sys_enter_alarm",
"syscalls:sys_exit_alarm",
"syscalls:sys_enter_getpid",
"syscalls:sys_exit_getpid",
"syscalls:sys_enter_getppid",
"syscalls:sys_exit_getppid",
"syscalls:sys_enter_getuid",
"syscalls:sys_exit_getuid",
"syscalls:sys_enter_geteuid",
"syscalls:sys_exit_geteuid",
"syscalls:sys_enter_getgid",
"syscalls:sys_exit_getgid",
"syscalls:sys_enter_getegid",
"syscalls:sys_exit_getegid",
"syscalls:sys_enter_gettid",
"syscalls:sys_exit_gettid",
"syscalls:sys_enter_sysinfo",
"syscalls:sys_exit_sysinfo",
"syscalls:sys_enter_ptrace",
"syscalls:sys_exit_ptrace",
"syscalls:sys_enter_capget",
"syscalls:sys_exit_capget",
"syscalls:sys_enter_capset",
"syscalls:sys_exit_capset",
"syscalls:sys_enter_sysctl",
"syscalls:sys_exit_sysctl"
]
syscalls11 =
[
"syscalls:sys_enter_time",
"syscalls:sys_exit_time",
"syscalls:sys_enter_gettimeofday",
"syscalls:sys_exit_gettimeofday",
"syscalls:sys_enter_settimeofday",
"syscalls:sys_exit_settimeofday",
"syscalls:sys_enter_adjtimex",
"syscalls:sys_exit_adjtimex",
"syscalls:sys_enter_getitimer",
"syscalls:sys_exit_getitimer",
"syscalls:sys_enter_setitimer",
"syscalls:sys_exit_setitimer",
"syscalls:sys_enter_exit",
"syscalls:sys_exit_exit",
"syscalls:sys_enter_exit_group",
"syscalls:sys_exit_exit_group",
"syscalls:sys_enter_waitid",
"syscalls:sys_exit_waitid",
"syscalls:sys_enter_wait4",
"syscalls:sys_exit_wait4",
"syscalls:sys_enter_syslog",
"syscalls:sys_exit_syslog",
"syscalls:sys_enter_personality",
"syscalls:sys_exit_personality",
"syscalls:sys_enter_set_tid_address",
"syscalls:sys_exit_set_tid_address",
"syscalls:sys_enter_unshare",
"syscalls:sys_exit_unshare",
"syscalls:sys_enter_sched_setscheduler",
"syscalls:sys_exit_sched_setscheduler",
"syscalls:sys_enter_sched_setparam",
"syscalls:sys_exit_sched_setparam",
"syscalls:sys_enter_sched_getscheduler",
"syscalls:sys_exit_sched_getscheduler",
"syscalls:sys_enter_sched_getparam",
"syscalls:sys_exit_sched_getparam",
"syscalls:sys_enter_sched_setaffinity",
"syscalls:sys_exit_sched_setaffinity",
"syscalls:sys_enter_sched_getaffinity",
"syscalls:sys_exit_sched_getaffinity",
-- Too common, crowds the display
-- "syscalls:sys_enter_sched_yield",
-- "syscalls:sys_exit_sched_yield",
"syscalls:sys_enter_sched_get_priority_max",
"syscalls:sys_exit_sched_get_priority_max",
"syscalls:sys_enter_sched_get_priority_min",
"syscalls:sys_exit_sched_get_priority_min",
"syscalls:sys_enter_sched_rr_get_interval",
"syscalls:sys_exit_sched_rr_get_interval",
"syscalls:sys_enter_mmap",
"syscalls:sys_exit_mmap"
]
-- Given two lists [a, b, c ..] [d, e, f ..]
-- return a single list by alternating elements from
-- each: [a, d, b, e, c, f ..] until at least one
-- of the lists is exhausted.
alternate :: [a] -> [a] -> [a]
alternate [] _ = []
alternate _ [] = []
alternate (x:xs) (y:ys) = x : y : alternate xs ys