#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = "Peace Lee" __copyright__ = "Copyright 2015-2021, Guider" __module__ = "guider" __credits__ = "Peace Lee" __license__ = "GPLv2" __version__ = "3.9.8" __revision__ = "210326" __maintainer__ = "Peace Lee" __email__ = "iipeace5@gmail.com" __repository__ = "https://github.com/iipeace/guider" # import essential packages # try: import os import re import gc import sys import time import errno import signal import atexit import struct from copy import deepcopy #from ctypes import * except ImportError: err = sys.exc_info()[1] print("[ERROR] fail to import essential packages: %s" % err.args[0]) sys.exit(0) # to convert an unsupported type # try: long except: long = int # to prevent MemoryError in python2 # try: xrange except: xrange = range class ConfigMgr(object): """ Manager for config """ # Define logo # # made by http://www.figlet.org, consider also jp2a # logo = ''' _____ _ _ / ____| (_) | | | | __ _ _ _ __| | ___ _ __ | | |_ | | | | |/ _` |/ _ \ '__| | |__| | |_| | | (_| | __/ | \_____|\__,_|_|\__,_|\___|_| ver.%s_%s on python_%s.%s ''' % (__version__, __revision__, sys.version_info[0], sys.version_info[1]) # Define color # if (sys.platform.startswith('linux') or \ sys.platform.startswith('freebsd')) and \ not 'REMOTERUN' in os.environ: WARNING = '\033[95m' OKBLUE = '\033[94m' OKGREEN = '\033[92m' SPECIAL = '\033[93m' FAIL = '\033[91m' ENDC = '\033[0m' BOLD = '\033[1m' UNDERLINE = '\033[4m' else: WARNING = '' OKBLUE = '' OKGREEN = '' SPECIAL = '' FAIL = '' ENDC = '' BOLD = '' UNDERLINE = '' # Define config info # confData = {} # Define support architecture # supportArch = [ 'arm', 'aarch64', 'x86', 'x64' ] # Define ANSI color # COLOR_LIST = { 'DEFAULT': '\033[0m', 'BOLD': '\033[1m', 'ITALIC': '\033[3m', 'UNDERLINE': '\033[4m', 'LIGHT': '\033[5m', 'BLINK': '\033[6m', 'REVERSE': '\033[7m', 'SCRATCH': '\033[9m', 'BLACK': '\033[30m', 'RED': '\033[31m', 'GREEN': '\033[32m', 'YELLOW': '\033[33m', 'BLUE': '\033[34m', 'PINK': '\033[35m', 'CYAN': '\033[36m', 'WHITE': '\033[37m', 'DEFCOLOR': '\033[39m', 'BGBLACK': '\033[40m', 'BGRED': '\033[41m', 'BGGREEN': '\033[42m', 'BGYELLOW': '\033[43m', 'BGBLUE': '\033[44m', 'BGPINK': '\033[45m', 'BGCYAN': '\033[46m', 'BGWHITE': '\033[47m', 'OKGREEN': '\033[92m', 'SPECIAL': '\033[93m', 'OKBLUE': '\033[94m', 'WARNING': '\033[95m', } # Define cgroup entity # CGROUP_VALUE = [ 'tasks', 'cgroup.procs', 'cpu.shares', 'cpuset.cpus', 'memory.limit_in_bytes', 'memory.memsw.limit_in_bytes', 'blkio.weight', 'blkio.weight_device', ] # Define cgroup stat # CGROUP_STAT = [ 'cpuacct.usage', 'memory.usage_in_bytes', 'tasks', 'cgroup.procs', ] # Define state of process # PROC_STAT_TYPE = { 'R': 'running', 'S': 'sleep', 'D': 'disk', 'T': 'stopped', 't': 'traced', 'X': 'dead', 'x': 'dead', 'Z': 'zombie', 'K': 'wakekill', 'W': 'waking', 'P': 'parked', 'I': 'idle', } # Define diskstat statistics # DISKSTAT = [ 'major', 'minor', 'name', 'readComplete', 'readMerge', 'sectorRead', 'readTime', 'writeComplete', 'writeMerge', 'sectorWrite', 'writeTime', 'currentIO', 'ioTime', 'ioWTime', 'discComplete', 'discMerged', 'sectorDisc', 'discTime', # 4.18+ 'flushComplete', 'flushTime', # 5.5+ ] # Define socketcall attributes # SOCKETCALL = { 1: "socket", 2: "bind", 3: "connect", 4: "listen", 5: "accept", 6: "getsockname", 7: "getpeername", 8: "socketpair", 9: "send", 10: "recv", 11: "sendto", 12: "recvfrom", 13: "shutdown", 14: "setsockopt", 15: "getsockopt", 16: "sendmsg", 17: "recvmsg", } # Define socket family # SOCKET_FAMILY = { 0: "AF_UNSPEC", 1: "AF_FILE", 2: "AF_INET", 3: "AF_AX25", 4: "AF_IPX", 5: "AF_APPLETALK", 6: "AF_NETROM", 7: "AF_BRIDGE", 8: "AF_ATMPVC", 9: "AF_X25", 10: "AF_INET6", 11: "AF_ROSE", 12: "AF_DECnet", 13: "AF_NETBEUI", 14: "AF_SECURITY", 15: "AF_KEY", 16: "AF_NETLINK", 17: "AF_PACKET", 18: "AF_ASH", 19: "AF_ECONET", 20: "AF_ATMSVC", 22: "AF_SNA", 23: "AF_IRDA", 24: "AF_PPPOX", 25: "AF_WANPIPE", 31: "AF_BLUETOOTH", } # Define DLOPEN type # DLOPEN_TYPE = { 1: "RTLD_LAZY", 2: "RTLD_NOW", 3: "RTLD_BINDING_MASK", 4: "RTLD_NOLOAD", 8: "RTLD_DEEPBIND", } # Define socket type # SOCKET_TYPE = { 1: "SOCK_STREAM", 2: "SOCK_DGRAM", 3: "SOCK_RAW", 4: "SOCK_RDM", 5: "SOCK_SEQPACKET", 10: "SOCK_PACKET", } # Define log level # LOG_LEVEL = { 0: "EMERG", 1: "ALERT", 2: "CRIT", 3: "ERR", 4: "WARNING", 5: "NOTICE", 6: "INFO", 7: "DEBUG", } # Define MSG type # MSG_TYPE = { 0x1: "MSG_OOB", 0x2: "MSG_PEEK", 0x4: "MSG_DONTROUTE|MSG_TRYHARD", 0x8: "MSG_CTRUNC", 0x10: "MSG_PROBE", 0x20: "MSG_TRUNC", 0x40: "MSG_DONTWAIT", 0x80: "MSG_EOR", 0x100: "MSG_WAITALL", 0x200: "MSG_FIN", 0x400: "MSG_SYN", 0x800: "MSG_CONFIRM", 0x1000: "MSG_RST", 0x2000: "MSG_ERRQUEUE", 0x4000: "MSG_NOSIGNAL", 0x8000: "MSG_MORE", 0x40000000: "MSG_CMSG_CLOEXEC", 0x80000000: "MSG_CMSG_COMPAT", } # Define control message type # CMSG_TYPE = { 0x01: "SCM_RIGHTS", # rw: access rights (array of int) 0x02: "SCM_CREDENTIALS", # rw: struct ucred 0x03: "SCM_SECURITY" } # Define mmap prot type # MAP_TYPE = { 0x0000: "MAP_FILE", 0x0001: "MAP_SHARED", 0x0002: "MAP_PRIVATE", #0x0003: "MAP_SHARED_VALIDATE", #0x000f: "MAP_TYPE", 0x0010: "MAP_FIXED", 0x0020: "MAP_ANONYMOUS", 0x0100: "MAP_GROWSDOWN", 0x0800: "MAP_DENYWRITE", 0x1000: "MAP_EXECUTABLE", 0x2000: "MAP_LOCKED", 0x4000: "MAP_NORESERVE", 0x8000: "MAP_POPULATE", 0x10000: "MAP_NONBLOCK", 0x20000: "MAP_STACK", 0x40000: "MAP_HUGETLB", 0x80000: "MAP_SYNC", } # Define mmap prot type # PROT_TYPE = { 0x0: "PROT_NONE", # Page can not be accessed 0x1: "PROT_READ", # Page can be read 0x2: "PROT_WRITE", # Page can be written 0x4: "PROT_EXEC", # Page can be executed } # Define perm type # PERM_TYPE = { 0x0: "F_OK", 0x1: "X_OK", 0x2: "W_OK", 0x4: "R_OK", } # Define seek type # SEEK_TYPE = { 0x0: "SEEK_SET", 0x1: "SEEK_CUR", 0x2: "SEEK_END", } # Define prctl flags type # PRCTL_TYPE = { 1: "PR_SET_PDEATHSIG", 2: "PR_GET_PDEATHSIG", 3: "PR_GET_DUMPABLE", 4: "PR_SET_DUMPABLE", 5: "PR_GET_UNALIGN", 6: "PR_SET_UNALIGN", 7: "PR_GET_KEEPCAPS", 8: "PR_SET_KEEPCAPS", 9: "PR_GET_FPEMU", 10: "PR_SET_FPEMU", 11: "PR_GET_FPEXC", 12: "PR_SET_FPEXC", 13: "PR_GET_TIMING", 14: "PR_SET_TIMING", 15: "PR_SET_NAME", 16: "PR_GET_NAME", 19: "PR_GET_ENDIAN", 20: "PR_SET_ENDIAN", 21: "PR_GET_SECCOMP", 22: "PR_SET_SECCOMP", 23: "PR_CAPBSET_READ", 24: "PR_CAPBSET_DROP", 25: "PR_GET_TSC 25", 26: "PR_SET_TSC 26", 27: "PR_GET_SECUREBITS", 28: "PR_SET_SECUREBITS", 29: "PR_SET_TIMERSLACK", 30: "PR_GET_TIMERSLACK", 31: "PR_TASK_PERF_EVENTS_DISABLE", 32: "PR_TASK_PERF_EVENTS_ENABLE", 33: "PR_MCE_KILL", } # Define clone flags type # CLONE_TYPE = { 0x000000ff: "CSIGNAL", 0x00000100: "CLONE_VM", 0x00000200: "CLONE_FS", 0x00000400: "CLONE_FILES", 0x00000800: "CLONE_SIGHAND", 0x00002000: "CLONE_PTRACE", 0x00004000: "CLONE_VFORK", 0x00008000: "CLONE_PARENT", 0x00010000: "CLONE_THREAD", 0x00020000: "CLONE_NEWNS", 0x00040000: "CLONE_SYSVSEM", 0x00080000: "CLONE_SETTLS", 0x00100000: "CLONE_PARENT_SETTID", 0x00200000: "CLONE_CHILD_CLEARTID", 0x00400000: "CLONE_DETACHED", 0x00800000: "CLONE_UNTRACED", 0x01000000: "CLONE_CHILD_SETTID", 0x02000000: "CLONE_STOPPED", 0x04000000: "CLONE_NEWUTS", 0x08000000: "CLONE_NEWIPC", 0x10000000: "CLONE_NEWUSER", 0x20000000: "CLONE_NEWPID", 0x40000000: "CLONE_NEWNET", 0x80000000: "CLONE_IO", } # Define open flags type # OPEN_TYPE = { 0o0: "O_RDONLY", 0o1: "O_WRONLY", 0o2: "O_RDWR", 0o100: "O_CREAT", 0o200: "O_EXCL", 0o400: "O_NOCTTY", 0o1000: "O_TRUNC", 0o2000: "O_APPEND", 0o4000: "O_NONBLOCK", 0o10000: "O_SYNC", 0o20000: "O_ASYNC", 0o40000: "O_DIRECT", 0o100000: "O_LARGEFILE", 0o200000: "O_DIRECTORY", 0o400000: "O_NOFOLLOW", 0o1000000: "O_NOATIME", 0o2000000: "O_CLOEXEC", 0o10000000: "O_PATH", 0o20200000: "O_TMPFILE", } # Define madvise type # MADV_TYPE = { 0: "MADV_NORMAL", # No further special treatment 1: "MADV_RANDOM", # Expect random page references 2: "MADV_SEQUENTIAL", # Expect sequential page references 3: "MADV_WILLNEED", # Will need these pages 4: "MADV_DONTNEED", # Don't need these pages 8: "MADV_FREE", # Free pages only if memory pressure 9: "MADV_REMOVE", # Remove these pages and resources 10: "MADV_DONTFORK", # Do not inherit across fork 11: "MADV_DOFORK", # Do inherit across fork 12: "MADV_MERGEABLE", # KSM may merge identical pages 13: "MADV_UNMERGEABLE", # KSM may not merge identical pages 14: "MADV_HUGEPAGE", # Worth backing with hugepages 15: "MADV_NOHUGEPAGE", # Not worth backing with hugepages 16: "MADV_DONTDUMP", # Explicity exclude from the core dump, 17: "MADV_DODUMP", # Clear the MADV_DONTDUMP flag 18: "MADV_WIPEONFORK", # Zero memory on fork, child only 19: "MADV_KEEPONFORK", # Undo MADV_WIPEONFORK 100: "MADV_HWPOISON", # Poison a page for testing } # Define netlink type # NETLINK_TYPE = { "NETLINK_ROUTE": 0, "NETLINK_UNUSED": 1, "NETLINK_USERSOCK": 2, "NETLINK_FIREWALL": 3, "NETLINK_SOCK_DIAG": 4, "NETLINK_NFLOG": 5, "NETLINK_XFRM": 6, "NETLINK_SELINUX": 7, "NETLINK_ISCSI": 8, "NETLINK_AUDIT": 9, "NETLINK_FIB_LOOKUP": 10, "NETLINK_CONNECTOR": 11, "NETLINK_NETFILTER": 12, "NETLINK_IP6_FW": 13, "NETLINK_DNRTMSG": 14, "NETLINK_KOBJECT_UEVENT": 15, "NETLINK_GENERIC": 16, "NETLINK_SCSITRANSPORT": 18, "NETLINK_ECRYPTFS": 19, "NETLINK_RDMA": 20, "NETLINK_CRYPTO": 21, } # Define entry type # INOTIFY_TYPE = { "IN_ACCESS": 0x00000001, # File was accessed */ "IN_MODIFY": 0x00000002, # File was modified */ "IN_ATTRIB": 0x00000004, # Metadata changed */ "IN_CLOSE_WRITE": 0x00000008, # Writtable file was closed */ "IN_CLOSE_NOWRITE": 0x00000010, # Unwrittable file closed */ "IN_CLOSE": 0x00000008|0x00000010, # file closed */ "IN_OPEN": 0x00000020, # File was opened */ "IN_MOVED_FROM": 0x00000040, # File was moved from X */ "IN_MOVED_TO": 0x00000080, # File was moved to Y */ "IN_MOVED": 0x00000040|0x00000080, # File was moved */ "IN_CREATE": 0x00000100, # Subfile was created */ "IN_DELETE": 0x00000200, # Subfile was deleted */ "IN_DELETE_SELF": 0x00000400, # Self was deleted */ "IN_MOVE_SELF": 0x00000800, # Self was moved */ "IN_UNMOUNT": 0x00002000, # Backing fs was unmounted */ "IN_Q_OVERFLOW": 0x00004000, # Event queued overflowed */ "IN_IGNORED": 0x00008000, # File was ignored */ "IN_ONLYDIR": 0x01000000, # only watch the path if it is a directory */ "IN_DONT_FOLLOW": 0x02000000, # don't follow a sym link */ "IN_EXCL_UNLINK": 0x04000000, # exclude events on unlinked objects */ "IN_MASK_CREATE": 0x10000000, # only create watches */ "IN_MASK_ADD": 0x20000000, # add to the mask of an already existing watch */ "IN_ISDIR": 0x40000000, # event occurred against dir */ "IN_ONESHOT": 0x80000000, # only send event once */ } # Define entry type # AT_TYPE = { "AT_IGNORE": 1, # Entry should be ignored "AT_EXECFD": 2, # File descriptor of program "AT_PHDR": 3, # Program headers for program "AT_PHENT": 4, # Size of program header entry "AT_PHNUM": 5, # Number of program headers "AT_PAGESZ": 6, # System page size "AT_BASE": 7, # Base address of interpreter "AT_FLAGS": 8, # Flags "AT_ENTRY": 9, # Entry point of program "AT_NOTELF": 10, # Program is not ELF "AT_UID": 11, # Real uid "AT_EUID": 12, # Effective uid "AT_GID": 13, # Real gid "AT_EGID": 14, # Effective gid "AT_CLKTCK": 17, # Frequency of times() "AT_PLATFORM": 15, # String identifying platform "AT_HWCAP": 16, # Machine-dependent hints about "AT_FPUCW": 18, # Used FPU control word "AT_DCACHEBSIZE": 19, # Data cache block size "AT_ICACHEBSIZE": 20, # Instruction cache block size "AT_UCACHEBSIZE": 21, # Unified cache block size "AT_IGNOREPPC": 22, # Entry should be ignored "AT_SECURE": 23, # Boolean, was exec setuid-like? "AT_BASE_PLATFORM": 24, # String identifying real platforms "AT_RANDOM": 25, # Address of 16 random bytes "AT_HWCAP2": 26, # More machine-dependent hints about "AT_EXECFN": 31, # Filename of executable "AT_SYSINFO": 32, "AT_SYSINFO_EHDR": 33, "AT_L1I_CACHESHAPE": 34, "AT_L1D_CACHESHAPE": 35, "AT_L2_CACHESHAPE": 36, "AT_L3_CACHESHAPE": 37, "AT_L1I_CACHESIZE": 40, "AT_L1I_CACHEGEOMETRY": 41, "AT_L1D_CACHESIZE": 42, "AT_L1D_CACHEGEOMETRY": 43, "AT_L2_CACHESIZE": 44, "AT_L2_CACHEGEOMETRY": 45, "AT_L3_CACHESIZE": 46, "AT_L3_CACHEGEOMETRY": 47, "AT_MINSIGSTKSZ": 51, # Stack needed for signal delivery } # Define syscall prototypes # SYSCALL_PROTOTYPES = { "accept": ("long", ( ("int", "sockfd"), ("struct sockaddr *", "addr"), ("int *", "addrlen"), )), "accept4": ("long", ( ("int", "sockfd"), ("struct sockaddr *", "addr"), ("int *", "addrlen"), ("int", "flags"), )), "access": ("long", ( ("const char *", "filename"), ("int", "mode"), )), "acct": ("long", ( ("const char *", "name"), )), "add_key": ("long", ( ("const char *", "_type"), ("const char *", "_description"), ("const void *", "_payload"), ("size_t", "plen"), ("key_serial_t", "destringid"), )), "adjtimex": ("long", ( ("struct timex *", "txc_p"), )), "alarm": ("long", ( ("unsigned int", "seconds"), )), "bdflush": ("long", ( ("int", "func"), ("long", "data"), )), "bind": ("long", ( ("int", "sockfd"), ("struct sockaddr *", "addr"), ("int", "addrlen"), )), "bpf": ("long", ( ("int", "cmd"), ("union bpf_attr *", "attr"), ("unsigned int", "size"), )), "brk": ("long", ( ("unsigned long", "brk"), )), "capget": ("long", ( ("cap_user_header_t", "header"), ("cap_user_data_t", "dataptr"), )), "capset": ("long", ( ("cap_user_header_t", "header"), ("const cap_user_data_t", "data"), )), "chdir": ("long", ( ("const char *", "filename"), )), "chmod": ("long", ( ("const char *", "filename"), ("umode_t", "mode"), )), "chown": ("long", ( ("const char *", "filename"), ("uid_t", "user"), ("gid_t", "group"), )), "chown16": ("long", ( ("const char *", "filename"), ("old_uid_t", "user"), ("old_gid_t", "group"), )), "chroot": ("long", ( ("const char *", "filename"), )), "clock_adjtime": ("long", ( ("clockid_t", "which_clock"), ("struct timex *", "tx"), )), "clock_adjtime32": ("long", ( ("clockid_t", "which_clock"), ("struct old_timex32 *", "tx"), )), "clock_getres": ("long", ( ("clockid_t", "which_clock"), ("struct timespec *", "tp"), )), "clock_getres_time32": ("long", ( ("clockid_t", "which_clock"), ("struct old_timespec32 *", "tp"), )), "clock_gettime": ("long", ( ("clockid_t", "which_clock"), ("struct timespec *", "tp"), )), "clock_gettime32": ("long", ( ("clockid_t", "which_clock"), ("struct old_timespec32 *", "tp"), )), "clock_nanosleep": ("long", ( ("clockid_t", "which_clock"), ("int", "flags"), ("const struct timespec *", "rqtp"), ("struct timespec *", "rmtp"), )), "clock_nanosleep_time32": ("long", ( ("clockid_t", "which_clock"), ("int", "flags"), ("struct old_timespec32 *", "rqtp"), ("struct old_timespec32 *", "rmtp"), )), "clock_settime": ("long", ( ("clockid_t", "which_clock"), ("const struct timespec *", "tp"), )), "clock_settime32": ("long", ( ("clockid_t", "which_clock"), ("struct old_timespec32 *", "tp"), )), "clone": ("long", ( ("unsigned long", "child_stack"), ("unsigned long", "flags"), ("int *", "ptid"), ("int *", "ctid"), ("unsigned long", "regs"), )), "clone3": ("long", ( ("struct clone_args *", "uargs"), ("size_t", "size"), )), "close": ("long", ( ("unsigned int", "fd"), )), "connect": ("long", ( ("int", "sockfd"), ("struct sockaddr *", "addr"), ("int", "addrlen"), )), "copy_file_range": ("long", ( ("int", "fd_in"), ("loff_t *", "off_in"), ("int", "fd_out"), ("loff_t *", "off_out"), ("size_t", "len"), ("unsigned int", "flags"), )), "creat": ("long", ( ("const char *", "pathname"), ("umode_t", "mode"), )), "delete_module": ("long", ( ("const char *", "name_user"), ("unsigned int", "flags"), )), "dup": ("long", ( ("unsigned int", "fildes"), )), "dup2": ("long", ( ("unsigned int", "oldfd"), ("unsigned int", "newfd"), )), "dup3": ("long", ( ("unsigned int", "oldfd"), ("unsigned int", "newfd"), ("int", "flags"), )), "epoll_create": ("long", ( ("int", "size"), )), "epoll_create1": ("long", ( ("int", "flags"), )), "epoll_ctl": ("long", ( ("int", "epfd"), ("int", "op"), ("int", "fd"), ("struct epoll_event *", "event"), )), "epoll_pwait": ("long", ( ("int", "epfd"), ("struct epoll_event *", "events"), ("int", "maxevents"), ("int", "timeout"), ("const sigset_t *", "sigmask"), ("size_t", "sigsetsize"), )), "epoll_wait": ("long", ( ("int", "epfd"), ("struct epoll_event *", "events"), ("int", "maxevents"), ("int", "timeout"), )), "eventfd": ("long", ( ("unsigned int", "count"), )), "eventfd2": ("long", ( ("unsigned int", "count"), ("int", "flags"), )), "execve": ("long", ( ("const char *", "filename"), ("const char *const *", "argv"), ("const char *const *", "envp"), )), "execveat": ("long", ( ("int", "dfd"), ("const char *", "filename"), ("const char *const *", "argv"), ("const char *const *", "envp"), ("int", "flags"), )), "exit": ("long", ( ("int", "error_code"), )), "exit_group": ("long", ( ("int", "error_code"), )), "faccessat": ("long", ( ("int", "dfd"), ("const char *", "filename"), ("int", "mode"), )), "faccessat2": ("long", ( ("int", "dfd"), ("const char *", "filename"), ("int", "mode"), ("int", "flags"), )), "fadvise64": ("long", ( ("int", "fd"), ("loff_t", "offset"), ("size_t", "len"), ("int", "advice"), )), "fadvise64_64": ("long", ( ("int", "fd"), ("loff_t", "offset"), ("loff_t", "len"), ("int", "advice"), )), "fallocate": ("long", ( ("int", "fd"), ("int", "mode"), ("loff_t", "offset"), ("loff_t", "len"), )), "fanotify_init": ("long", ( ("unsigned int", "flags"), ("unsigned int", "event_f_flags"), )), "fanotify_mark": ("long", ( ("int", "fanotify_fd"), ("unsigned int", "flags"), ("u64", "mask"), ("int", "fd"), ("const char *", "pathname"), )), "fchdir": ("long", ( ("unsigned int", "fd"), )), "fchmod": ("long", ( ("unsigned int", "fd"), ("umode_t", "mode"), )), "fchmodat": ("long", ( ("int", "dfd"), ("const char *", "filename"), ("umode_t", "mode"), )), "fchown": ("long", ( ("unsigned int", "fd"), ("uid_t", "user"), ("gid_t", "group"), )), "fchown16": ("long", ( ("unsigned int", "fd"), ("old_uid_t", "user"), ("old_gid_t", "group"), )), "fchownat": ("long", ( ("int", "dfd"), ("const char *", "filename"), ("uid_t", "user"), ("gid_t", "group"), ("int", "flag"), )), "fcntl": ("long", ( ("unsigned int", "fd"), ("unsigned int", "cmd"), ("unsigned long", "arg"), )), "fcntl64": ("long", ( ("unsigned int", "fd"), ("unsigned int", "cmd"), ("unsigned long", "arg"), )), "fdatasync": ("long", ( ("unsigned int", "fd"), )), "fgetxattr": ("long", ( ("int", "fd"), ("const char *", "name"), ("void *", "value"), ("size_t", "size"), )), "finit_module": ("long", ( ("int", "fd"), ("const char *", "uargs"), ("int", "flags"), )), "flistxattr": ("long", ( ("int", "fd"), ("char *", "list"), ("size_t", "size"), )), "flock": ("long", ( ("unsigned int", "fd"), ("unsigned int", "cmd"), )), "fork": ("long", ( )), "fremovexattr": ("long", ( ("int", "fd"), ("const char *", "name"), )), "fsconfig": ("long", ( ("int", "fs_fd"), ("unsigned int", "cmd"), ("const char *", "key"), ("const void *", "value"), ("int", "aux"), )), "fsetxattr": ("long", ( ("int", "fd"), ("const char *", "name"), ("const void *", "value"), ("size_t", "size"), ("int", "flags"), )), "fsmount": ("long", ( ("int", "fs_fd"), ("unsigned int", "flags"), ("unsigned int", "ms_flags"), )), "fsopen": ("long", ( ("const char *", "fs_name"), ("unsigned int", "flags"), )), "fspick": ("long", ( ("int", "dfd"), ("const char *", "path"), ("unsigned int", "flags"), )), "fstat": ("long", ( ("unsigned int", "fd"), ("struct __old_kernel_stat *", "statbuf"), )), "fstat64": ("long", ( ("unsigned long", "fd"), ("struct stat64 *", "statbuf"), )), "fstatat64": ("long", ( ("int", "dfd"), ("const char *", "filename"), ("struct stat64 *", "statbuf"), ("int", "flag"), )), "fstatfs": ("long", ( ("unsigned int", "fd"), ("struct statfs *", "buf"), )), "fstatfs64": ("long", ( ("unsigned int", "fd"), ("size_t", "sz"), ("struct statfs64 *", "buf"), )), "fsync": ("long", ( ("unsigned int", "fd"), )), "ftruncate": ("long", ( ("unsigned int", "fd"), ("unsigned long", "length"), )), "ftruncate64": ("long", ( ("unsigned int", "fd"), ("loff_t", "length"), )), "futex": ("long", ( ("u32 *", "uaddr"), ("int", "op"), ("u32", "val"), ("struct timespec *", "utime"), ("u32 *", "uaddr2"), ("u32", "val3"), )), "futex_time32": ("long", ( ("u32 *", "uaddr"), ("int", "op"), ("u32", "val"), ("struct old_timespec32 *", "utime"), ("u32 *", "uaddr2"), ("u32", "val3"), )), "futimesat": ("long", ( ("int", "dfd"), ("const char *", "filename"), ("struct old_timeval *", "utimes"), )), "futimesat_time32": ("long", ( ("unsigned int", "dfd"), ("const char *", "filename"), ("struct old_timeval32 *", "t"), )), "get_mempolicy": ("long", ( ("int *", "policy"), ("unsigned long *", "nmask"), ("unsigned long", "maxnode"), ("unsigned long", "addr"), ("unsigned long", "flags"), )), "get_robust_list": ("long", ( ("int", "pid"), ("struct robust_list_head * *", "head_ptr"), ("size_t *", "len_ptr"), )), "getcpu": ("long", ( ("unsigned *", "cpu"), ("unsigned *", "node"), ("struct getcpu_cache *", "cache"), )), "getcwd": ("long", ( ("char *", "pathname"), ("unsigned long", "size"), )), "getdents": ("long", ( ("unsigned int", "fd"), ("struct linux_dirent *", "dirent"), ("unsigned int", "count"), )), "getdents64": ("long", ( ("unsigned int", "fd"), ("struct linux_dirent64 *", "dirent"), ("unsigned int", "count"), )), "getegid": ("long", ( )), "getegid16": ("long", ( )), "geteuid": ("long", ( )), "geteuid16": ("long", ( )), "getgid": ("long", ( )), "getgid16": ("long", ( )), "getgroups": ("long", ( ("int", "gidsetsize"), ("gid_t *", "grouplist"), )), "getgroups16": ("long", ( ("int", "gidsetsize"), ("old_gid_t *", "grouplist"), )), "gethostname": ("long", ( ("char *", "name"), ("int", "len"), )), "getitimer": ("long", ( ("int", "which"), ("struct itimerval *", "value"), )), "getpeername": ("long", ( ("int", "sockfd"), ("struct sockaddr *", "addr"), ("int *", "addrlen"), )), "getpgid": ("long", ( ("pid_t", "pid"), )), "getpgrp": ("long", ( )), "getpid": ("long", ( )), "getppid": ("long", ( )), "getpriority": ("long", ( ("int", "which"), ("int", "who"), )), "getrandom": ("long", ( ("char *", "buf"), ("size_t", "count"), ("unsigned int", "flags"), )), "getresgid": ("long", ( ("gid_t *", "rgid"), ("gid_t *", "egid"), ("gid_t *", "sgid"), )), "getresgid16": ("long", ( ("old_gid_t *", "rgid"), ("old_gid_t *", "egid"), ("old_gid_t *", "sgid"), )), "getresuid": ("long", ( ("uid_t *", "ruid"), ("uid_t *", "euid"), ("uid_t *", "suid"), )), "getresuid16": ("long", ( ("old_uid_t *", "ruid"), ("old_uid_t *", "euid"), ("old_uid_t *", "suid"), )), "getrlimit": ("long", ( ("unsigned int", "resource"), ("struct rlimit *", "rlim"), )), "ugetrlimit": ("long", ( ("unsigned int", "resource"), ("struct rlimit *", "rlim"), )), "getrusage": ("long", ( ("int", "who"), ("struct rusage *", "ru"), )), "getsid": ("long", ( ("pid_t", "pid"), )), "getsockname": ("long", ( ("int", "sockfd"), ("struct sockaddr *", "addr"), ("int *", "addrlen"), )), "getsockopt": ("long", ( ("int", "fd"), ("int", "level"), ("int", "optname"), ("char *", "optval"), ("int *", "optlen"), )), "gettid": ("long", ( )), "gettimeofday": ("long", ( ("struct timeval *", "tv"), ("struct timezone *", "tz"), )), "getuid": ("long", ( )), "getuid16": ("long", ( )), "getuid32": ("long", ( )), "getxattr": ("long", ( ("const char *", "path"), ("const char *", "name"), ("void *", "value"), ("size_t", "size"), )), "init_module": ("long", ( ("void *", "umod"), ("unsigned long", "len"), ("const char *", "uargs"), )), "inotify_add_watch": ("long", ( ("int", "fd"), ("const char *", "path"), ("u32", "mask"), )), "inotify_init": ("long", ( )), "inotify_init1": ("long", ( ("int", "flags"), )), "inotify_rm_watch": ("long", ( ("int", "fd"), ("__s32", "wd"), )), "io_cancel": ("long", ( ("aio_context_t", "ctx_id"), ("struct iocb *", "iocb"), ("struct io_event *", "result"), )), "io_destroy": ("long", ( ("aio_context_t", "ctx"), )), "io_getevents": ("long", ( ("aio_context_t", "ctx_id"), ("long", "min_nr"), ("long", "nr"), ("struct io_event *", "events"), ("struct timespec *", "timeout"), )), "io_getevents_time32": ("long", ( ("__u32", "ctx_id"), ("__s32", "min_nr"), ("__s32", "nr"), ("struct io_event *", "events"), ("struct old_timespec32 *", "timeout"), )), "io_pgetevents": ("long", ( ("aio_context_t", "ctx_id"), ("long", "min_nr"), ("long", "nr"), ("struct io_event *", "events"), ("struct timespec *", "timeout"), ("const struct __aio_sigset *", "sig"), )), "io_pgetevents_time32": ("long", ( ("aio_context_t", "ctx_id"), ("long", "min_nr"), ("long", "nr"), ("struct io_event *", "events"), ("struct old_timespec32 *", "timeout"), ("const struct __aio_sigset *", "sig"), )), "io_setup": ("long", ( ("unsigned", "nr_reqs"), ("aio_context_t *", "ctx"), )), "io_submit": ("long", ( ("aio_context_t", "ctx_id"), ("long", "nr"), ("struct iocb * *", "iocbpp"), )), "io_uring_enter": ("long", ( ("unsigned int", "fd"), ("u32", "to_submit"), ("u32", "min_complete"), ("u32", "flags"), ("const sigset_t *", "sig"), ("size_t", "sigsz"), )), "io_uring_register": ("long", ( ("unsigned int", "fd"), ("unsigned int", "op"), ("void *", "arg"), ("unsigned int", "nr_args"), )), "io_uring_setup": ("long", ( ("u32", "entries"), ("struct io_uring_params *", "p"), )), "ioctl": ("long", ( ("unsigned int", "fd"), ("unsigned int", "cmd"), ("unsigned long", "arg"), )), "ioperm": ("long", ( ("unsigned long", "from"), ("unsigned long", "num"), ("int", "on"), )), "ioprio_get": ("long", ( ("int", "which"), ("int", "who"), )), "ioprio_set": ("long", ( ("int", "which"), ("int", "who"), ("int", "ioprio"), )), "ipc": ("long", ( ("unsigned int", "call"), ("int", "first"), ("unsigned long", "second"), ("unsigned long", "third"), ("void *", "ptr"), ("long", "fifth"), )), "kcmp": ("long", ( ("pid_t", "pid1"), ("pid_t", "pid2"), ("int", "type"), ("unsigned long", "idx1"), ("unsigned long", "idx2"), )), "kexec_file_load": ("long", ( ("int", "kernel_fd"), ("int", "initrd_fd"), ("unsigned long", "cmdline_len"), ("const char *", "cmdline_ptr"), ("unsigned long", "flags"), )), "kexec_load": ("long", ( ("unsigned long", "entry"), ("unsigned long", "nr_segments"), ("struct kexec_segment *", "segments"), ("unsigned long", "flags"), )), "keyctl": ("long", ( ("int", "cmd"), ("unsigned long", "arg2"), ("unsigned long", "arg3"), ("unsigned long", "arg4"), ("unsigned long", "arg5"), )), "kill": ("long", ( ("int", "pid"), ("int", "sig"), )), "lchown": ("long", ( ("const char *", "filename"), ("uid_t", "user"), ("gid_t", "group"), )), "lchown16": ("long", ( ("const char *", "filename"), ("old_uid_t", "user"), ("old_gid_t", "group"), )), "lgetxattr": ("long", ( ("const char *", "path"), ("const char *", "name"), ("void *", "value"), ("size_t", "size"), )), "link": ("long", ( ("const char *", "oldname"), ("const char *", "newname"), )), "linkat": ("long", ( ("int", "olddfd"), ("const char *", "oldname"), ("int", "newdfd"), ("const char *", "newname"), ("int", "flags"), )), "listen": ("long", ( ("int", "sockfd"), ("int", "backlog"), )), "listxattr": ("long", ( ("const char *", "path"), ("char *", "list"), ("size_t", "size"), )), "llistxattr": ("long", ( ("const char *", "path"), ("char *", "list"), ("size_t", "size"), )), "llseek": ("long", ( ("unsigned int", "fd"), ("unsigned long", "offset_high"), ("unsigned long", "offset_low"), ("loff_t *", "result"), ("unsigned int", "whence"), )), "lookup_dcookie": ("long", ( ("u64", "cookie64"), ("char *", "buf"), ("size_t", "len"), )), "lremovexattr": ("long", ( ("const char *", "path"), ("const char *", "name"), )), "lseek": ("long", ( ("unsigned int", "fd"), ("off_t", "offset"), ("unsigned int", "whence"), )), "lsetxattr": ("long", ( ("const char *", "path"), ("const char *", "name"), ("const void *", "value"), ("size_t", "size"), ("int", "flags"), )), "lstat": ("long", ( ("const char *", "filename"), ("struct __old_kernel_stat *", "statbuf"), )), "lstat64": ("long", ( ("const char *", "filename"), ("struct stat64 *", "statbuf"), )), "madvise": ("long", ( ("unsigned long", "start"), ("size_t", "len"), ("int", "behavior"), )), "mbind": ("long", ( ("unsigned long", "start"), ("unsigned long", "len"), ("unsigned long", "mode"), ("const unsigned long *", "nmask"), ("unsigned long", "maxnode"), ("unsigned", "flags"), )), "membarrier": ("long", ( ("int", "cmd"), ("int", "flags"), )), "memfd_create": ("long", ( ("const char *", "uname_ptr"), ("unsigned int", "flags"), )), "migrate_pages": ("long", ( ("pid_t", "pid"), ("unsigned long", "maxnode"), ("const unsigned long *", "from"), ("const unsigned long *", "to"), )), "mincore": ("long", ( ("unsigned long", "start"), ("size_t", "len"), ("unsigned char *", "vec"), )), "mkdir": ("long", ( ("const char *", "pathname"), ("umode_t", "mode"), )), "mkdirat": ("long", ( ("int", "dfd"), ("const char *", "pathname"), ("umode_t", "mode"), )), "mknod": ("long", ( ("const char *", "filename"), ("umode_t", "mode"), ("unsigned", "dev"), )), "mknodat": ("long", ( ("int", "dfd"), ("const char *", "filename"), ("umode_t", "mode"), ("unsigned", "dev"), )), "mlock": ("long", ( ("unsigned long", "start"), ("size_t", "len"), )), "mlock2": ("long", ( ("unsigned long", "start"), ("size_t", "len"), ("int", "flags"), )), "mlockall": ("long", ( ("int", "flags"), )), "mmap_pgoff": ("long", ( ("unsigned long", "addr"), ("unsigned long", "len"), ("unsigned long", "prot"), ("unsigned long", "flags"), ("unsigned long", "fd"), ("unsigned long", "pgoff"), )), "mmap": ("long", ( ("unsigned long", "addr"), ("unsigned long", "len"), ("unsigned long", "prot"), ("unsigned long", "flags"), ("unsigned long", "fd"), ("unsigned long", "pgoff"), )), "mmap2": ("long", ( ("unsigned long", "addr"), ("unsigned long", "len"), ("unsigned long", "prot"), ("unsigned long", "flags"), ("unsigned long", "fd"), ("unsigned long", "pgoff"), )), "move_mount": ("long", ( ("int", "from_dfd"), ("const char *", "from_path"), ("int", "to_dfd"), ("const char *", "to_path"), ("unsigned int", "ms_flags"), )), "arch_prctl": ("int", ( ("int", "code"), ("unsigned long", "addr"), )), "mount": ("long", ( ("char *", "dev_name"), ("char *", "dir_name"), ("char *", "type"), ("unsigned long", "flags"), ("void *", "data"), )), "move_pages": ("long", ( ("pid_t", "pid"), ("unsigned long", "nr_pages"), ("const void * *", "pages"), ("const int *", "nodes"), ("int *", "status"), ("int", "flags"), )), "mprotect": ("long", ( ("unsigned long", "start"), ("size_t", "len"), ("unsigned long", "prot"), )), "mq_getsetattr": ("long", ( ("mqd_t", "mqdes"), ("const struct mq_attr *", "mqstat"), ("struct mq_attr *", "omqstat"), )), "mq_notify": ("long", ( ("mqd_t", "mqdes"), ("const struct sigevent *", "notification"), )), "mq_open": ("long", ( ("const char *", "name"), ("int", "oflag"), ("umode_t", "mode"), ("struct mq_attr *", "attr"), )), "mq_timedreceive": ("long", ( ("mqd_t", "mqdes"), ("char *", "msg_ptr"), ("size_t", "msg_len"), ("unsigned int *", "msg_prio"), ("const struct timespec *", "abs_timeout"), )), "mq_timedreceive_time32": ("long", ( ("mqd_t", "mqdes"), ("char *", "u_msg_ptr"), ("unsigned int", "msg_len"), ("unsigned int *", "u_msg_prio"), ("const struct old_timespec32 *", "u_abs_timeout"), )), "mq_timedsend": ("long", ( ("mqd_t", "mqdes"), ("const char *", "msg_ptr"), ("size_t", "msg_len"), ("unsigned int", "msg_prio"), ("const struct timespec *", "abs_timeout"), )), "mq_timedsend_time32": ("long", ( ("mqd_t", "mqdes"), ("const char *", "u_msg_ptr"), ("unsigned int", "msg_len"), ("unsigned int", "msg_prio"), ("const struct old_timespec32 *", "u_abs_timeout"), )), "mq_unlink": ("long", ( ("const char *", "name"), )), "mremap": ("long", ( ("unsigned long", "addr"), ("unsigned long", "old_len"), ("unsigned long", "new_len"), ("unsigned long", "flags"), ("unsigned long", "new_addr"), )), "msgctl": ("long", ( ("int", "msqid"), ("int", "cmd"), ("struct msqid_ds *", "buf"), )), "msgget": ("long", ( ("key_t", "key"), ("int", "msgflg"), )), "msgrcv": ("long", ( ("int", "msqid"), ("struct msgbuf *", "msgp"), ("size_t", "msgsz"), ("long", "msgtyp"), ("int", "msgflg"), )), "msgsnd": ("long", ( ("int", "msqid"), ("struct msgbuf *", "msgp"), ("size_t", "msgsz"), ("int", "msgflg"), )), "msync": ("long", ( ("unsigned long", "start"), ("size_t", "len"), ("int", "flags"), )), "munlock": ("long", ( ("unsigned long", "start"), ("size_t", "len"), )), "munlockall": ("long", ( )), "munmap": ("long", ( ("unsigned long", "addr"), ("size_t", "len"), )), "name_to_handle_at": ("long", ( ("int", "dfd"), ("const char *", "name"), ("struct file_handle *", "handle"), ("int *", "mnt_id"), ("int", "flag"), )), "nanosleep": ("long", ( ("struct timespec *", "rqtp"), ("struct timespec *", "rmtp"), )), "nanosleep_time32": ("long", ( ("struct old_timespec32 *", "rqtp"), ("struct old_timespec32 *", "rmtp"), )), "newfstat": ("long", ( ("unsigned int", "fd"), ("struct stat *", "statbuf"), )), "newfstatat": ("long", ( ("int", "dfd"), ("const char *", "filename"), ("struct stat *", "statbuf"), ("int", "flag"), )), "newlstat": ("long", ( ("const char *", "filename"), ("struct stat *", "statbuf"), )), "newstat": ("long", ( ("const char *", "filename"), ("struct stat *", "statbuf"), )), "newuname": ("long", ( ("struct new_utsname *", "name"), )), "ni_syscall": ("long", ( )), "nice": ("long", ( ("int", "increment"), )), "old_getrlimit": ("long", ( ("unsigned int", "resource"), ("struct rlimit *", "rlim"), )), "old_mmap": ("long", ( ("struct mmap_arg_struct *", "arg"), )), "old_msgctl": ("long", ( ("int", "msqid"), ("int", "cmd"), ("struct msqid_ds *", "buf"), )), "old_readdir": ("long", ( ("unsigned int", "fd"), ("struct old_linux_dirent *", "dirp"), ("unsigned int", "count"), )), "old_select": ("long", ( ("struct sel_arg_struct *", "arg"), )), "old_semctl": ("long", ( ("int", "semid"), ("int", "semnum"), ("int", "cmd"), ("unsigned long", "arg"), )), "old_shmctl": ("long", ( ("int", "shmid"), ("int", "cmd"), ("struct shmid_ds *", "buf"), )), "oldumount": ("long", ( ("char *", "name"), )), "olduname": ("long", ( ("struct oldold_utsname *", "buf"), )), "open": ("long", ( ("const char *", "filename"), ("int", "flags"), ("umode_t", "mode"), )), "open_by_handle_at": ("long", ( ("int", "mountdirfd"), ("struct file_handle *", "handle"), ("int", "flags"), )), "open_tree": ("long", ( ("int", "dfd"), ("const char *", "path"), ("unsigned", "flags"), )), "openat": ("long", ( ("int", "dfd"), ("const char *", "filename"), ("int", "flags"), ("umode_t", "mode"), )), "openat2": ("long", ( ("int", "dfd"), ("const char *", "filename"), ("struct open_how *", "how"), ("size_t", "size"), )), "pause": ("long", ( )), "pciconfig_iobase": ("long", ( ("long", "which"), ("unsigned long", "bus"), ("unsigned long", "devfn"), )), "pciconfig_read": ("long", ( ("unsigned long", "bus"), ("unsigned long", "dfn"), ("unsigned long", "off"), ("unsigned long", "len"), ("void *", "buf"), )), "pciconfig_write": ("long", ( ("unsigned long", "bus"), ("unsigned long", "dfn"), ("unsigned long", "off"), ("unsigned long", "len"), ("void *", "buf"), )), "perf_event_open": ("long", ( ("struct perf_event_attr *", "attr_uptr"), ("pid_t", "pid"), ("int", "cpu"), ("int", "group_fd"), ("unsigned long", "flags"), )), "personality": ("long", ( ("unsigned int", "personality"), )), "pidfd_getfd": ("long", ( ("int", "pidfd"), ("int", "fd"), ("unsigned int", "flags"), )), "pidfd_open": ("long", ( ("pid_t", "pid"), ("unsigned int", "flags"), )), "pidfd_send_signal": ("long", ( ("int", "pidfd"), ("int", "sig"), ("siginfo_t *", "info"), ("unsigned int", "flags"), )), "pipe": ("long", ( ("int *", "fildes"), )), "pipe2": ("long", ( ("int *", "fildes"), ("int", "flags"), )), "pivot_root": ("long", ( ("const char *", "new_root"), ("const char *", "put_old"), )), "pkey_alloc": ("long", ( ("unsigned long", "flags"), ("unsigned long", "init_val"), )), "pkey_free": ("long", ( ("int", "pkey"), )), "pkey_mprotect": ("long", ( ("unsigned long", "start"), ("size_t", "len"), ("unsigned long", "prot"), ("int", "pkey"), )), "poll": ("long", ( ("struct pollfd *", "ufds"), ("unsigned int", "nfds"), ("int", "timeout"), )), "ppoll": ("long", ( ("struct pollfd *", "fds"), ("unsigned int", "nfds"), ("struct timespec *", "tmo_p"), ("const sigset_t *", "sigmask"), )), "ppoll_time32": ("long", ( ("struct pollfd *", "fds"), ("unsigned int", "nfds"), ("struct old_timespec *", "tmo_p"), ("const sigset_t *", "sigmask"), )), "prctl": ("long", ( ("int", "option"), ("unsigned long", "arg2"), ("unsigned long", "arg3"), ("unsigned long", "arg4"), ("unsigned long", "arg5"), )), "pread64": ("long", ( ("unsigned int", "fd"), ("char *", "buf"), ("size_t", "count"), ("loff_t", "pos"), )), "preadv": ("long", ( ("unsigned long", "fd"), ("const struct iovec *", "vec"), ("unsigned long", "vlen"), ("unsigned long", "pos_l"), ("unsigned long", "pos_h"), )), "preadv2": ("long", ( ("unsigned long", "fd"), ("const struct iovec *", "vec"), ("unsigned long", "vlen"), ("unsigned long", "pos_l"), ("unsigned long", "pos_h"), ("rwf_t", "flags"), )), "prlimit64": ("long", ( ("pid_t", "pid"), ("unsigned int", "resource"), ("const struct rlimit64 *", "new_rlim"), ("struct rlimit64 *", "old_rlim"), )), "process_vm_readv": ("long", ( ("pid_t", "pid"), ("const struct iovec *", "lvec"), ("unsigned long", "liovcnt"), ("const struct iovec *", "rvec"), ("unsigned long", "riovcnt"), ("unsigned long", "flags"), )), "process_vm_writev": ("long", ( ("pid_t", "pid"), ("const struct iovec *", "lvec"), ("unsigned long", "liovcnt"), ("const struct iovec *", "rvec"), ("unsigned long", "riovcnt"), ("unsigned long", "flags"), )), "pselect6": ("long", ( ("int", "nfds"), ("fd_set *", "readfds"), ("fd_set *", "writefds"), ("fd_set *", "exceptfds"), ("struct timespec *", "timeout"), ("void *", "sigmask"), )), "pselect6_time32": ("long", ( ("int", "nfds"), ("fd_set *", "readfds"), ("fd_set *", "writefds"), ("fd_set *", "exceptfds"), ("struct old_timespec32 *", ""), ("void *", "sigmask"), )), "ptrace": ("long", ( ("long", "request"), ("long", "pid"), ("unsigned long", "addr"), ("unsigned long", "data"), )), "pwrite64": ("long", ( ("unsigned int", "fd"), ("const char *", "buf"), ("size_t", "count"), ("loff_t", "pos"), )), "pwritev": ("long", ( ("unsigned long", "fd"), ("const struct iovec *", "vec"), ("unsigned long", "vlen"), ("unsigned long", "pos_l"), ("unsigned long", "pos_h"), )), "pwritev2": ("long", ( ("unsigned long", "fd"), ("const struct iovec *", "vec"), ("unsigned long", "vlen"), ("unsigned long", "pos_l"), ("unsigned long", "pos_h"), ("rwf_t", "flags"), )), "quotactl": ("long", ( ("unsigned int", "cmd"), ("const char *", "special"), ("qid_t", "id"), ("void *", "addr"), )), "read": ("long", ( ("unsigned int", "fd"), ("char *", "buf"), ("size_t", "count"), )), "readahead": ("long", ( ("int", "fd"), ("loff_t", "offset"), ("size_t", "count"), )), "readlink": ("long", ( ("const char *", "path"), ("char *", "buf"), ("int", "bufsiz"), )), "readlinkat": ("long", ( ("int", "dfd"), ("const char *", "path"), ("char *", "buf"), ("int", "bufsiz"), )), "readv": ("long", ( ("unsigned long", "fd"), ("const struct iovec *", "vec"), ("unsigned long", "vlen"), )), "reboot": ("long", ( ("int", "magic1"), ("int", "magic2"), ("unsigned int", "cmd"), ("void *", "arg"), )), "recv": ("long", ( ("int", "sockfd"), ("void *", "buf"), ("size_t", "len"), ("unsigned", "flags"), )), "recvfrom": ("long", ( ("int", "sockfd"), ("void *", "buf"), ("size_t", "len"), ("unsigned", "flags"), ("struct sockaddr *", "src_addr"), ("int *", "addrlen"), )), "recvmmsg": ("long", ( ("int", "fd"), ("struct mmsghdr *", "msg"), ("unsigned int", "vlen"), ("unsigned", "flags"), ("struct timespec *", "timeout"), )), "recvmmsg_time32": ("long", ( ("int", "fd"), ("struct mmsghdr *", "msg"), ("unsigned int", "vlen"), ("unsigned", "flags"), ("struct old_timespec32 *", "timeout"), )), "recvmsg": ("long", ( ("int", "fd"), ("struct user_msghdr *", "msg"), ("unsigned", "flags"), )), "remap_file_pages": ("long", ( ("unsigned long", "start"), ("unsigned long", "size"), ("unsigned long", "prot"), ("unsigned long", "pgoff"), ("unsigned long", "flags"), )), "removexattr": ("long", ( ("const char *", "path"), ("const char *", "name"), )), "rename": ("long", ( ("const char *", "oldname"), ("const char *", "newname"), )), "renameat": ("long", ( ("int", "olddfd"), ("const char *", "oldname"), ("int", "newdfd"), ("const char *", "newname"), )), "renameat2": ("long", ( ("int", "olddfd"), ("const char *", "oldname"), ("int", "newdfd"), ("const char *", "newname"), ("unsigned int", "flags"), )), "request_key": ("long", ( ("const char *", "_type"), ("const char *", "_description"), ("const char *", "_callout_info"), ("key_serial_t", "destringid"), )), "restart_syscall": ("long", ( )), "rmdir": ("long", ( ("const char *", "pathname"), )), "rseq": ("long", ( ("struct rseq *", "rseq"), ("uint32_t", "rseq_len"), ("int", "flags"), ("uint32_t", "sig"), )), "rt_sigaction": ("long", ( ("int", "signum"), ("const struct sigaction *", "act"), ("struct sigaction *", "oldact"), ("size_t", ""), )), "rt_sigpending": ("long", ( ("sigset_t *", "set"), ("size_t", "sigsetsize"), )), "rt_sigreturn": ("long", ( )), "rt_sigprocmask": ("long", ( ("int", "how"), ("sigset_t *", "set"), ("sigset_t *", "oset"), ("size_t", "sigsetsize"), )), "rt_sigqueueinfo": ("long", ( ("int", "pid"), ("int", "sig"), ("siginfo_t *", "uinfo"), )), "rt_sigsuspend": ("long", ( ("sigset_t *", "unewset"), ("size_t", "sigsetsize"), )), "rt_sigtimedwait": ("long", ( ("const sigset_t *", "uthese"), ("siginfo_t *", "uinfo"), ("const struct timespec *", "uts"), ("size_t", "sigsetsize"), )), "rt_sigtimedwait_time32": ("long", ( ("const sigset_t *", "uthese"), ("siginfo_t *", "uinfo"), ("const struct old_timespec32 *", "uts"), ("size_t", "sigsetsize"), )), "rt_tgsigqueueinfo": ("long", ( ("pid_t", "tgid"), ("pid_t", "pid"), ("int", "sig"), ("siginfo_t *", "uinfo"), )), "sched_get_priority_max": ("long", ( ("int", "policy"), )), "sched_get_priority_min": ("long", ( ("int", "policy"), )), "sched_getaffinity": ("long", ( ("pid_t", "pid"), ("unsigned int", "len"), ("unsigned long *", "user_mask_ptr"), )), "sched_getattr": ("long", ( ("pid_t", "pid"), ("struct sched_attr *", "attr"), ("unsigned int", "size"), ("unsigned int", "flags"), )), "sched_getparam": ("long", ( ("pid_t", "pid"), ("struct sched_param *", "param"), )), "sched_getscheduler": ("long", ( ("pid_t", "pid"), )), "sched_rr_get_interval": ("long", ( ("pid_t", "pid"), ("struct timespec *", "interval"), )), "sched_rr_get_interval_time32": ("long", ( ("pid_t", "pid"), ("struct old_timespec32 *", "interval"), )), "sched_setaffinity": ("long", ( ("pid_t", "pid"), ("unsigned int", "len"), ("unsigned long *", "user_mask_ptr"), )), "sched_setattr": ("long", ( ("pid_t", "pid"), ("struct sched_attr *", "attr"), ("unsigned int", "flags"), )), "sched_setparam": ("long", ( ("pid_t", "pid"), ("struct sched_param *", "param"), )), "sched_setscheduler": ("long", ( ("pid_t", "pid"), ("int", "policy"), ("struct sched_param *", "param"), )), "sched_yield": ("long", ( )), "seccomp": ("long", ( ("unsigned int", "op"), ("unsigned int", "flags"), ("const char *", "uargs"), )), "select": ("long", ( ("int", "n"), ("fd_set *", "inp"), ("fd_set *", "outp"), ("fd_set *", "exp"), ("struct timeval *", "tvp"), )), "newselect": ("long", ( ("int", "n"), ("fd_set *", "inp"), ("fd_set *", "outp"), ("fd_set *", "exp"), ("struct timeval *", "tvp"), )), "semctl": ("long", ( ("int", "semid"), ("int", "semnum"), ("int", "cmd"), ("unsigned long", "arg"), )), "semget": ("long", ( ("key_t", "key"), ("int", "nsems"), ("int", "semflg"), )), "semop": ("long", ( ("int", "semid"), ("struct sembuf *", "sops"), ("unsigned", "nsops"), )), "semtimedop": ("long", ( ("int", "semid"), ("struct sembuf *", "sops"), ("unsigned", "nsops"), ("const struct timespec *", "timeout"), )), "semtimedop_time32": ("long", ( ("int", "semid"), ("struct sembuf *", "sops"), ("unsigned", "nsops"), ("const struct old_timespec32 *", "timeout"), )), "send": ("long", ( ("int", "sockfd"), ("void *", "buf"), ("size_t", "len"), ("unsigned", "flags"), )), "sendfile": ("long", ( ("int", "out_fd"), ("int", "in_fd"), ("off_t *", "offset"), ("size_t", "count"), )), "sendfile64": ("long", ( ("int", "out_fd"), ("int", "in_fd"), ("loff_t *", "offset"), ("size_t", "count"), )), "sendmmsg": ("long", ( ("int", "fd"), ("struct mmsghdr *", "msg"), ("unsigned int", "vlen"), ("unsigned", "flags"), )), "sendmsg": ("long", ( ("int", "fd"), ("struct user_msghdr *", "msg"), ("unsigned", "flags"), )), "sendto": ("long", ( ("int", "sockfd"), ("void *", "buf"), ("size_t", "len"), ("unsigned", "flags"), ("struct sockaddr *", "destAddr"), ("int", "addrlen"), )), "set_mempolicy": ("long", ( ("int", "mode"), ("const unsigned long *", "nmask"), ("unsigned long", "maxnode"), )), "set_robust_list": ("long", ( ("struct robust_list_head *", "head"), ("size_t", "len"), )), "set_tid_address": ("long", ( ("int *", "tidptr"), )), "setdomainname": ("long", ( ("char *", "name"), ("int", "len"), )), "setfsgid": ("long", ( ("gid_t", "gid"), )), "setfsgid16": ("long", ( ("old_gid_t", "gid"), )), "setfsuid": ("long", ( ("uid_t", "uid"), )), "setfsuid16": ("long", ( ("old_uid_t", "uid"), )), "setgid": ("long", ( ("gid_t", "gid"), )), "setgid16": ("long", ( ("old_gid_t", "gid"), )), "setgroups": ("long", ( ("int", "gidsetsize"), ("gid_t *", "grouplist"), )), "setgroups16": ("long", ( ("int", "gidsetsize"), ("old_gid_t *", "grouplist"), )), "sethostname": ("long", ( ("char *", "name"), ("int", "len"), )), "setitimer": ("long", ( ("int", "which"), ("struct itimerval *", "value"), ("struct itimerval *", "ovalue"), )), "setns": ("long", ( ("int", "fd"), ("int", "nstype"), )), "setpgid": ("long", ( ("pid_t", "pid"), ("pid_t", "pgid"), )), "setpriority": ("long", ( ("int", "which"), ("int", "who"), ("int", "niceval"), )), "setregid": ("long", ( ("gid_t", "rgid"), ("gid_t", "egid"), )), "setregid16": ("long", ( ("old_gid_t", "rgid"), ("old_gid_t", "egid"), )), "setresgid": ("long", ( ("gid_t", "rgid"), ("gid_t", "egid"), ("gid_t", "sgid"), )), "setresgid16": ("long", ( ("old_gid_t", "rgid"), ("old_gid_t", "egid"), ("old_gid_t", "sgid"), )), "setresuid": ("long", ( ("uid_t", "ruid"), ("uid_t", "euid"), ("uid_t", "suid"), )), "setresuid16": ("long", ( ("old_uid_t", "ruid"), ("old_uid_t", "euid"), ("old_uid_t", "suid"), )), "setreuid": ("long", ( ("uid_t", "ruid"), ("uid_t", "euid"), )), "setreuid16": ("long", ( ("old_uid_t", "ruid"), ("old_uid_t", "euid"), )), "setrlimit": ("long", ( ("unsigned int", "resource"), ("struct rlimit *", "rlim"), )), "setsid": ("long", ( )), "setsockopt": ("long", ( ("int", "fd"), ("int", "level"), ("int", "optname"), ("char *", "optval"), ("int", "optlen"), )), "settimeofday": ("long", ( ("struct timeval *", "tv"), ("struct timezone *", "tz"), )), "setuid": ("long", ( ("uid_t", "uid"), )), "setuid16": ("long", ( ("old_uid_t", "uid"), )), "setxattr": ("long", ( ("const char *", "path"), ("const char *", "name"), ("const void *", "value"), ("size_t", "size"), ("int", "flags"), )), "sgetmask": ("long", ( )), "shmat": ("long", ( ("int", "shmid"), ("char *", "shmaddr"), ("int", "shmflg"), )), "shmctl": ("long", ( ("int", "shmid"), ("int", "cmd"), ("struct shmid_ds *", "buf"), )), "shmdt": ("long", ( ("char *", "shmaddr"), )), "shmget": ("long", ( ("key_t", "key"), ("size_t", "size"), ("int", "flag"), )), "shutdown": ("long", ( ("int", "sockfd"), ("int", "how"), )), "sigaction": ("long", ( ("int", "signum"), ("const struct old_sigaction *", "act"), ("struct old_sigaction *", "oldact"), )), "sigaltstack": ("long", ( ("const struct sigaltstack *", "uss"), ("struct sigaltstack *", "uoss"), )), "signal": ("long", ( ("int", "sig"), ("__sighandler_t", "handler"), )), "signalfd": ("long", ( ("int", "ufd"), ("sigset_t *", "user_mask"), ("size_t", "sizemask"), )), "signalfd4": ("long", ( ("int", "ufd"), ("sigset_t *", "user_mask"), ("size_t", "sizemask"), ("int", "flags"), )), "sigpending": ("long", ( ("old_sigset_t *", "set"), )), "sigprocmask": ("long", ( ("int", "how"), ("old_sigset_t *", "set"), ("old_sigset_t *", "oset"), )), "sigsuspend": ("long", ( ("int", "unused1"), ("int", "unused2"), ("old_sigset_t", "mask"), )), "socket": ("long", ( ("int", "domain"), ("int", "type"), ("int", "protocol"), )), "socketcall": ("long", ( ("int", "call"), ("unsigned long *", "args"), )), "socketpair": ("long", ( ("int", "domain"), ("int", "type"), ("int", "protocol"), ("int *", "sv"), )), "splice": ("long", ( ("int", "fd_in"), ("loff_t *", "off_in"), ("int", "fd_out"), ("loff_t *", "off_out"), ("size_t", "len"), ("unsigned int", "flags"), )), "spu_create": ("long", ( ("const char *", "name"), ("unsigned int", "flags"), ("umode_t", "mode"), ("int", "fd"), )), "spu_run": ("long", ( ("int", "fd"), ("__u32 *", "unpc"), ("__u32 *", "ustatus"), )), "ssetmask": ("long", ( ("int", "newmask"), )), "stat": ("long", ( ("const char *", "filename"), ("struct __old_kernel_stat *", "statbuf"), )), "stat64": ("long", ( ("const char *", "filename"), ("struct stat64 *", "statbuf"), )), "statx": ("long", ( ("int", "dfd"), ("const char *", "path"), ("unsigned", "flags"), ("unsigned", "mask"), ("struct statx *", "buf"), )), "statfs": ("long", ( ("const char *", "path"), ("struct statfs *", "buf"), )), "statfs64": ("long", ( ("const char *", "path"), ("size_t", "sz"), ("struct statfs64 *", "buf"), )), "statx": ("long", ( ("int", "dfd"), ("const char *", "path"), ("unsigned", "flags"), ("unsigned", "mask"), ("struct statx *", "buffer"), )), "stime": ("long", ( ("old_time_t *", "tptr"), )), "stime32": ("long", ( ("old_time32_t *", "tptr"), )), "swapoff": ("long", ( ("const char *", "specialfile"), )), "swapon": ("long", ( ("const char *", "specialfile"), ("int", "swap_flags"), )), "symlink": ("long", ( ("const char *", "old"), ("const char *", "new"), )), "symlinkat": ("long", ( ("const char *", "oldname"), ("int", "newdfd"), ("const char *", "newname"), )), "sync": ("long", ( )), "sync_file_range": ("long", ( ("int", "fd"), ("loff_t", "offset"), ("loff_t", "nbytes"), ("unsigned int", "flags"), )), "sync_file_range2": ("long", ( ("int", "fd"), ("unsigned int", "flags"), ("loff_t", "offset"), ("loff_t", "nbytes"), )), "syncfs": ("long", ( ("int", "fd"), )), "sysctl": ("long", ( ("struct __sysctl_args *", "args"), )), "sysfs": ("long", ( ("int", "option"), ("unsigned long", "arg1"), ("unsigned long", "arg2"), )), "sysinfo": ("long", ( ("struct sysinfo *", "info"), )), "syslog": ("long", ( ("int", "type"), ("char *", "buf"), ("int", "len"), )), "tee": ("long", ( ("int", "fdin"), ("int", "fdout"), ("size_t", "len"), ("unsigned int", "flags"), )), "tgkill": ("long", ( ("int", "tgid"), ("int", "pid"), ("int", "sig"), )), "time": ("long", ( ("old_time_t *", "tloc"), )), "time32": ("long", ( ("old_time32_t *", "tloc"), )), "timer_create": ("long", ( ("clockid_t", "which_clock"), ("struct sigevent *", "timer_event_spec"), ("timer_t *", "created_timer_id"), )), "timer_delete": ("long", ( ("timer_t", "timer_id"), )), "timer_getoverrun": ("long", ( ("timer_t", "timer_id"), )), "timer_gettime": ("long", ( ("timer_t", "timer_id"), ("struct itimerspec *", "setting"), )), "timer_gettime32": ("long", ( ("timer_t", "timer_id"), ("struct old_itimerspec32 *", "setting"), )), "timer_settime": ("long", ( ("timer_t", "timer_id"), ("int", "flags"), ("const struct itimerspec *", "new_setting"), ("struct itimerspec *", "old_setting"), )), "timer_settime32": ("long", ( ("timer_t", "timer_id"), ("int", "flags"), ("struct old_itimerspec32 *", "new"), ("struct old_itimerspec32 *", "old"), )), "timerfd_create": ("long", ( ("int", "clockid"), ("int", "flags"), )), "timerfd_gettime": ("long", ( ("int", "ufd"), ("struct itimerspec *", "otmr"), )), "timerfd_gettime32": ("long", ( ("int", "ufd"), ("struct old_itimerspec32 *", "otmr"), )), "timerfd_settime": ("long", ( ("int", "ufd"), ("int", "flags"), ("const struct itimerspec *", "utmr"), ("struct itimerspec *", "otmr"), )), "timerfd_settime32": ("long", ( ("int", "ufd"), ("int", "flags"), ("const struct old_itimerspec32 *", "utmr"), ("struct old_itimerspec32 *", "otmr"), )), "times": ("long", ( ("struct tms *", "tbuf"), )), "tkill": ("long", ( ("int", "pid"), ("int", "sig"), )), "truncate": ("long", ( ("const char *", "path"), ("long", "length"), )), "truncate64": ("long", ( ("const char *", "path"), ("loff_t", "length"), )), "umask": ("long", ( ("int", "mask"), )), "umount": ("long", ( ("char *", "name"), ("int", "flags"), )), "uname": ("long", ( ("struct old_utsname *", "buf"), )), "unlink": ("long", ( ("const char *", "pathname"), )), "unlinkat": ("long", ( ("int", "dfd"), ("const char *", "pathname"), ("int", "flag"), )), "unshare": ("long", ( ("unsigned long", "unshare_flags"), )), "uselib": ("long", ( ("const char *", "library"), )), "userfaultfd": ("long", ( ("int", "flags"), )), "ustat": ("long", ( ("unsigned", "dev"), ("struct ustat *", "ubuf"), )), "utime": ("long", ( ("char *", "filename"), ("struct utimbuf *", "times"), )), "utime32": ("long", ( ("const char *", "filename"), ("struct old_utimbuf32 *", "t"), )), "utimensat": ("long", ( ("int", "dfd"), ("const char *", "filename"), ("struct timespec *", "utimes"), ("int", "flags"), )), "utimensat_time32": ("long", ( ("unsigned int", "dfd"), ("const char *", "filename"), ("struct old_timespec32 *", "t"), ("int", "flags"), )), "utimes": ("long", ( ("char *", "filename"), ("struct old_timeval *", "utimes"), )), "utimes_time32": ("long", ( ("const char *", "filename"), ("struct old_timeval32 *", "t"), )), "vfork": ("long", ( )), "vhangup": ("long", ( )), "vmsplice": ("long", ( ("int", "fd"), ("const struct iovec *", "iov"), ("unsigned long", "nr_segs"), ("unsigned int", "flags"), )), "wait4": ("long", ( ("pid_t", "pid"), ("int *", "stat_addr"), ("int", "options"), ("struct rusage *", "ru"), )), "waitid": ("long", ( ("int", "which"), ("pid_t", "pid"), ("struct siginfo *", "infop"), ("int", "options"), ("struct rusage *", "ru"), )), "waitpid": ("long", ( ("pid_t", "pid"), ("int *", "stat_addr"), ("int", "options"), )), "write": ("long", ( ("unsigned int", "fd"), ("const char *", "buf"), ("size_t", "count"), )), "writev": ("long", ( ("unsigned long", "fd"), ("const struct iovec *", "vec"), ("unsigned long", "vlen"), )), } ''' update syscalls from https://github.com/strace/strace/linux/ARCH/syscallent.h 1. %s/\[.*= //g 2. %s/{.*),\s*"/\'sys_/g 3. %s/".*,/\',/g 4. paste the processed list 4. call UtilMgr.printSyscalls(ConfigMgr.SYSCALL_X86) ''' # Define common 32bit syscalls from 403 ~ 423 # SYSCALL_COMMON32 = [ 'sys_clock_gettime64', 'sys_clock_settime64', 'sys_clock_adjtime64', 'sys_clock_getres_time64', 'sys_clock_nanosleep_time64', 'sys_timer_gettime64', 'sys_timer_settime64', 'sys_timerfd_gettime64', 'sys_timerfd_settime64', 'sys_utimensat_time64', 'sys_pselect6_time64', 'sys_ppoll_time64', 'sys_unused', 'sys_io_pgetevents_time64', 'sys_recvmmsg_time64', 'sys_mq_timedsend_time64', 'sys_mq_timedreceive_time64', 'sys_semtimedop_time64', 'sys_rt_sigtimedwait_time64', 'sys_futex_time64', 'sys_sched_rr_get_interval_time64', ] # Define common syscalls from 424 ~ 435 # SYSCALL_COMMON = [ 'sys_pidfd_send_signal', 'sys_io_uring_setup', 'sys_io_uring_enter', 'sys_io_uring_register', 'sys_open_tree', 'sys_move_mount', 'sys_fsopen', 'sys_fsconfig', 'sys_fsmount', 'sys_fspick', 'sys_pidfd_open', 'sys_clone3', ] # Define syscall for ARM # SYSCALL_ARM = [ 'sys_restart_syscall', 'sys_exit', 'sys_fork', 'sys_read', 'sys_write', 'sys_open', 'sys_close', 'sys_waitpid', 'sys_creat', 'sys_link', 'sys_unlink', 'sys_execve', 'sys_chdir', 'sys_time', 'sys_mknod', 'sys_chmod', 'sys_lchown', 'sys_break', 'sys_oldstat', 'sys_lseek', 'sys_getpid', 'sys_mount', 'sys_umount', 'sys_setuid', 'sys_getuid', 'sys_stime', 'sys_ptrace', 'sys_alarm', 'sys_oldfstat', 'sys_pause', 'sys_utime', 'sys_stty', 'sys_gtty', 'sys_access', 'sys_nice', 'sys_ftime', 'sys_sync', 'sys_kill', 'sys_rename', 'sys_mkdir', 'sys_rmdir', 'sys_dup', 'sys_pipe', 'sys_times', 'sys_prof', 'sys_brk', 'sys_setgid', 'sys_getgid', 'sys_signal', 'sys_geteuid', 'sys_getegid', 'sys_acct', 'sys_umount2', 'sys_lock', 'sys_ioctl', 'sys_fcntl', 'sys_mpx', 'sys_setpgid', 'sys_ulimit', 'sys_oldolduname', 'sys_umask', 'sys_chroot', 'sys_ustat', 'sys_dup2', 'sys_getppid', 'sys_getpgrp', 'sys_setsid', 'sys_sigaction', 'sys_sgetmask', 'sys_ssetmask', 'sys_setreuid', 'sys_setregid', 'sys_sigsuspend', 'sys_sigpending', 'sys_sethostname', 'sys_setrlimit', 'sys_getrlimit', 'sys_getrusage', 'sys_gettimeofday', 'sys_settimeofday', 'sys_getgroups', 'sys_setgroups', 'sys_select', 'sys_symlink', 'sys_oldlstat', 'sys_readlink', 'sys_uselib', 'sys_swapon', 'sys_reboot', 'sys_readdir', 'sys_mmap', 'sys_munmap', 'sys_truncate', 'sys_ftruncate', 'sys_fchmod', 'sys_fchown', 'sys_getpriority', 'sys_setpriority', 'sys_profil', 'sys_statfs', 'sys_fstatfs', 'sys_ioperm', 'sys_socketcall', 'sys_syslog', 'sys_setitimer', 'sys_getitimer', 'sys_stat', 'sys_lstat', 'sys_fstat', 'sys_olduname', 'sys_iopl', 'sys_vhangup', 'sys_idle', 'sys_syscall', 'sys_wait4', 'sys_swapoff', 'sys_sysinfo', 'sys_ipc', 'sys_fsync', 'sys_sigreturn', 'sys_clone', 'sys_setdomainname', 'sys_uname', 'sys_modify_ldt', 'sys_adjtimex', 'sys_mprotect', 'sys_sigprocmask', 'sys_create_module', 'sys_init_module', 'sys_delete_module', 'sys_get_kernel_syms', 'sys_quotactl', 'sys_getpgid', 'sys_fchdir', 'sys_bdflush', 'sys_sysfs', 'sys_personality', 'sys_afs_syscall', 'sys_setfsuid', 'sys_setfsgid', 'sys_llseek', 'sys_getdents', 'sys_newselect', 'sys_flock', 'sys_msync', 'sys_readv', 'sys_writev', 'sys_getsid', 'sys_fdatasync', 'sys_sysctl', 'sys_mlock', 'sys_munlock', 'sys_mlockall', 'sys_munlockall', 'sys_sched_setparam', 'sys_sched_getparam', 'sys_sched_setscheduler', 'sys_sched_getscheduler', 'sys_sched_yield', 'sys_sched_get_priority_max', 'sys_sched_get_priority_min', 'sys_sched_rr_get_interval', 'sys_nanosleep', 'sys_mremap', 'sys_setresuid', 'sys_getresuid', 'sys_vm86', 'sys_query_module', 'sys_poll', 'sys_nfsservctl', 'sys_setresgid', 'sys_getresgid', 'sys_prctl', 'sys_rt_sigreturn', 'sys_rt_sigaction', 'sys_rt_sigprocmask', 'sys_rt_sigpending', 'sys_rt_sigtimedwait', 'sys_rt_sigqueueinfo', 'sys_rt_sigsuspend', 'sys_pread64', 'sys_pwrite64', 'sys_chown', 'sys_getcwd', 'sys_capget', 'sys_capset', 'sys_sigaltstack', 'sys_sendfile', 'sys_getpmsg', 'sys_putpmsg', 'sys_vfork', 'sys_ugetrlimit', 'sys_mmap2', 'sys_truncate64', 'sys_ftruncate64', 'sys_stat64', 'sys_lstat64', 'sys_fstat64', 'sys_lchown32', 'sys_getuid32', 'sys_getgid32', 'sys_geteuid32', 'sys_getegid32', 'sys_setreuid32', 'sys_setregid32', 'sys_getgroups32', 'sys_setgroups32', 'sys_fchown32', 'sys_setresuid32', 'sys_getresuid32', 'sys_setresgid32', 'sys_getresgid32', 'sys_chown32', 'sys_setuid32', 'sys_setgid32', 'sys_setfsuid32', 'sys_setfsgid32', 'sys_getdents64', 'sys_pivot_root', 'sys_mincore', 'sys_madvise', 'sys_fcntl64', 'sys_tux', 'sys_unused', '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_sendfile64', 'sys_futex', 'sys_sched_setaffinity', 'sys_sched_getaffinity', 'sys_io_setup', 'sys_io_destroy', 'sys_io_getevents', 'sys_io_submit', 'sys_io_cancel', 'sys_exit_group', 'sys_lookup_dcookie', 'sys_epoll_create', 'sys_epoll_ctl', 'sys_epoll_wait', 'sys_remap_file_pages', 'sys_set_thread_area', 'sys_get_thread_area', 'sys_set_tid_address', '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_statfs64', 'sys_fstatfs64', 'sys_tgkill', 'sys_utimes', 'sys_fadvise64_64', 'sys_pciconfig_iobase', 'sys_pciconfig_read', 'sys_pciconfig_write', 'sys_mq_open', 'sys_mq_unlink', 'sys_mq_timedsend', 'sys_mq_timedreceive', 'sys_mq_notify', 'sys_mq_getsetattr', 'sys_waitid', 'sys_socket', 'sys_bind', 'sys_connect', 'sys_listen', 'sys_accept', 'sys_getsockname', 'sys_getpeername', 'sys_socketpair', 'sys_send', 'sys_sendto', 'sys_recv', 'sys_recvfrom', 'sys_shutdown', 'sys_setsockopt', 'sys_getsockopt', 'sys_sendmsg', 'sys_recvmsg', 'sys_semop', 'sys_semget', 'sys_semctl', 'sys_msgsnd', 'sys_msgrcv', 'sys_msgget', 'sys_msgctl', 'sys_shmat', 'sys_shmdt', 'sys_shmget', 'sys_shmctl', 'sys_add_key', 'sys_request_key', 'sys_keyctl', 'sys_semtimedop', 'sys_vserver', 'sys_ioprio_set', 'sys_ioprio_get', 'sys_inotify_init', 'sys_inotify_add_watch', 'sys_inotify_rm_watch', 'sys_mbind', 'sys_get_mempolicy', 'sys_set_mempolicy', 'sys_openat', 'sys_mkdirat', 'sys_mknodat', 'sys_fchownat', 'sys_futimesat', 'sys_fstatat64', '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_sync_file_range2', 'sys_tee', 'sys_vmsplice', 'sys_move_pages', 'sys_getcpu', 'sys_epoll_pwait', 'sys_kexec_load', 'sys_utimensat', 'sys_signalfd', 'sys_timerfd_create', 'sys_eventfd', 'sys_fallocate', 'sys_timerfd_settime', 'sys_timerfd_gettime', '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_accept4', '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_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', 'sys_rseq', 'sys_io_pgetevents', 'sys_migrate_pages', 'sys_kexec_file_load', 'sys_unused', ] + SYSCALL_COMMON32 + SYSCALL_COMMON # Define syscall for AARCH64 # SYSCALL_AARCH64 = [ '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_fcntl', '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_statfs', 'sys_fstatfs', 'sys_truncate', 'sys_ftruncate', '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_lseek', 'sys_read', 'sys_write', 'sys_readv', 'sys_writev', 'sys_pread64', 'sys_pwrite64', 'sys_preadv', 'sys_pwritev', 'sys_sendfile', 'sys_pselect6', 'sys_ppoll', 'sys_signalfd4', 'sys_vmsplice', 'sys_splice', 'sys_tee', 'sys_readlinkat', 'sys_newfstatat', 'sys_fstat', 'sys_sync', 'sys_fsync', 'sys_fdatasync', '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_mmap', 'sys_fadvise64', '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_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', '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', 'sys_io_pgetevents', 'sys_rseq', 'sys_kexec_file_load', ] + ['sys_null' for idx in range(295, 423, 1)] + SYSCALL_COMMON + \ ['close_range', 'openat2', 'pidfd_getfd', 'pidfd_getfd', 'faccessat2'] # Define syscall for x86 # SYSCALL_X86 = [ 'sys_restart_syscall', 'sys_exit', 'sys_fork', 'sys_read', 'sys_write', 'sys_open', 'sys_close', 'sys_waitpid', 'sys_creat', 'sys_link', 'sys_unlink', 'sys_execve', 'sys_chdir', 'sys_time', 'sys_mknod', 'sys_chmod', 'sys_lchown', 'sys_break', 'sys_oldstat', 'sys_lseek', 'sys_getpid', 'sys_mount', 'sys_umount', 'sys_setuid', 'sys_getuid', 'sys_stime', 'sys_ptrace', 'sys_alarm', 'sys_oldfstat', 'sys_pause', 'sys_utime', 'sys_stty', 'sys_gtty', 'sys_access', 'sys_nice', 'sys_ftime', 'sys_sync', 'sys_kill', 'sys_rename', 'sys_mkdir', 'sys_rmdir', 'sys_dup', 'sys_pipe', 'sys_times', 'sys_prof', 'sys_brk', 'sys_setgid', 'sys_getgid', 'sys_signal', 'sys_geteuid', 'sys_getegid', 'sys_acct', 'sys_umount2', 'sys_lock', 'sys_ioctl', 'sys_fcntl', 'sys_mpx', 'sys_setpgid', 'sys_ulimit', 'sys_oldolduname', 'sys_umask', 'sys_chroot', 'sys_ustat', 'sys_dup2', 'sys_getppid', 'sys_getpgrp', 'sys_setsid', 'sys_sigaction', 'sys_sgetmask', 'sys_ssetmask', 'sys_setreuid', 'sys_setregid', 'sys_sigsuspend', 'sys_sigpending', 'sys_sethostname', 'sys_setrlimit', 'sys_getrlimit', 'sys_getrusage', 'sys_gettimeofday', 'sys_settimeofday', 'sys_getgroups', 'sys_setgroups', 'sys_select', 'sys_symlink', 'sys_oldlstat', 'sys_readlink', 'sys_uselib', 'sys_swapon', 'sys_reboot', 'sys_readdir', 'sys_mmap', 'sys_munmap', 'sys_truncate', 'sys_ftruncate', 'sys_fchmod', 'sys_fchown', 'sys_getpriority', 'sys_setpriority', 'sys_profil', 'sys_statfs', 'sys_fstatfs', 'sys_ioperm', 'sys_socketcall', 'sys_syslog', 'sys_setitimer', 'sys_getitimer', 'sys_stat', 'sys_lstat', 'sys_fstat', 'sys_olduname', 'sys_iopl', 'sys_vhangup', 'sys_idle', 'sys_vm86old', 'sys_wait4', 'sys_swapoff', 'sys_sysinfo', 'sys_ipc', 'sys_fsync', 'sys_sigreturn', 'sys_clone', 'sys_setdomainname', 'sys_uname', 'sys_modify_ldt', 'sys_adjtimex', 'sys_mprotect', 'sys_sigprocmask', 'sys_create_module', 'sys_init_module', 'sys_delete_module', 'sys_get_kernel_syms', 'sys_quotactl', 'sys_getpgid', 'sys_fchdir', 'sys_bdflush', 'sys_sysfs', 'sys_personality', 'sys_afs_syscall', 'sys_setfsuid', 'sys_setfsgid', 'sys_llseek', 'sys_getdents', 'sys_newselect', 'sys_flock', 'sys_msync', 'sys_readv', 'sys_writev', 'sys_getsid', 'sys_fdatasync', 'sys_sysctl', 'sys_mlock', 'sys_munlock', 'sys_mlockall', 'sys_munlockall', 'sys_sched_setparam', 'sys_sched_getparam', 'sys_sched_setscheduler', 'sys_sched_getscheduler', 'sys_sched_yield', 'sys_sched_get_priority_max', 'sys_sched_get_priority_min', 'sys_sched_rr_get_interval', 'sys_nanosleep', 'sys_mremap', 'sys_setresuid', 'sys_getresuid', 'sys_vm86', 'sys_query_module', 'sys_poll', 'sys_nfsservctl', 'sys_setresgid', 'sys_getresgid', 'sys_prctl', 'sys_rt_sigreturn', 'sys_rt_sigaction', 'sys_rt_sigprocmask', 'sys_rt_sigpending', 'sys_rt_sigtimedwait', 'sys_rt_sigqueueinfo', 'sys_rt_sigsuspend', 'sys_pread64', 'sys_pwrite64', 'sys_chown', 'sys_getcwd', 'sys_capget', 'sys_capset', 'sys_sigaltstack', 'sys_sendfile', 'sys_getpmsg', 'sys_putpmsg', 'sys_vfork', 'sys_ugetrlimit', 'sys_mmap2', 'sys_truncate64', 'sys_ftruncate64', 'sys_stat64', 'sys_lstat64', 'sys_fstat64', 'sys_lchown32', 'sys_getuid32', 'sys_getgid32', 'sys_geteuid32', 'sys_getegid32', 'sys_setreuid32', 'sys_setregid32', 'sys_getgroups32', 'sys_setgroups32', 'sys_fchown32', 'sys_setresuid32', 'sys_getresuid32', 'sys_setresgid32', 'sys_getresgid32', 'sys_chown32', 'sys_setuid32', 'sys_setgid32', 'sys_setfsuid32', 'sys_setfsgid32', 'sys_pivot_root', 'sys_mincore', 'sys_madvise', 'sys_getdents64', 'sys_fcntl64', 'sys_null', 'sys_null', '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_sendfile64', 'sys_futex', 'sys_sched_setaffinity', 'sys_sched_getaffinity', 'sys_set_thread_area', 'sys_get_thread_area', 'sys_io_setup', 'sys_io_destroy', 'sys_io_getevents', 'sys_io_submit', 'sys_io_cancel', 'sys_fadvise64', 'sys_set_zone_reclaim', 'sys_exit_group', 'sys_lookup_dcookie', 'sys_epoll_create', 'sys_epoll_ctl', 'sys_epoll_wait', 'sys_remap_file_pages', 'sys_set_tid_address', '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_statfs64', 'sys_fstatfs64', 'sys_tgkill', 'sys_utimes', 'sys_fadvise64_64', 'sys_vserver', 'sys_mbind', 'sys_get_mempolicy', 'sys_set_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_setaltroot', '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_fstatat64', '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_sync_file_range', 'sys_tee', 'sys_vmsplice', 'sys_move_pages', 'sys_getcpu', 'sys_epoll_pwait', 'sys_utimensat', 'sys_signalfd', 'sys_timerfd_create', 'sys_eventfd', 'sys_fallocate', 'sys_timerfd_settime', 'sys_timerfd_gettime', '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_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_socket', 'sys_socketpair', 'sys_bind', 'sys_connect', 'sys_listen', 'sys_accept4', 'sys_getsockopt', 'sys_setsockopt', 'sys_getsockname', 'sys_getpeername', 'sys_sendto', 'sys_sendmsg', 'sys_recvfrom', 'sys_recvmsg', 'sys_shutdown', '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', 'sys_arch_prctl', 'sys_io_pgetevents', 'sys_rseq', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_reserved', 'sys_semget', 'sys_semctl', 'sys_shmget', 'sys_shmctl', 'sys_shmat', 'sys_shmdt', 'sys_msgget', 'sys_msgsnd', 'sys_msgrcv', 'sys_msgctl', ] + SYSCALL_COMMON32 + SYSCALL_COMMON # Define syscall for x86_64 # SYSCALL_X64 = [ 'sys_read', 'sys_write', 'sys_open', 'sys_close', 'sys_stat', 'sys_fstat', 'sys_lstat', 'sys_poll', 'sys_lseek', 'sys_mmap', 'sys_mprotect', 'sys_munmap', 'sys_brk', 'sys_rt_sigaction', 'sys_rt_sigprocmask', 'sys_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_sendfile', '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', 'sys_clone', 'sys_fork', 'sys_vfork', 'sys_execve', 'sys_exit', 'sys_wait4', 'sys_kill', 'sys_uname', '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', 'sys_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_umount2', 'sys_swapon', 'sys_swapoff', 'sys_reboot', 'sys_sethostname', 'sys_setdomainname', 'sys_iopl', 'sys_ioperm', 'sys_create_module', 'sys_init_module', 'sys_delete_module', 'sys_get_kernel_syms', 'sys_query_module', 'sys_quotactl', 'sys_nfsservctl', 'sys_getpmsg', 'sys_putpmsg', 'sys_afs_syscall', 'sys_tuxcall', 'sys_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', 'sys_set_thread_area', 'sys_io_setup', 'sys_io_destroy', 'sys_io_getevents', 'sys_io_submit', 'sys_io_cancel', 'sys_get_thread_area', 'sys_lookup_dcookie', 'sys_epoll_create', 'sys_epoll_ctl_old', 'sys_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', 'sys_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', 'sys_sched_setattr', 'sys_sched_getattr', 'sys_renameat2', 'sys_seccomp', 'sys_getrandom', 'sys_memfd_create', 'sys_kexec_file_load', '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', 'sys_io_pgetevents', 'sys_rseq', ] + ['sys_null' for idx in range(335, 423, 1)] + SYSCALL_COMMON # Define default syscall list # sysList = [] # Define default register list # regList = [] # Define registers by number sequence # REGS_X86 = [ 'eax', 'ecx', 'edx', 'ebx', 'esp', 'ebp', 'esi', 'edi', 'eip', 'eflags', '', 'st0', 'st1', 'st2', 'st3', 'st4', 'st5', 'st6', 'st7', '', '', 'xmm0', 'xmm1', 'xmm2', 'xmm3', 'xmm4', 'xmm5', 'xmm6', 'xmm7', 'mm0', 'mm1', 'mm2', 'mm3', 'mm4', 'mm5', 'mm6', 'mm7', 'fcw', 'fsw', 'mxcsr', 'es', 'cs', 'ss', 'ds', 'fs', 'gs', '', '', 'tr', 'ldtr' ] REGS_X64 = [ 'rax', 'rdx', 'rcx', 'rbx', 'rsi', 'rdi', 'rbp', 'rsp', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15', 'rip', 'xmm0', 'xmm1', 'xmm2', 'xmm3', 'xmm4', 'xmm5', 'xmm6', 'xmm7', 'xmm8', 'xmm9', 'xmm10', 'xmm11', 'xmm12', 'xmm13', 'xmm14', 'xmm15', 'st0', 'st1', 'st2', 'st3', 'st4', 'st5', 'st6', 'st7', 'mm0', 'mm1', 'mm2', 'mm3', 'mm4', 'mm5', 'mm6', 'mm7', 'rflags', 'es', 'cs', 'ss', 'ds', 'fs', 'gs', '', '', 'fs.base', 'gs.base', '', '', 'tr', 'ldtr', 'mxcsr', 'fcw', 'fsw' ] REGS_ARM = ['r%d' % idx for idx in range(0, 16, 1)] REGS_AARCH64 = \ ['x%d' % idx for idx in range(0, 31, 1)] + \ ['sp', 'pc', 'ELP_mode', 'RA_SIGN_STATE', '', ''] + \ ['reserved' for idx in range(37, 46, 1)] + \ ['VG', 'FFR'] + ['p%d' % idx for idx in range(0, 16, 1)] + \ ['v%d' % idx for idx in range(0, 32, 1)] + \ ['z%d' % idx for idx in range(0, 32, 1)] pcRegIndex = { 'arm': REGS_ARM.index('r14'), 'aarch64': REGS_AARCH64.index('pc'), 'x86': REGS_X86.index('eip'), 'x64': REGS_X64.index('rip'), } # Define syscall register # SYSREG_LIST = { "powerpc": "gpr0", "arm": "r7", "aarch64": "x8", "x64": "orig_rax", "x86": "orig_eax" } # Define return register # RET_LIST = { "powerpc": "result", "arm": "r0", "aarch64": "x0", "x64": "rax", "x86": "eax" } # Define signal # SIG_LIST = [ 'ZERO', 'SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', #4# 'SIGTRAP', 'SIGABRT', 'SIGBUS', 'SIGFPE', #8# 'SIGKILL', 'SIGUSR1', 'SIGSEGV', 'SIGUSR2', #12# 'SIGPIPE', 'SIGALRM', 'SIGTERM', 'SIGSTKFLT', #16# 'SIGCHLD', 'SIGCONT', 'SIGSTOP', 'SIGTSTP', #20# 'SIGTTIN', 'SIGTTOU', 'SIGURG', 'SIGXCPU', #24# 'SIGXFSZ', 'SIGVTALRM', 'SIGPROF', 'SIGWINCH', #28# 'SIGIO', 'SIGPWR', 'SIGSYS', 'NONE', 'NONE'] + \ ['SIGRT%d' % idx for idx in range(0, 32, 1)] SIGKILL = SIG_LIST.index('SIGKILL') # stat list from http://linux.die.net/man/5/proc # STAT_ATTR = [ 'PID', 'COMM', 'STATE', 'PPID', 'PGRP', 'SESSIONID', #5# 'NRTTY', 'TPGID', 'FLAGS', 'MINFLT', 'CMINFLT', #10# 'MAJFLT', 'CMAJFLT', 'UTIME', 'STIME', 'CUTIME', #15# 'CSTIME', 'PRIORITY', 'NICE', 'NRTHREAD', 'ITERALVAL', #20# 'STARTTIME', 'VSIZE', 'RSS', 'RSSLIM', 'STARTCODE', #25# 'ENDCODE', 'STARTSTACK', 'SP', 'PC', 'SIGNAL', #30# 'BLOCKED', 'SIGIGNORE', 'SIGCATCH', 'WCHEN', 'NSWAP', #35# 'CNSWAP', 'EXITSIGNAL', 'PROCESSOR', 'RTPRIORITY', #39# 'POLICY', 'DELAYBLKTICK', 'GUESTTIME', 'CGUESTTIME' #43# 'STARTDATA', 'ENDDATA', 'STARTBRK', 'ARGSTART', 'ARGEND', #48# 'ENVSTART', 'ENVEND', 'EXITCODE', #51# ] SCHED_POLICY = [ 'C', # 0: CFS # 'F', # 1: FIFO # 'R', # 2: RR # 'B', # 3: BATCH # 'N', # 4: NONE # 'I', # 5: IDLE # 'D', # 6: DEADLINE # ] # Define statm of process # STATM_TYPE = [ 'TOTAL', # 0 # 'RSS', # 1 # 'SHR', # 2 # 'TEXT', # 3 # 'DATA', # 4 # 'LIB', # 5 # 'DIRTY', # 6 # ] ERR_TYPE = [ 'EPERM', # Operation not permitted # 'ENOENT', # No such file or directory # 'ESRCH', # No such process # 'EINTR', # Interrupted system call # 'EIO', # I/O error # 'ENXIO', # No such device or address # 'E2BIG', # Argument list too long # 'ENOEXEC', # Exec format error # 'EBADF', # Bad file number # 'ECHILD', # No child processes # 'EAGAIN', # Try again # 'ENOMEM', # Out of memory # 'EACCES', # Permission denied # 'EFAULT', # Bad address # 'ENOTBLK', # Block device required # 'EBUSY', # Device or resource busy # 'EEXIST', # File exists # 'EXDEV', # Cross-device link # 'ENODEV', # No such device # 'ENOTDIR', # Not a directory # 'EISDIR', # Is a directory # 'EINVAL', # Invalid argument # 'ENFILE', # File table overflow # 'EMFILE', # Too many open files # 'ENOTTY', # Not a typewriter # 'ETXTBSY', # Text file busy # 'EFBIG', # File too large # 'ENOSPC', # No space left on device # 'ESPIPE', # Illegal seek # 'EROFS', # Read-only file system # 'EMLINK', # Too many links # 'EPIPE', # Broken pipe # 'EDOM', # Math argument out of domain of func # 'ERANGE', # Math result not representable # 'EDEADLK', # Resource deadlock would occur # 'ENAMETOOLONG', # File name too long # 'ENOLCK', # No record locks available # 'ENOSYS', # Function not implemented # 'ENOTEMPTY', # Directory not empty # 'ELOOP', # Too many symbolic links encountered # 'EWOULDBLOCK', # Operation would block # 'ENOMSG', # No message of desired type # 'EIDRM', # Identifier removed # 'ECHRNG', # Channel number out of range # 'EL2NSYNC', # Level 2 not synchronized # 'EL3HLT', # Level 3 halted # 'EL3RST', # Level 3 reset # 'ELNRNG', # Link number out of range # 'EUNATCH', # Protocol driver not attached # 'ENOCSI', # No CSI structure available # 'EL2HLT', # Level 2 halted # 'EBADE', # Invalid exchange # 'EBADR', # Invalid request descriptor # 'EXFULL', # Exchange full # 'ENOANO', # No anode # 'EBADRQC', # Invalid request code # 'EBADSLT ', # Invalid slot # 'EDEADLOCK', 'EBFONT', # Bad font file format # 'ENOSTR', # Device not a stream # 'ENODATA', # No data available # 'ETIME', # Timer expired # 'ENOSR', # Out of streams resources # 'ENONET', # Machine is not on the network # 'ENOPKG', # Package not installed # 'EREMOTE', # Object is remote # 'ENOLINK', # Link has been severed # 'EADV', # Advertise error # 'ESRMNT', # Srmount error # 'ECOMM', # Communication error on send # 'EPROTO', # Protocol error # 'EMULTIHOP', # Multihop attempted # 'EDOTDOT', # RFS specific error # 'EBADMSG', # Not a data message # 'EOVERFLOW', # Value too large for defined data type # 'ENOTUNIQ', # Name not unique on network # 'EBADFD', # File descriptor in bad state # 'EREMCHG', # Remote address changed # 'ELIBACC', # Can not access a needed shared library # 'ELIBBAD', # Accessing a corrupted shared library # 'ELIBSCN', # .lib section in a.out corrupted # 'ELIBMAX', # Attempting to link in too many shared libraries # 'ELIBEXEC', # Cannot exec a shared library directly # 'EILSEQ', # Illegal byte sequence # 'ERESTART', # Interrupted system call should be restarted # 'ESTRPIPE', # Streams pipe error # 'EUSERS', # Too many users # 'ENOTSOCK', # Socket operation on non-socket # 'EDESTADDRREQ', # Destination address required # 'EMSGSIZE', # Message too long # 'EPROTOTYPE', # Protocol wrong type for socket # 'EPROTOTYPE', # Protocol wrong type for socket # 'ENOPROTOOPT', # Protocol not available # 'EPROTONOSUPPORT', # Protocol not supported # 'ESOCKTNOSUPPORT', # Socket type not supported # 'EOPNOTSUPP', # Operation not supported on transport endpoint # 'EPFNOSUPPORT', # Protocol family not supported # 'EAFNOSUPPORT ', # Address family not supported by protocol # 'EADDRINUSE ', # Address already in use # 'EADDRNOTAVAIL', # Cannot assign requested address # 'ENETDOWN', # Network is down # 'ENETUNREACH', # Network is unreachable # 'ENETRESET', # Network dropped connection because of reset # 'ECONNABORTED', # Software caused connection abort # 'ECONNRESET', # Connection reset by peer # 'ENOBUFS', # No buffer space available # 'EISCONN', # Transport endpoint is already connected # 'ENOTCONN', # Transport endpoint is not connected # 'ESHUTDOWN', # Cannot send after transport endpoint shutdown # 'ETOOMANYREFS', # Too many references: cannot splice # 'ETIMEDOUT', # Connection timed out # 'ECONNREFUSED', # Connection refused # 'EHOSTDOWN', # Host is down # 'EHOSTUNREACH', # No route to host # 'EALREADY', # Operation already in progress # 'EINPROGRESS', # Operation now in progress # 'ESTALE', # Stale NFS file handle # 'EUCLEAN', # Structure needs cleaning # 'ENOTNAM', # Not a XENIX named type file # 'ENAVAIL', # No XENIX semaphores available # 'EISNAM', # Is a named type file # 'EREMOTEIO', # Remote I/O error # 'EDQUOT', # Quota exceeded # 'ENOMEDIUM', # No medium found # 'EMEDIUMTYPE', # Wrong medium type # 'ECANCELED', # Operation Canceled # 'ENOKEY', # Required key not available # 'EKEYEXPIRED', # Key has expired # 'EKEYREVOKED', # Key has been revoked # 'EKEYREJECTED', # Key was rejected by service # 'EOWNERDEAD', # Owner died # 'ENOTRECOVERABLE', # State not recoverable # 'ERFKILL', # Operation not possible due to RF-kill # 'EHWPOISON', # Memory page has hardware error # ] # Define rlimit of process # RLIMIT_TYPE = [ 'RLIMIT_CPU', 'RLIMIT_FSIZE', 'RLIMIT_DATA', 'RLIMIT_STACK', 'RLIMIT_CORE', 'RLIMIT_RSS', 'RLIMIT_NPROC', 'RLIMIT_NOFILE', 'RLIMIT_MEMLOCK', 'RLIMIT_AS', 'RLIMIT_LOCKS', 'RLIMIT_SIGPENDING', 'RLIMIT_MSGQUEUE', 'RLIMIT_NICE', 'RLIMIT_RTPRIO', 'RLIMIT_RTTIME', 'RLIMIT_NLIMITS' ] # Define udp/tcp format of system # UDP_ATTR = [ 'sl', 'local_address', 'rem_address', 'st', 'tx_rx_queue', 'tr_tm->when', 'retrnsmt', 'uid', 'timeout', 'inode', 'ref', 'pointer', 'drops' ] # Define uds format of system # UDS_ATTR = [ 'Num', 'RefCount', 'Protocol', 'Flags', 'Type', 'St', 'Inode', 'Path', ] TCP_STAT = [ 'N/A', 'ESTABLISHED', 'SYN_SENT', 'SYN_RECV', 'FIN_WAIT1', 'FIN_WAIT2', 'TIME_WAIT', 'CLOSE', 'CLOSE_WAIT', 'LAST_ACK', 'LISTEN', 'CLOSING' ] # Define futex operation flags # FUTEX_TYPE = [ 'FUTEX_WAIT', 'FUTEX_WAKE', 'FUTEX_FD', 'FUTEX_REQUEUE', 'FUTEX_CMP_REQUEUE', 'FUTEX_WAKE_OP', 'FUTEX_LOCK_PI', 'FUTEX_UNLOCK_PI', 'FUTEX_TRYLOCK_PI', 'FUTEX_WAIT_BITSET', 'FUTEX_WAKE_BITSET', 'FUTEX_WAIT_REQUEUE_PI', 'FUTEX_CMP_REQUEUE_PI', ] # Define fcntl command flags # FCNTL_TYPE = [ 'F_DUPFD', 'F_GETFD', 'F_SETFD', 'F_GETFL', 'F_SETFL', 'F_GETOWN', 'F_SETOWN', 'F_GETLK', 'F_SETLK', 'F_SETLKW', ] # Define ipc call flags # IPC_TYPE = { 1: "SEMOP", 2: "SEMGET", 3: "SEMCTL", 4: "SEMTIMEDOP", 11: "MSGSND", 12: "MSGRCV", 13: "MSGGET", 14: "MSGCTL", 21: "SHMAT", 22: "SHMDT", 23: "SHMGET", 24: "SHMCTL", } # Define ptrace request type # PTRACE_TYPE = [ 'PTRACE_TRACEME', #0# 'PTRACE_PEEKTEXT', 'PTRACE_PEEKDATA', 'PTRACE_PEEKUSR', 'PTRACE_POKETEXT', 'PTRACE_POKEDATA', 'PTRACE_POKEUSR', 'PTRACE_CONT', 'PTRACE_KILL', 'PTRACE_SINGLESTEP', #9# '', '', 'PTRACE_GETREGS', #12# 'PTRACE_SETREGS', #13# 'PTRACE_GETFPREGS', #14# 'PTRACE_SETFPREGS', #15# 'PTRACE_ATTACH', #16# 'PTRACE_DETACH', #17# 'PTRACE_GETFPXREGS', #18# 'PTRACE_SETFPXREGS', #19# '', '', '', 'PTRACE_SET_SYSCALL', #23# 'PTRACE_SYSCALL', #24# '', '', '', '', '', '', 'PTRACE_SYSEMU', #31# 'PTRACE_SYSEMU_SINGLESTEP', #32# ] # Define ptrace event type # PTRACE_EVENT_TYPE = [ 'PTRACE_EVENT_NONE', 'PTRACE_EVENT_FORK', 'PTRACE_EVENT_VFORK', 'PTRACE_EVENT_CLONE', 'PTRACE_EVENT_EXEC', 'PTRACE_EVENT_VFORK_DONE', 'PTRACE_EVENT_EXIT', 'PTRACE_EVENT_SECCOMP', ] + ['NONE' for idx in range(0, 120, 1)] + ['PTRACE_EVENT_STOP'] # Define perf event types # PERF_EVENT_TYPE = [ 'PERF_TYPE_HARDWARE', 'PERF_TYPE_SOFTWARE', 'PERF_TYPE_TRACEPOINT', 'PERF_TYPE_HW_CACHE', 'PERF_TYPE_RAW', 'PERF_TYPE_BREAKPOINT', ] PERF_HW_EVENT_TYPE = [ 'PERF_COUNT_HW_CPU_CYCLES', 'PERF_COUNT_HW_INSTRUCTIONS', 'PERF_COUNT_HW_CACHE_REFERENCES', 'PERF_COUNT_HW_CACHE_MISSES', 'PERF_COUNT_HW_BRANCH_INSTRUCTIONS', 'PERF_COUNT_HW_BRANCH_MISSES', 'PERF_COUNT_HW_BUS_CYCLES', 'PERF_COUNT_HW_STALLED_CYCLES_FRONTEND', 'PERF_COUNT_HW_STALLED_CYCLES_BACKEND', 'PERF_COUNT_HW_REF_CPU_CYCLES', ] PERF_SW_EVENT_TYPE = [ 'PERF_COUNT_SW_CPU_CLOCK', 'PERF_COUNT_SW_TASK_CLOCK', 'PERF_COUNT_SW_PAGE_FAULTS', 'PERF_COUNT_SW_CONTEXT_SWITCHES', 'PERF_COUNT_SW_CPU_MIGRATIONS', 'PERF_COUNT_SW_PAGE_FAULTS_MIN', 'PERF_COUNT_SW_PAGE_FAULTS_MAJ', 'PERF_COUNT_SW_ALIGNMENT_FAULTS', 'PERF_COUNT_SW_EMULATION_FAULTS', 'PERF_COUNT_SW_DUMMY', 'PERF_COUNT_SW_BPF_OUTPUT', ] PERF_CACHE_EVENT_TYPE = [ 'PERF_COUNT_HW_CACHE_L1D', 'PERF_COUNT_HW_CACHE_L1I', 'PERF_COUNT_HW_CACHE_LL', 'PERF_COUNT_HW_CACHE_DTLB', 'PERF_COUNT_HW_CACHE_ITLB', 'PERF_COUNT_HW_CACHE_BPU', 'PERF_COUNT_HW_CACHE_NODE', ] PERF_CACHE_EVENT_OP = [ 'PERF_COUNT_HW_CACHE_OP_READ', 'PERF_COUNT_HW_CACHE_OP_WRITE', 'PERF_COUNT_HW_CACHE_OP_PREFETCH', ] PERF_CACHE_EVENT_OPRES = [ 'PERF_COUNT_HW_CACHE_RESULT_ACCESS', 'PERF_COUNT_HW_CACHE_RESULT_MISS', ] @staticmethod def getMmapId(): if SysMgr.arch == 'arm': return ConfigMgr.sysList.index('sys_mmap2') else: return ConfigMgr.sysList.index('sys_mmap') @staticmethod def openConfFile(path): path += '.tc' if os.path.isfile(path): SysMgr.printWarn( "%s already exists so that make new one" % path) try: fd = open(path, 'w') except SystemExit: sys.exit(0) except: SysMgr.printOpenErr(path) return None return fd @staticmethod def writeConfData(fd, line): if not fd: SysMgr.printErr("fail to get file descriptor") return None fd.write(line) def __init__(self, mode): pass def __del__(self): pass class UtilMgr(object): """ Manager for utilities """ curTime = 0 progressCnt = 0 progressChar = { 0: '|', 1: '/', 2: '-', 3: '\\', } @staticmethod def setTime(): UtilMgr.curTime = time.time() @staticmethod def convHtmlChar(string): chars = { '<': '<', '>': '>', '&': '&', } for key, val in chars.items(): string = string.replace(key, val) return string @staticmethod def printTime(name=None, update=False): # get current time # now = time.time() diff = now - UtilMgr.curTime # update timestamp # if update: UtilMgr.current = now # add name # if name: prefix = '[%s]' % name else: prefix = '' # print time diff # string = '\n%s[Elapsed: %f]' % (prefix, diff) print(UtilMgr.convColor(string, 'RED')) @staticmethod def compareSyscallSuperset(): # initialize ignore list # ignoreList = set([ 'sys_ppoll_time64', 'sys_nfsservctl', 'sys_null', 'sys_setfsgid32', 'sys_ftime', 'sys_geteuid32', 'sys_clock_adjtime64', 'sys_timerfd_settime64', 'sys_epoll_ctl_old', 'sys_setfsuid32', 'sys_getresgid32', 'sys_iopl', 'sys_chown32', 'sys_rt_sigtimedwait_time64', 'sys_gtty', 'sys_setresgid32', 'sys_reserved', 'sys_unused', ]) syscallList = \ ConfigMgr.SYSCALL_COMMON + \ ConfigMgr.SYSCALL_COMMON32 + \ ConfigMgr.SYSCALL_X86 + \ ConfigMgr.SYSCALL_X64 + \ ConfigMgr.SYSCALL_ARM + \ ConfigMgr.SYSCALL_AARCH64 syscallList = set(syscallList) protoList = set(\ ['sys_%s' % name for name in ConfigMgr.SYSCALL_PROTOTYPES.keys()]) # print final diff list # print("--- no prototype ---") print(list(syscallList - protoList - ignoreList)) print("\n--- no define ---") print(list(protoList - syscallList)) @staticmethod def isBitEnabled(num, bits): if not bits: return None try: num = long(num) except: num = long(num, 16) try: bits = long(bits) except: bits = long(bits, 16) if bits & (1 << num-1): return True else: return False @staticmethod def cleanItem(targetList, union=True): targetType = type(targetList) if targetType is str: targetStr = '' for val in targetList: if val: targetStr = '%s%s' % (targetStr, val) return targetStr elif targetType is list: # remove redundant values # if union: targetList = list(set(targetList)) # remove empty values # newList = [] for val in targetList: val = val.strip() if val: newList.append(val) return newList else: return targetList @staticmethod def printHist(table, title, unit): if not table: return convNum = UtilMgr.convNum # pop stats # statmin = table.pop('min', None) statmax = table.pop('max', None) statcnt = table.pop('cnt', None) SysMgr.printPipe( '\n[%s Histogram] (unit:%s)\n%s' % (title, unit, twoLine)) SysMgr.printPipe('{0:^21} {1:^17}'.format('Range', 'Count')) SysMgr.printPipe(oneLine) for digit, cnt in sorted(table.items()): srange = long(pow(2, digit-1)) if srange == 0: erange = 1 else: erange = long((srange<<1)-1) SysMgr.printPipe( '{0:10}-{1:>10} {2:>10}({3:5.1f}%)'.format( convNum(srange), convNum(erange), convNum(cnt), cnt/float(statcnt)*100)) SysMgr.printPipe(oneLine) SysMgr.printPipe('{0:^21} {1:>17}'.format('Min', convNum(statmin))) SysMgr.printPipe('{0:^21} {1:>17}'.format('Max', convNum(statmax))) SysMgr.printPipe('{0:^21} {1:>17}'.format('Cnt', convNum(statcnt))) SysMgr.printPipe(oneLine) @staticmethod def convList2Histo(items, dtype='float', mult=1): def _getRangeIdx(value): if value <= 1: return 0 digit = 0 while 1: digit += 1 value = value >> 1 if value == 0: return digit if not items: return None # convert type # if dtype == 'float': if type(items[0]) != float: items = list(map(float, items)) elif dtype == 'long': if type(items[0]) != long: items = list(map(long, items)) else: return None # convert unit # items = list(map(lambda x: long(x * mult), items)) # get stats # histDict = { 'max': max(items), 'min': min(items), 'cnt': len(items) } for value in items: digit = _getRangeIdx(value) histDict.setdefault(digit, 0) histDict[digit] += 1 return histDict @staticmethod def getSigList(): sigList = dict( (k, v) for v, k in reversed(sorted(signal.__dict__.items())) if v.startswith('SIG') and not v.startswith('SIG_')) return sigList @staticmethod def convList2Dict(optList, sep=':'): newDict = {} for item in optList: try: # get values # values = item.split(sep, 1) if len(values) == 1: key = values[0] value = 'SET' else: key, value = values # set values # if key in newDict: newDict[key].append(value) else: newDict[key] = [value] except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to parse %s by seperator %s" % (item, sep)) continue return newDict @staticmethod def getStdev(data): def _variance(data, ddof=0): n = len(data) mean = sum(data) / n return sum((x - mean) ** 2 for x in data) / (n - ddof) var = _variance(data) math = SysMgr.getPkg('math') std_dev = math.sqrt(var) return std_dev @staticmethod def getRealTime(): return time.asctime(time.gmtime(time.time())) @staticmethod def splitString(string): string = string.replace('\,', '$%') clist = string.split(',') for idx, item in enumerate(list(clist)): clist[idx] = item.replace('$%', ',').strip() return clist @staticmethod def getDrawOutputPath(inputPath, name): # set output path # if SysMgr.outPath: outputPath = SysMgr.outPath # check dir # if os.path.isdir(outputPath): outputFileName = '%s.svg' % \ os.path.splitext(os.path.basename(inputPath))[0] outputPath = \ os.path.join(outputPath, outputFileName) else: outputPath = UtilMgr.prepareForImageFile( inputPath, 'flamegraph') return outputPath @staticmethod def printSyscalls(systable): bufstring = '' for idx, syscall in enumerate(systable): if idx % 4 == 0: bufstring += '\n' bufstring += "'%s', " % syscall print(bufstring) print('total: %s' % len(systable)) sys.exit(0) @staticmethod def isValidStr(string, key=None, inc=True, ignCap=False): if not key: key = SysMgr.filterGroup if not key: return True if ignCap: string = string.lower() for cond in list(key): if ignCap: cond = cond.lower() if inc: if cond in string: return True else: if cond == '*': return True elif cond.startswith('*') and \ cond.endswith('*') and \ cond.strip('*') in string: return True elif cond.startswith('*') and \ string.endswith(cond[1:]): return True elif cond.endswith('*') and \ string.startswith(cond[:-1]): return True elif cond == string: return True return False @staticmethod def drawGraph(inFile, outFile=None): instance = TaskAnalyzer(onlyInstance=True) instance.drawStats(inFile, outFile=outFile, onlyGraph=True) @staticmethod def drawChart(inFile, outFile=None): instance = TaskAnalyzer(onlyInstance=True) instance.drawStats(inFile, outFile=outFile, onlyChart=True) @staticmethod def convWord2Str(word): try: return struct.pack('L', word) except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to convert word %s to string" % word, True) return None @staticmethod def getFiles(path, incFile=True, incDir=False): flist = list() for r, d, f in os.walk(path): if incFile: for sfile in f: flist.append(os.path.join(r, sfile)) if incDir: for sdir in d: flist.append(os.path.join(r, sdir)) return flist @staticmethod def getFileList(flist, sort=False): if not flist or type(flist) is not list: return [] rlist = list() for item in flist: if item.startswith('-'): break # apply regular expression for path # ilist = UtilMgr.convPath(item) if UtilMgr.isString(ilist): rlist.append(ilist) elif type(ilist) is list: rlist += ilist # check redundant files # if len(rlist) != len(set(rlist)): SysMgr.printWarn( "detected redundant files in [ %s ]" % \ ', '.join(rlist), True) # remove redundant files # if sort: return sorted(rlist) else: return rlist @staticmethod def decodeArg(value): try: text = repr(value.decode()) except SystemExit: sys.exit(0) except: text = value # define start index by encoding type # if type(text) is bytes: start = 2 else: start = 1 return text[start:] @staticmethod def convBin2Str(path, pos=False): try: if sys.version_info < (3, 0): fd = open(path, 'rb') else: fd = open(path, encoding='latin-1') content = fd.read() strList = list(re.findall("[^\x00-\x1F\x7F-\xFF]{4,}", content)) # add position # if pos: lastPos = 0 dictList = {} for item in strList: dictList.setdefault(item, content.find(item, lastPos)) lastPos = dictList[item] return dictList return strList except SystemExit: sys.exit(0) except: SysMgr.printErr('fail to convert %s to strings' % path, True) return False @staticmethod def bisect_left(a, x, lo=0, hi=None): # copied from python standard library bisect.py # if lo < 0: raise ValueError('lo must be non-negative') if not hi: hi = len(a) while lo < hi: mid = (lo+hi)//2 if a[mid] <= x: lo = mid+1 else: hi = mid return lo @staticmethod def getFlagBit(vlist, flist): num = 0 for flag in flist: try: num |= vlist[flag] except: SysMgr.printErr( "fail to get %s in [%s]" % \ (flag, '|'.join(list(vlist.keys())))) sys.exit(0) return num @staticmethod def getFlagList(value, flist, num='hex'): rlist = [] numVal = long(value) for name, bits in list(flist.items()): if numVal & bits: rlist.append(name) return rlist @staticmethod def getFlagString(value, flist, num='hex'): string = '' numVal = long(value) for bit in list(flist.keys()): try: if numVal - bit < 0: break elif numVal & bit: string = '%s%s|' % (string, flist[bit]) except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to get flag info for %s" % value, reason=True) # check value for 0 index # if 0 in flist: if num == 'hex' and numVal & 0xF == 0: string = '%s|%s' % (flist[bit], string) elif num == 'oct' and numVal & 0o7 == 0: string = '%s|%s' % (flist[bit], string) elif num == 'bin' and numVal & 0 == 0: string = '%s|%s' % (flist[bit], string) if len(string) > 0: return string[:-1] else: return value @staticmethod def encodeBase64(value): base64 = SysMgr.getPkg('base64', False) try: return base64.b64encode(value) except SystemExit: sys.exit(0) except: return value @staticmethod def readLEB128(fd): data = None while 1: char = fd.read(1) if ord(char) & 0x80 == 0: break elif not data: data = char else: data += char return data @staticmethod def decodeSLEB128(obj): size = 1 value = 0 for b in obj: value = (value << 7) + (ord(b) & 0x7F) if (ord(b) & 0x80) == 0: break size += 1 obj = obj[:size] if ord(obj[-1]) & 0x40: # negative -> sign extend value |= - (1 << (7 * len(obj))) return value, size @staticmethod def decodeULEB128(obj): size = 1 value = 0 # get size # for b in obj: if (ord(b) & 0x80) == 0: break size += 1 # decode data # for b in reversed(obj[:size]): value = (value << 7) + (ord(b) & 0x7F) return value, size @staticmethod def isCompressed(fname=None, fd=None): if fname: try: fd = open(fname, 'rb') except SystemExit: sys.exit(0) except: SysMgr.printOpenErr(fname) sys.exit(0) if fd: data = fd.read(2) fd.seek(0, 0) if struct.unpack('BB', data) == (0x1f, 0x8b): return True else: return False else: return False @staticmethod def conv2BitStr(content): return bin(content) @staticmethod def decodeBase64(value): base64 = SysMgr.getPkg('base64', False) try: return base64.b64decode(value) except SystemExit: sys.exit(0) except: return value @staticmethod def encodeStr(value): try: return value.encode() except SystemExit: sys.exit(0) except: try: return value.encode('utf8', 'surrogateescape') except SystemExit: sys.exit(0) except: return value @staticmethod def isString(value): if isinstance(value, str): return True elif sys.version_info >= (3, 0, 0): if isinstance(value, bytes): return True else: if isinstance(value, unicode): # pylint: disable=undefined-variable return True return False @staticmethod def isFloat(value): if type(value) is float: return True elif type(value) is str: try: float(value) return True except SystemExit: sys.exit(0) except: return False else: return False @staticmethod def isNumber(value): if type(value) is int or \ type(value) is long: return True elif type(value) is str: if value.isdigit(): return True try: if value.startswith('0x') and long(value, 16): return True else: return False except SystemExit: sys.exit(0) except: return False else: return False @staticmethod def getTextLines(fname, verbose=False, retfd=False): buf = [] if verbose: if retfd: SysMgr.printStat( r"start checking '%s'..." % fname) else: SysMgr.printStat( r"start loading '%s'..." % fname) # check gzip # try: fd = None with open(fname, 'rb') as fd: data = fd.read(2) if struct.unpack('BB', data) != (0x1f, 0x8b): raise Exception() compressor = SysMgr.getPkg('gzip', False) fd = compressor.open(fname, 'rt') except SystemExit: sys.exit(0) except: fd = None # open a file # try: if not fd: fd = open(fname, 'r', encoding='utf-8') except SystemExit: sys.exit(0) except: fd = open(fname, 'r') # just return fd # if retfd: return fd # get total size # try: totalSize = os.stat(fname).st_size except SystemExit: sys.exit(0) except: totalSize = long(0) # read data from a file # while 1: try: data = fd.readline() curSize = fd.tell() if not data: break buf.append(data) except SystemExit: sys.exit(0) except: break if verbose: UtilMgr.printProgress(curSize, totalSize) if verbose: UtilMgr.deleteProgress() try: fd.close() except: pass return buf @staticmethod def convPath(value, retStr=False, isExit=False, separator=' '): value = value.strip() glob = SysMgr.getPkg('glob', False) if glob: # check recursive path for specific version(>=python 3.5) # if '**' in value and sys.version_info >= (3, 5): res = glob.glob(value, recursive=True) else: res = glob.glob(value) if not res and isExit: SysMgr.printErr( "fail to find a file matching '%s'" % value) sys.exit(0) # str # if retStr: return separator.join(res) # list # else: return res else: # str # if retStr: return value # list # else: return [value] @staticmethod def convStr2Word(bstring): try: return struct.unpack('L', bstring)[0] except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to convert string %s to word" % bstring) return None @staticmethod def convOverlayPath(path, overlayfsList): fileList = [] itemList = ['lowerdir', 'upperdir'] for pos, info in overlayfsList.items(): if not pos in path: continue for target in itemList: for item in info[target]: fullpath = item + path if os.path.exists(fullpath): fileList.append(fullpath) # return recent path # if fileList: return fileList[-1] else: return path @staticmethod def convStr2Num(string, verb=True): try: if type(string) is long: return string elif string.isdigit(): string = long(string) else: string = long(string, 16) except SystemExit: sys.exit(0) except: if verb: SysMgr.printErr( "fail to convert %s to number" % string, True) return None return string @staticmethod def convNum(number): try: return format(long(number), ",") except SystemExit: sys.exit(0) except: return number @staticmethod def getRealLen(string): ansi = r'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]' ansiObj = re.compile(ansi) return len(ansiObj.sub('', string)) @staticmethod def convColor(string, color='LIGHT', size=1, align='right'): if not SysMgr.colorEnable or not color or \ SysMgr.outPath or SysMgr.outputFile or \ not SysMgr.isLinux or SysMgr.remoteRun: return string if align == 'right': string = '{0:>{size}}'.format(str(string), size=size) else: string = '{0:<{size}}'.format(str(string), size=size) try: return (ConfigMgr.COLOR_LIST[color] + string + ConfigMgr.ENDC) except SystemExit: sys.exit(0) except: SysMgr.printWarn( 'fail to convert color for %s' % color, reason=True) @staticmethod def convSize2Unit(size, isInt=False): sizeKB = long(1024) sizeMB = sizeKB << 10 sizeGB = sizeMB << 10 sizeTB = sizeGB << 10 # convert to ABS value # try: sizeAbs = abs(size) except SystemExit: sys.exit(0) except: return '?' # Int type # if isInt: try: if sizeAbs >= sizeTB: return '%dT' % (size >> 40) elif sizeAbs >= sizeGB: return '%dG' % (size >> 30) elif sizeAbs >= sizeMB: return '%dM' % (size >> 20) elif sizeAbs >= sizeKB: return '%dK' % (size >> 10) else: return '%d' % size except SystemExit: sys.exit(0) except: return '?' # Float type # else: try: if sizeAbs >= sizeTB: return '%.1fT' % ((size >> 30) / 1024.0) elif sizeAbs >= sizeGB: return '%.1fG' % ((size >> 20) / 1024.0) elif sizeAbs >= sizeMB: return '%.1fM' % ((size >> 10) / 1024.0) elif sizeAbs >= sizeKB: return '%.1fK' % (size / 1024.0) else: return '%d' % (size) except SystemExit: sys.exit(0) except: return '?' @staticmethod def convTime(time): # convert seconds to time # try: m, s = divmod(time, 60) h, m = divmod(m, 60) # hour # if h >= 24: d, h = divmod(h, 24) # year # if d >= 365: y, d = divmod(d, 365) d = '%dy:%dd:' % (y, d) else: d = '%dd:' % d else: d = '' ctime = "%s%02d:%02d:%02d" % (d, h, m, s) except SystemExit: sys.exit(0) except: ctime = "%s%02s:%02s:%02s" % ('', '?', '?', '?') return ctime.strip() @staticmethod def prepareForImageFile(logFile, itype='', outFile=None): # build output file name # if outFile: outputFile = outFile else: if SysMgr.outPath: outputFile = os.path.normpath(SysMgr.outPath) else: outputFile = os.path.normpath(logFile) # convert output path # if os.path.isdir(outputFile): filename = os.path.basename(logFile) filename = os.path.splitext(filename)[0] name = '%s/%s' % (outputFile, filename) else: name = os.path.splitext(outputFile)[0] outputFile = '%s_%s.%s' % (name, itype, SysMgr.drawFormat) try: # backup an exist image file # if os.path.isfile(outputFile): name, ext = os.path.splitext(outputFile) oldPath = '%s_old%s' % (name, ext) if os.path.isfile(oldPath): os.remove(oldPath) os.rename(outputFile, oldPath) SysMgr.printInfo( "renamed '%s' to '%s' for backup" % \ (outputFile, oldPath)) except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to backup '%s' to '%s'" % \ (outputFile, oldPath), True) return outputFile @staticmethod def convUnit2Time(data): if str(data).isdigit(): ret = long(data) elif data.upper().endswith('S'): ret = long(data[:-1]) elif data.upper().endswith('M'): ret = long(data[:-1]) * 60 elif data.upper().endswith('H'): ret = long(data[:-1]) * 60 * 60 elif data.upper().endswith('D'): ret = long(data[:-1]) * 60 * 60 * 24 elif data.upper().endswith('W'): ret = long(data[:-1]) * 60 * 60 * 24 * 7 else: ret = 0 SysMgr.printErr( "fail to convert '%s' to seconds" % data) return ret @staticmethod def convUnit2Size(value): sizeKB = long(1024) sizeMB = sizeKB << 10 sizeGB = sizeMB << 10 sizeTB = sizeGB << 10 sizePB = sizeTB << 10 if str(value).isdigit(): return long(value) # convert unit character to capital # value = value.upper() try: if value.endswith('K'): return long(float(value[:-1]) * sizeKB) if value.endswith('KB'): return long(float(value[:-2]) * sizeKB) if value.endswith('M'): return long(float(value[:-1]) * sizeMB) if value.endswith('MB'): return long(float(value[:-2]) * sizeMB) if value.endswith('G'): return long(float(value[:-1]) * sizeGB) if value.endswith('GB'): return long(float(value[:-2]) * sizeGB) if value.endswith('T'): return long(float(value[:-1]) * sizeTB) if value.endswith('TB'): return long(float(value[:-2]) * sizeTB) if value.endswith('P'): return long(float(value[:-1]) * sizePB) if value.endswith('PB'): return long(float(value[:-2]) * sizePB) SysMgr.printErr( "fail to convert %s to size" % value) assert False except SystemExit: sys.exit(0) except AssertionError: raise Exception('wrong number unit') except: return value @staticmethod def writeJsonObject(jsonObj, fd=None, trunc=False, path=None): if fd: try: if trunc: fd.seek(0, 0) fd.truncate() fd.write(jsonObj) fd.flush() except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to write JSON format data", reason=True) return # check write option # if trunc: perm = 'w' else: perm = 'a' # open the file # try: with open(path, perm) as fd: fd.write(jsonObj) except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to write JSON format data to %s" % path, True) sys.exit(0) @staticmethod def saveObjectToFile(obj, path): if not obj: return False pickle = SysMgr.getPicklePkg(False) if not pickle: return False # disable compression for performance # SysMgr.compressEnable = False # compress by gzip # if SysMgr.compressEnable: compressor = SysMgr.getPkg('gzip', False) else: compressor = None # original object # try: if compressor: with compressor.open(path, 'wb') as fd: pickle.dump(obj, fd, -1) else: with open(path, 'wb') as fd: pickle.dump(obj, fd, -1) return True except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to save %s object to %s" % \ (obj.__class__.__name__, path), reason=True) return False @staticmethod def loadObjectFromFile(path): # check object exists # if not os.path.isfile(path): return None pickle = SysMgr.getPicklePkg(False) if not pickle: return None # disable compression for performance # SysMgr.compressEnable = False # decompress by gzip # if SysMgr.compressEnable: decompressor = SysMgr.getPkg('gzip') else: decompressor = None try: if decompressor: with decompressor.open(path, 'rb') as fd: return pickle.load(fd) else: with open(path, 'rb') as fd: return pickle.load(fd) except SystemExit: sys.exit(0) except: return None @staticmethod def printProgress(current=0, dest=0): if not SysMgr.printEnable or \ dest == sys.maxsize: return # just output # if not current and not dest: if UtilMgr.progressCnt >= len(UtilMgr.progressChar)-1: UtilMgr.progressCnt = 0 else: UtilMgr.progressCnt += 1 mod = UtilMgr.progressCnt sys.stdout.write('.... %s%s' % \ (UtilMgr.progressChar[mod], '\b' * 6)) else: try: div = round((current / float(dest)) * 100, 1) except SystemExit: sys.exit(0) except: div = long(0) percent = long(div) mod = percent & 3 sys.stdout.write('%3d%% %s%s' % \ (percent, UtilMgr.progressChar[mod], '\b' * 6)) # handle reentrant call exception # try: sys.stdout.flush() except SystemExit: sys.exit(0) except: return @staticmethod def writeFlamegraph(path, samples, title): # flamegraph from https://github.com/rbspy/rbspy/tree/master/src/ui/flamegraph.rs # flameCode = ''' ''' attrCode = ''' Guider Flamegraph %s Reset Zoom Search ''' % ('\r\n%s' % title if title else '') # complete code for flamegraph # finalCode = flameCode + attrCode + samples + '\n' # write flamegraph to file # try: with open(path, 'w') as fd: fd.write(finalCode) # get output size # fsize = UtilMgr.getFileSize(path) if fsize and fsize != '0': fsize = ' [%s]' % fsize else: fsize = '' SysMgr.printInfo( "saved flamegraph into '%s'%s successfully" % (path, fsize)) except SystemExit: sys.exit(0) except: SysMgr.printErr( 'fail to write flamegraph to %s' % path, True) sys.exit(0) @staticmethod def getFileSize(path, string=True): try: fsize = long(os.path.getsize(path)) if string: return UtilMgr.convSize2Unit(fsize) else: return fsize except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to get file size for '%s'" % path) if string: return '?' else: return 0 @staticmethod def printFile(path): try: with open(path, 'r') as fd: for line in fd: print(line) except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to print %s" % path, reason=True) @staticmethod def deleteProgress(): if not SysMgr.printEnable: return sys.stdout.write(' ' * 6) # handle reentrant call exception # try: sys.stdout.flush() except SystemExit: sys.exit(0) except: return @staticmethod def which(file): pathList = [] for path in os.environ["PATH"].split(os.pathsep): if os.path.exists(os.path.join(path, file)): pathList.append(os.path.join(path, file)) if not pathList: return None else: return pathList @staticmethod def convDict2Str(dictObj, pretty=True, indent=2, ignore=False): try: if ignore: jsonStr = SysMgr.getPkg('json').\ dumps(dictObj, indent=indent, ensure_ascii=False, default=lambda o: '') else: jsonStr = SysMgr.getPkg('json').\ dumps(dictObj, indent=indent, ensure_ascii=False) if pretty: return jsonStr except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to convert %s to string" % [dictObj], reason=True) return None # when encode flag is disabled, remove whitespace [\t\n\r\f\v] # if not SysMgr.encodeEnable: jsonStr = re.sub("\s", "", jsonStr) + "\n" return jsonStr @staticmethod def convUlong2Long(retval): retval = (retval & 0xffffffffffffffff) if retval & 0x8000000000000000: retval = retval - 0x10000000000000000 return retval @staticmethod def convStr2Dict(strObj, verb=False): try: return SysMgr.getPkg('json').loads(strObj) except SystemExit: sys.exit(0) except: try: strObj = strObj.replace("'", '"') return SysMgr.getPkg('json').loads(strObj) except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to convert %s to dict" % [strObj], always=verb, reason=True) return None class NetworkMgr(object): """ Manager for remote communication """ def __init__( self, mode, ip, port, blocking=True, tcp=False, anyPort=False, bind=True, netlink=False, reuse=True): self.mode = mode self.ip = None self.port = None self.socket = None self.request = None self.status = None self.ignore = long(0) self.fileno = -1 self.time = None self.sendSize = 32767 self.recvSize = 32767 self.tcp = tcp self.netlink = netlink self.connected = False # get socket object # socket = SysMgr.getPkg('socket') try: from socket import socket, AF_INET, SOCK_DGRAM,\ SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR, SO_SNDBUF, SO_RCVBUF,\ SOL_TCP, SO_RCVTIMEO, SO_SNDTIMEO, SOCK_RAW except: SysMgr.printWarn( "fail to import socket", True, reason=True) return None try: # set socket type # if tcp: self.socket = socket(AF_INET, SOCK_STREAM) elif netlink: try: from socket import socket, AF_NETLINK self.socket = socket( AF_NETLINK, SOCK_RAW, ConfigMgr.NETLINK_TYPE['NETLINK_GENERIC']) except: SysMgr.printWarn( "fail to create NETLINK socket", True, reason=True) return None else: self.socket = socket(AF_INET, SOCK_DGRAM) self.fileno = self.socket.fileno() # increate socket buffer size to 1MB # self.socket.setsockopt(SOL_SOCKET, SO_SNDBUF, 1<<20) self.socket.setsockopt(SOL_SOCKET, SO_RCVBUF, 1<<20) # get buffer size # self.sendSize = self.socket.getsockopt(SOL_SOCKET, SO_SNDBUF) self.recvSize = self.socket.getsockopt(SOL_SOCKET, SO_RCVBUF) # set REUSEADDR # if reuse: self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # set REUSEPORT # ''' from socket import SO_REUSEPORT self.socket.setsockopt(SOL_SOCKET, SO_REUSEPORT, 0) ''' # set NODELAY # ''' self.setNoDelay() ''' # set SENDTIMEOUT # ''' sec = 1 usec = long(0) timeval = struct.pack('ll', sec, usec) self.socket.setsockopt(SOL_SOCKET, SO_SNDTIMEO, timeval) ''' # set IP & PORT # self.ip = ip self.port = port if mode == 'server': # IP # if ip is None: self.ip = '0.0.0.0' # PORT # if anyPort: self.port = long(0) elif not port: self.port = SysMgr.defaultPort # bind # if bind: try: self.socket.bind((self.ip, self.port)) except OSError as e: if e.errno == errno.EADDRINUSE: self.port = long(0) self.socket.bind((self.ip, self.port)) else: raise e except SystemExit: sys.exit(0) except: self.socket.bind((self.ip, self.port)) # get bind port # self.port = self.socket.getsockname()[1] if not blocking: self.socket.setblocking(0) except: err = SysMgr.getErrMsg() if err.startswith('13') and \ not SysMgr.isRoot() and \ port < 1024: feedback = ', use port bigger than 1024' else: feedback = '' # check mode to print error message # if SysMgr.warnEnable or \ SysMgr.checkMode('server') or \ SysMgr.checkMode('cli'): SysMgr.printErr( "fail to create a socket for %s:%s as server because %s%s" % \ (self.ip, self.port, err, feedback)) ''' if error "99 Cannot assign requested address" occurs: add "net.ipv4.ip_nonlocal_bind = 1" in /etc/sysctl.conf execute sysctl -p /etc/sysctl.conf ''' self.ip = None self.port = None return None def listen(self, nrQueue=5): return self.socket.listen(nrQueue) def accept(self): return self.socket.accept() def bind(self, ip, port): return self.socket.bind((ip, port)) def write(self, message): return self.send(message, write=True) def close(self): if self.socket: ret = self.socket.close() else: ret = False self.socket = None return ret def flush(self): pass def timeout(self, time=3): if 'TIMEOUT' in SysMgr.environList: try: time = float(SysMgr.environList['TIMEOUT'][0]) except: SysMgr.printErr( 'fail to get TIMEOUT variable', True) sys.exit(0) self.socket.settimeout(time) def connect(self, addr=None): if addr is None: addr = (self.ip, self.port) ret = self.socket.connect(addr) self.connected = True return ret def handleServerRequest(self, req, onlySocket=False): def _onDownload(req): # parse path # plist = req.split('|', 1)[1] path = UtilMgr.cleanItem(plist.split('@'), False) if len(path) == 2: origPath, targetPath = path if origPath and not targetPath: origPath = targetPath else: origPath = targetPath = path[0] receiver = self targetIp = self.ip targetPort = self.port addr = '%s:%s' % (targetIp, targetPort) # get select object # selectObj = SysMgr.getPkg('select') # receive file # try: curSize = long(0) totalSize = None dirPos = targetPath.rfind('/') if dirPos >= 0 and not os.path.isdir(targetPath[:dirPos]): os.makedirs(targetPath[:dirPos]) # receive file size # while 1: size = receiver.recv(receiver.recvSize) if not size: continue else: totalSize = long(size.decode()) receiver.send('ACK'.encode()) break # receive file # with open(targetPath, 'wb') as fd: while 1: selectObj.select([receiver.socket], [], [], 3) buf = receiver.recv(receiver.recvSize) if buf: curSize += len(buf) fd.write(buf) else: break # print progress # UtilMgr.printProgress(curSize, totalSize) UtilMgr.deleteProgress() SysMgr.printInfo( "downloaded %s [%s] from %s:%s:%s successfully\n" % \ (targetPath, UtilMgr.getFileSize(targetPath), targetIp, targetPort, origPath)) res = True except: SysMgr.printErr( 'fail to download %s from %s in %s' % \ (origPath, targetPath, addr), True) res = False finally: receiver.close() return res def _onUpload(req): # parse path # plist = req.split('|', 1)[1] path = UtilMgr.cleanItem(plist.split('@'), False) if len(path) == 2: origPath, targetPath = path if origPath and not targetPath: origPath = targetPath else: origPath = targetPath = path[0] sender = self targetIp = self.ip targetPort = self.port addr = '%s:%s' % (targetIp, targetPort) # check file # if not os.path.isfile(origPath): SysMgr.printErr( 'failed to find %s to transfer' % origPath) return try: # receive file size # stat = os.stat(origPath) st_size = '%s' % stat.st_size sender.send(st_size) # read for ACK # while 1: ret = sender.recv(3) if ret is None: continue elif ret is False: sys.exit(0) else: break # transfer file # curSize = long(0) totalSize = long(st_size) with open(origPath, 'rb') as fd: buf = fd.read(sender.sendSize) while buf: # print progress # UtilMgr.printProgress(curSize, totalSize) assert sender.send(buf) curSize = len(buf) buf = fd.read(sender.sendSize) UtilMgr.deleteProgress() SysMgr.printInfo( "uploaded %s [%s] to %s:%s successfully\n" % \ (origPath, UtilMgr.getFileSize(origPath), addr, targetPath)) res = True except: SysMgr.printErr( "fail to upload %s to %s in %s" % \ (origPath, targetPath, addr), True) res = False finally: sender.close() return res def _onList(req): SysMgr.printInfo(req.lstrip('LIST:')) return True def _onRun(req, onlySocket): # parse command # command = req.split('|', 1)[1] # parse addr # addr = '%s:%s' % (self.ip, self.port) if not onlySocket: SysMgr.printInfo( "executed '%s' from %s\n" % (command, addr)) # return just the connected socket # if onlySocket: return self # get select object # selectObj = SysMgr.getPkg('select') # set print flag # printFlag = SysMgr.getPrintFlag() if printFlag: print(oneLine) # run mainloop # isPrint = False while 1: try: [readSock, writeSock, errorSock] = \ selectObj.select([self.socket], [], []) # receive packet # output = self.getData() if not output: break if printFlag: print(output[:-1]) isPrint = True except: break # print output from server # if not isPrint: print('no response') if printFlag: print(oneLine) # close connection # try: self.close() except: pass # get select object to check reply # SysMgr.getPkg('select') # unmarshalling # if type(req) is tuple: try: req = req[0].decode() except: req = req[0] # check request # if not req: return # handle request # reqUpper = req.upper() if reqUpper.startswith('DOWNLOAD'): return _onDownload(req) elif reqUpper.startswith('UPLOAD'): return _onUpload(req) elif reqUpper.startswith('RUN'): return _onRun(req, onlySocket) elif reqUpper.startswith('LIST:'): return _onList(req) elif reqUpper.startswith('ERROR'): err = req.split('|', 1)[1] errToken = err.find("':") errMsg = "%s' from %s" % (err[:errToken], err[errToken+2:]) SysMgr.printErr(errMsg) else: SysMgr.printErr( "fail to recognize '%s' request" % req) elif not req: SysMgr.printErr( "no response from server") else: SysMgr.printErr( "received wrong reply '%s'" % req) def send(self, message, write=False): if self.ip is None or self.port is None: SysMgr.printWarn( "fail to use IP address for client because it is not set") return False elif not self.socket: SysMgr.printErr( "fail to use socket for client because it is not set") return False # encode message # if UtilMgr.isString(message): message = UtilMgr.encodeStr(message) try: # check protocol # if self.tcp or self.netlink: ret = self.socket.send(message) elif not write and SysMgr.localServObj: ret = SysMgr.localServObj.socket.sendto( message, (self.ip, self.port)) else: ret = self.socket.sendto(message, (self.ip, self.port)) if ret < 0: raise Exception('send error') if self.status != 'ALWAYS': self.status = 'SENT' return True except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to send data to %s:%d as server" % \ (self.ip, self.port), True) return False def sendto(self, message, ip, port): if not ip or not port: SysMgr.printWarn( "fail to use IP address for client because it is not set") return False elif not self.socket: SysMgr.printErr( "fail to use socket for client because it is not set") return False # encode message # if UtilMgr.isString(message): message = UtilMgr.encodeStr(message) try: self.socket.sendto(message, (ip, port)) return True except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to send data to %s:%d as client" % \ (self.ip, self.port), True) return False def recv(self, size=0): if self.ip is None or self.port is None: SysMgr.printWarn( "fail to use IP address for server because it is not set") return False elif not self.socket: SysMgr.printErr( "fail to use socket for client because it is not set") return False # set recv size # if size == 0: size = self.recvSize try: return self.socket.recv(size) except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to receive data from %s:%d as client" % \ (self.ip, self.port), reason=True) return False def getData(self, noTimeout=True): try: data = b'' # receive and composite packets # while 1: output = self.recvfrom(noTimeout=noTimeout) # handle error # if not output: continue # handle timeout # if not noTimeout and \ (not output[0] and not output[1]): if data: return data else: return None # get only data # output = output[0] # composite packets # data = data + output if not output: break # decode data # try: output = output.decode() except: pass if len(output) < self.recvSize and \ output[-1] == '\n': break except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to get data from %s:%d as client" % \ (self.ip, self.port), True) return None # decode data # try: retstr = data.decode() return retstr except: return data def setNoDelay(self): from socket import socket, SOL_TCP, TCP_NODELAY # set NODELAY for NAGLE # self.socket.setsockopt(SOL_TCP, TCP_NODELAY, 1) def recvfrom(self, size=0, noTimeout=False, verbose=True): if self.ip is None or self.port is None: SysMgr.printWarn( "fail to use IP address for server because it is not set") return False elif not self.socket: SysMgr.printErr( "fail to use socket for client because it is not set") return False # get socket object # socket = SysMgr.getPkg('socket', False) if not socket: return # set recv size # if size == 0: size = self.recvSize while 1: try: message, address = self.socket.recvfrom(size) return (message, address) except socket.timeout: if noTimeout: continue SysMgr.printWarn( "fail to receive data from %s:%d as client because of %s" % \ (self.ip, self.port, 'timeout')) return None except KeyboardInterrupt: sys.exit(0) except SystemExit: sys.exit(0) except: if verbose: SysMgr.printWarn( "fail to receive data from %s:%d as client" % \ (self.ip, self.port), reason=True) return None @staticmethod def getDataType(data): if not data: return 'None' data = data.lstrip() if data.startswith('{'): return 'JSON' elif '[INFO' in data[:10] or \ '[ERROR' in data[:10] or \ '[WARN' in data[:10] or \ '[STEP' in data[:10]: return 'LOG' else: return 'CONSOLE' @staticmethod def requestCmd(connObj, cmd): if not connObj: return # send request to server # connObj.send(cmd) # receive reply from server # reply = connObj.recvfrom() # handle reply from server # try: connObj.handleServerRequest(reply) except: return @staticmethod def requestPing(addr=None, verb=True): return NetworkMgr.execRemoteCmd("PING:PING", addr=addr, verb=verb) @staticmethod def getCmdPipe(connObj, cmd): if not cmd: return None # define valid request list # requestList = { 'DOWNLOAD': None, 'UPLOAD': None, 'RUN': None, 'BROADCAST': None, 'NEW': None, 'PING': None, 'LIST': None, } # add command prefix # reqList = cmd.upper().split(':') if reqList[0] in requestList: pass elif not cmd.startswith('run:'): cmd = 'run:%s' % cmd # send request to server # connObj.send(cmd) # receive reply from server # reply = connObj.recvfrom() try: if not reply: raise Exception() msg = reply[0].decode() if not msg: pass elif msg == 'PONG': return True elif msg == 'NO_SERV_NODE': SysMgr.printErr( 'no service node to %s:%s' % (connObj.ip, connObj.port)) return True elif msg.startswith('MSG:'): # print message in the packet # SysMgr.printInfo(msg.strip('MSG:')) # send ACK to prevent receiving two packegs at once # connObj.send('ACK') # wait for a request again # reply = connObj.recvfrom() elif msg.startswith('LIST:'): reply = (msg,) except: pass # handle reply from server # try: return connObj.handleServerRequest(reply, onlySocket=True) except: return None @staticmethod def execRemoteCmd(command, addr=None, verb=True): # get new connection # connObj = NetworkMgr.getServerConn(addr, verb) if not connObj: return None # launch remote command # pipe = NetworkMgr.getCmdPipe(connObj, command) return pipe @staticmethod def getServerConn(addr=None, verb=True): def _printErr(): SysMgr.printErr( "no running server or wrong server address") # set server address in local # if addr: # classify IP and PORT # service, ip, port = NetworkMgr.parseAddr(addr) if service == ip == port == None: _printErr() return None else: NetworkMgr.setRemoteServer('%s:%s' % (ip, port), tcp=True) elif SysMgr.isLinux and not SysMgr.remoteServObj: try: addr = SysMgr.getProcNetAddrs(__module__) except: addr = None if not addr: return None # classify IP and PORT # service, ip, port = NetworkMgr.parseAddr(addr) if service == ip == port == None: _printErr() return None else: NetworkMgr.setRemoteServer(addr, tcp=True) # set server address again # elif SysMgr.remoteServObj: servObj = SysMgr.remoteServObj ip = servObj.ip port = servObj.port NetworkMgr.setRemoteServer('%s:%s' % (ip, port), tcp=True) # check server address # if not SysMgr.remoteServObj: _printErr() return None # bind local socket for UDP # try: if not SysMgr.remoteServObj.tcp and SysMgr.localServObj: lip = SysMgr.localServObj.ip lport = SysMgr.localServObj.port SysMgr.remoteServObj.socket.bind((lip, lport)) except: SysMgr.printErr( "fail to bind socket to %s:%s for connection" % \ (lip, lport), True) # do connect to server # try: connObj = SysMgr.remoteServObj if not 'NOTIMEOUT' in SysMgr.environList: connObj.timeout() # connect with handling CLOSE_WAIT # while 1: try: connObj.connect() break except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to connect to %s:%s" % (ip, port), reason=True, always=verb) et, err, to = sys.exc_info() if err.args and err.args[0] == 99: time.sleep(0.1) continue else: raise Exception(err.args[0]) return connObj except SystemExit: sys.exit(0) except: if verb: SysMgr.printErr( "fail to set socket for connection", True) return None @staticmethod def parseAddr(value): service = None ip = None port = None if not UtilMgr.isString(value): return (service, ip, port) # get request and address # cmdList = value.split('@') if len(cmdList) >= 2: service = cmdList[0] addr = cmdList[1] else: addr = value # get IP and PORT # addrList = addr.split(':') if len(addrList) >= 2: try: if len(addrList[0]) > 0: ip = addrList[0] if len(addrList[1]) > 0: port = long(addrList[1]) except: pass else: try: if '.' in addrList[0]: ip = addrList[0] else: port = long(addrList[0]) except: pass return (service, ip, port) @staticmethod def setRemoteServer(value, tcp=False): # receive mode # if not value: SysMgr.remoteServObj = 'NONE' return # request mode # service, ip, port = NetworkMgr.parseAddr(value) # set PRINT as default # if not service: service = 'PRINT' if not ip: ip = NetworkMgr.getPublicIp() if not port: port = SysMgr.defaultPort # check server addresses # if SysMgr.localServObj and \ SysMgr.localServObj.ip == ip and \ SysMgr.localServObj.port == port: SysMgr.printErr(( "wrong value for remote connection, " "local address and remote address are same " "with %s:%s") % (ip, port)) sys.exit(0) if not ip or not port or \ not SysMgr.isValidRequest(service): reqList = '' for req in TaskAnalyzer.requestType: reqList += req + '|' SysMgr.printErr( ("wrong input address, " "input [%s]@IP:PORT as remote address") % \ reqList[:-1]) sys.exit(0) # create a socket # networkObject = NetworkMgr('client', ip, port, tcp=tcp) if not networkObject.ip: sys.exit(0) else: networkObject.request = service SysMgr.remoteServObj = networkObject # set protocol # if tcp: proto = 'TCP' else: proto = 'UDP' SysMgr.printInfo( "use %s:%d(%s) as remote address" % (ip, port, proto)) return SysMgr.remoteServObj @staticmethod def setRemoteNetwork(service, ip, port): # set default service # if not service: service = 'PRINT' errMsg = ("wrong value for remote server, " "input in the format [%s]@IP:PORT") % \ '|'.join(TaskAnalyzer.requestType) if not ip or not SysMgr.isValidRequest(service): SysMgr.printErr(errMsg) sys.exit(0) if not port: port = SysMgr.defaultPort networkObject = NetworkMgr('client', ip, port) if not networkObject.ip: sys.exit(0) else: networkObject.status = 'ALWAYS' networkObject.request = service naddr = '%s:%s' % (ip, str(port)) if service == 'PRINT': SysMgr.addrListForPrint[naddr] = networkObject elif service.startswith('REPORT_'): SysMgr.reportEnable = True SysMgr.addrListForReport[naddr] = networkObject else: SysMgr.printErr(errMsg) SysMgr.printInfo( "use %s:%d as remote address to request %s" % \ (ip, port, service)) @staticmethod def setServerNetwork( ip, port, force=False, blocking=False, tcp=False, anyPort=False, reuse=True): if SysMgr.localServObj and not force: SysMgr.printWarn( "ignored to set server network because it is already set") return # get internet available IP first # if not ip: ip = NetworkMgr.getPublicIp() # print available IP list # try: iplist = sorted(NetworkMgr.getUsingIps()) if iplist: SysMgr.printWarn( 'available IP list [ %s ]' % ', '.join(iplist)) except: pass # check server setting # if SysMgr.localServObj and \ SysMgr.localServObj.socket and \ SysMgr.localServObj.ip == ip and \ SysMgr.localServObj.port == port: if blocking: SysMgr.localServObj.socket.setblocking(1) else: SysMgr.localServObj.socket.setblocking(0) return # create a new server setting # networkObject = NetworkMgr( 'server', ip, port, blocking, tcp, anyPort, reuse=reuse) if not networkObject.ip: SysMgr.printWarn("fail to set server IP") return if tcp: proto = 'TCP' else: proto = 'UDP' SysMgr.localServObj = networkObject SysMgr.printInfo( "use %s:%d(%s) as local address" % \ (SysMgr.localServObj.ip, SysMgr.localServObj.port, proto)) return networkObject @staticmethod def prepareServerConn(cliAddr, servAddr): # set local address # if not cliAddr: NetworkMgr.setServerNetwork(None, None, anyPort=True) else: service, ip, port = NetworkMgr.parseAddr(cliAddr) NetworkMgr.setServerNetwork(ip, port) # set remote address # if servAddr: NetworkMgr.setRemoteServer(servAddr) # set client address # if SysMgr.localServObj: cliIp = SysMgr.localServObj.ip cliPort = SysMgr.localServObj.port else: cliIp = None cliPort = None # set server address # if SysMgr.remoteServObj.ip: servIp = SysMgr.remoteServObj.ip servPort = SysMgr.remoteServObj.port else: servIp = None servPort = None return (cliIp, cliPort), (servIp, servPort) @staticmethod def getRepMacAddr(): dirPath = '/sys/class/net' try: devices = os.listdir(dirPath) except SystemExit: sys.exit(0) except: SysMgr.printOpenErr(dirPath) return for dev in devices: if dev == 'lo': continue target = '%s/%s/address' % (dirPath, dev) try: with open(target, 'r') as fd: addr = fd.readline()[:-1] return (dev, addr) except SystemExit: sys.exit(0) except: SysMgr.printOpenErr(target) return ('None', 'None') @staticmethod def getUsingIps(): effectiveList = {} connPaths = \ ['%s/net/udp' % SysMgr.procPath, '%s/net/tcp' % SysMgr.procPath] for path in connPaths: try: with open(path, 'r') as fd: ipList = fd.readlines() # remove title # ipList.pop(0) for line in ipList: items = line.split() ip = SysMgr.convertCIDR(items[1].split(':')[0]) effectiveList[ip] = None except SystemExit: sys.exit(0) except: SysMgr.printOpenWarn(path) return list(effectiveList.keys()) @staticmethod def getGateways(): gateways = {} ips = NetworkMgr.getRoutedIps() for item in ips: try: ip = item[1] if ip == '0.0.0.0' or \ ip == '127.0.0.1' or \ not ip.endswith('.1'): continue gw = '%s.1' % ip[:ip.rfind('.')] gateways[gw] = None except SystemExit: sys.exit(0) except: pass return list(gateways.keys()) @staticmethod def getMainIp(): ipList = {} ipList = NetworkMgr.getUsingIps() # remove invaild ip # try: ipList.remove('0.0.0.0') except: pass if not ipList or not ipList: return None elif '127.0.0.1' in ipList: return '127.0.0.1' else: return list(sorted(ipList, reverse=True))[0] @staticmethod def getRoutedIps(): effectiveList = [] routePath = '%s/net/route' % SysMgr.procPath try: with open(routePath, 'r') as fd: ipList = fd.readlines() # remove title # ipList.pop(0) for line in ipList: items = line.split() effectiveList.append( [items[0], SysMgr.convertCIDR(items[1])]) return effectiveList except SystemExit: sys.exit(0) except: SysMgr.printOpenWarn(routePath) return effectiveList @staticmethod def getPublicIp(): # get socket object # socket = SysMgr.getPkg('socket', False) if not socket: return from socket import socket, AF_INET, SOCK_DGRAM, SOCK_STREAM ret = None try: s = socket(AF_INET, SOCK_STREAM) s.settimeout(0.3) # connect to google public IP # s.connect(("8.8.8.8", 53)) ret = s.getsockname()[0] except SystemExit: sys.exit(0) except: SysMgr.printWarn("fail to get public IP address") if not ret: ret = NetworkMgr.getMainIp() return ret def __del__(self): try: self.close() except: pass class Timeline(object): class Segment(object): def __init__(self, group, time_start, time_end, extra): self.group = group self.time_start = time_start self.time_end = time_end self.text = None self.id = None self.color = None self.state = None self._init_extra(extra) def _init_extra(self, extra): if "text" in extra: self.text = extra["text"] if "id" in extra: self.id = extra["id"] if "color" in extra: self.color = extra["color"] if "state" in extra: self.state = extra["state"] class Config(object): def _conv_palette(self, palette): # get svgwrite object # svgwrite = SysMgr.getPkg('svgwrite') plist = [] for palette_entry in palette: rgb = [int(rgb_value) for rgb_value in \ re.findall("\d+", palette_entry)] plist.append(svgwrite.rgb(rgb[0], rgb[1], rgb[2])) return plist def __init__(self): self.WIDTH = 1500 self.HEIGHT = 770 self.TIME_AXIS_HEIGHT = 1 self.TICKS = 100 self.LABEL_SIZE_MIN = 0 # set font size # if 'FONTSIZE' in SysMgr.environList: try: val = SysMgr.environList['FONTSIZE'][0] self.FONT_SIZE = long(val) except: SysMgr.printErr( "fail to set font size to '%s'" % val, True) sys.exit(0) else: self.FONT_SIZE = 3 palette = [ "(0,150,136)", "(0,188,212)", "(0,0,128)", "(0,0,139)", "(0,0,205)", "(0,0,255)", "(0,100,0)", "(0,128,0)", "(0,128,128)", "(0,139,139)", "(0,191,255)", "(0,206,209)", "(0,250,154)", "(0,255,0)", "(0,255,127)", "(0,255,255)", "(100,149,237)", "(102,205,170)", "(103,58,183)", "(106,90,205)", "(107,142,35)", "(121,85,72)", "(123,104,238)", "(124,252,0)", "(127,255,0)", "(127,255,212)", "(128,0,0)", "(128,0,128)", "(128,128,0)", "(128,128,128)", "(135,206,235)", "(135,206,250)", "(138,43,226)", "(139,195,74)", "(139,0,0)", "(139,0,139)", "(139,69,19)", "(143,188,143)", "(144,238,144)", "(147,112,219)", "(148,0,211)", "(152,251,152)", "(153,50,204)", "(154,205,50)", "(156,39,176)", "(158,158,158)", "(160,82,45)", "(165,42,42)", "(173,216,230)", "(173,255,47)", "(175,238,238)", "(176,224,230)", "(178,34,34)", "(184,134,11)", "(186,85,211)", "(188,143,143)", "(189,183,107)", "(192,192,192)", "(199,21,133)", "(205,133,63)", "(205,220,57)", "(205,92,92)", "(210,105,30)", "(210,180,140)", "(216,191,216)", "(218,112,214)", "(218,165,32)", "(219,112,147)", "(220,20,60)", "(221,160,221)", "(222,184,135)", "(224,255,255)", "(233,150,122)", "(233,30,99)", "(238,130,238)", "(238,232,170)", "(240,128,128)", "(240,230,140)", "(244,67,54)", "(244,164,96)", "(245,222,179)", "(245,245,220)", "(25,25,112)", "(250,128,114)", "(250,235,215)", "(250,250,210)", "(255,0,0)", "(255,0,255)", "(255,105,180)", "(255,127,80)", "(255,140,0)", "(255,152,0)", "(255,160,122)", "(255,165,0)", "(255,182,193)", "(255,192,203)", "(255,193,7)", "(255,20,147)", "(255,215,0)", "(255,228,196)", "(255,235,205)", "(255,235,59)", "(255,248,220)", "(255,250,205)", "(255,255,0)", "(255,255,224)", "(255,69,0)", "(255,87,34)", "(255,99,71)", "(3,169,244)", "(30,144,255)", "(32,178,170)", "(33,150,243)", "(34,139,34)", "(46,139,87)", "(47,79,79)", "(50,205,50)", "(60,179,113)", "(63,81,181)", "(64,224,208)", "(65,105,225)", "(70,130,180)", "(72,209,204)", "(72,61,139)", "(75,0,130)", "(76,175,80)", "(85,107,47)", "(95,158,160)", "(96,125,139)", ] self.PALETTE = self._conv_palette(palette) # shuffle list # random = SysMgr.getPkg('random', False) if random: random.shuffle(self.PALETTE) @staticmethod def _load(file_name=None, data=None): if file_name: with open(file_name) as fd: data = fd.read() data = UtilMgr.convStr2Dict(data) elif not data: SysMgr.printErr('no path or data for timeline config') sys.exit(0) config = Timeline.Config() config.WIDTH = data.get("width", 20000) config.HEIGHT = data.get("height", 4000) config.FONT_SIZE = data.get("font_size", 3) config.TICKS = data.get("time_ticks", 5) config.TIME_AXIS_HEIGHT = data.get("time_axis_height", 5) config.LABEL_SIZE_MIN = data.get("label_size_min", 5) config.PALETTE = config._conv_palette(data.get("palette", [])) config.TIMEUNIT = data.get("time_unit", None) config.TIMEFACTOR = data.get("time_factor", 1) return config def __init__( self, title, segments, time_unit, fontsize, config, tasks=[]): self.title = title self.segments = segments self.time_unit = time_unit self.config = config self.time_start = \ min(segments, key=lambda segment: segment.time_start).time_start self.time_end = \ max(segments, key=lambda segment: segment.time_end).time_end self.segment_groups = set(s.group for s in self.segments) self.groups = len(self.segment_groups) self.group_list = list(self.segment_groups) self.scaled_height = self.config.HEIGHT / self.groups try: self.ratio = \ self.config.WIDTH / float(self.time_end - self.time_start) except: SysMgr.printErr( 'fail to recognize timeline because start and end are same') sys.exit(0) self.tasks = tasks self.last_group_segment = dict() self.last_group_time = dict() self.height_group_pos = dict() self.last_iogroup_segment = dict() self.last_iogroup_time = dict() self.height_iogroup_pos = dict() # time factor # if hasattr(self.config, 'TIMEFACTOR'): self.time_factor = self.config.TIMEFACTOR else: self.time_factor = 1 # task color # if self.tasks: self.color_map = self._build_task_color_map() else: self.color_map = self._build_color_map() # update font size # if fontsize and self.config: self.config.FONT_SIZE = fontsize def _build_task_color_map(self): color_map = {} palette = self.config.PALETTE for i, group in enumerate(self.tasks): color_map[group] = palette[i % len(palette)] return color_map def _build_color_map(self): color_map = {} palette = self.config.PALETTE segment_groups = self.segment_groups for i, group in enumerate(segment_groups): color_map[group] = palette[i % len(palette)] return color_map def _draw_grid(self, dwg): for x in range(0, self.config.WIDTH, self.config.TICKS): dwg.add(dwg.line( (x, 0), (x, self.config.HEIGHT), stroke='black', stroke_width=0.1)) def _draw_group_axis(self, dwg): dwg.add(dwg.rect( (0, 0), (self.config.TIME_AXIS_HEIGHT, self.config.HEIGHT), fill='black')) idx = 0 groupList = list(self.segment_groups) for y_tick in range(0, self.config.HEIGHT): try: name = groupList[idx] idx += 1 except: continue y_tick *= self.scaled_height dwg.add(dwg.line( (0, y_tick), (self.config.WIDTH, y_tick), stroke='black', stroke_width=0.1)) dwg.add(dwg.text( name, (self.config.FONT_SIZE, y_tick+self.scaled_height), font_size=self.scaled_height/2, fill='rgb(220,220,220)')) def _draw_time_axis(self, dwg): dwg.add(dwg.rect( (0, self.config.HEIGHT), (self.config.WIDTH, self.config.TIME_AXIS_HEIGHT), fill='black')) y_time_tick = self.config.HEIGHT + self.config.TIME_AXIS_HEIGHT / 2 for x_tick_time in range(0, self.config.WIDTH, self.config.TICKS): tick_time = "{:10}".format(long(x_tick_time * (1 / self.ratio))) dwg.add(dwg.text( '%s %s' % (UtilMgr.convNum(tick_time), self.time_unit), (x_tick_time, y_time_tick + self.config.FONT_SIZE*5), font_size=self.config.FONT_SIZE*5, color='rgb(255,255,255)')) def _draw_background(self, dwg): dwg.add(dwg.rect((0, 0), (self.config.WIDTH, self.config.HEIGHT), fill='rgb(245,245,245)')) # set title # if self.title: title = self.title else: title = 'Guider Timeline Chart' # set font size for title # fontsize = self.config.FONT_SIZE * 10 dwg.add(dwg.text(title, ((self.config.WIDTH/2)-(len(title)*fontsize/4), fontsize), font_size=fontsize, font_weight='bolder', fill='rgb(230,230,230)')) def _draw_segments(self, dwg): for idx, segment in enumerate(self.segments): UtilMgr.printProgress(idx, len(self.segments)) self._draw_segment(segment, dwg) UtilMgr.deleteProgress() def _draw_segment(self, segment, dwg): x0 = float(segment.time_start - self.time_start) * self.ratio x1 = float(segment.time_end - self.time_start) * self.ratio group_idx = self.group_list.index(segment.group) y0 = self.scaled_height * float(group_idx % self.groups) y1 = self.scaled_height * float((group_idx % self.groups)+1) scaled_width = (x1 - x0) scaled_top_height = y0 + (self.scaled_height / 7) scaled_bottom_height = y1 - (self.scaled_height * 0.25) # get color id # if segment.color: color = segment.color else: if segment.id: colorid = segment.id else: colorid = group_idx # get real color via id # try: color = self.color_map[colorid] except: color = self.color_map[list(self.color_map.keys())[0]] # draw bold line for core off # if segment.state == 'OFF': dwg.add(dwg.line( (x0, y0), (x1, y0), stroke='black', stroke_width=1.5)) return # draw circle and text for event # if segment.state and segment.state.startswith('EVENT'): if segment.state == 'EVENT_MARK': font_size = self.config.FONT_SIZE elif segment.state == 'EVENT_USER': font_size = self.config.FONT_SIZE * 3 else: font_size = self.config.FONT_SIZE dwg.add(dwg.circle( center=(x0,y0), r=font_size/2, stroke='darkgreen', fill='darkgreen')) # draw text # dwg.add(dwg.text(segment.text, (x0+font_size, y0), fill='darkgreen', stroke='none', font_size=font_size, font_weight='bolder')) return # draw line for block_read status # if segment.state == 'RD': dwg.add(dwg.rect((x0, scaled_bottom_height), (scaled_width, self.scaled_height*0.25), rx=1, ry=1, fill='purple', fill_opacity=0.5)) # draw line for block_write status # elif segment.state == 'WR': dwg.add(dwg.rect((x0, scaled_bottom_height), (scaled_width, self.scaled_height*0.25), rx=1, ry=1, fill='darkcyan', fill_opacity=0.5)) # draw line for syscall status # elif segment.state == 'SYSCALL': dwg.add(dwg.rect((x0, y0), (scaled_width, self.scaled_height*0.5), rx=1, ry=1, fill=color, fill_opacity=0.5)) # draw line for sched status # else: # draw timeslice # dwg.add(dwg.rect((x0, y0), (scaled_width, self.scaled_height), rx=1, ry=1, fill=color, fill_opacity=0.5)) # draw preempted status # if segment.state == 'R': dwg.add(dwg.line( (x1, y0), (x1, scaled_top_height), stroke='red', stroke_width=0.3)) # draw wait status # elif segment.state == 'D': dwg.add(dwg.line( (x1, y0), (x1, scaled_top_height), stroke='black', stroke_width=0.3)) # check duration # duration = segment.time_end - segment.time_start if not SysMgr.showAll and \ (scaled_width < self.config.LABEL_SIZE_MIN or duration == 0): return # convert duration to text # if duration == 0: duration = '~' else: duration = '~%s' % (UtilMgr.convNum(duration)) # I/O # if segment.state == 'RD' or segment.state == 'WR': # initialize group data # self.last_iogroup_segment.setdefault(group_idx, None) self.last_iogroup_time.setdefault(group_idx, x0) # define data # last_iogroup_segment = self.last_iogroup_segment[group_idx] last_iogroup_time = self.last_iogroup_time[group_idx] # set text attributes for block_read # if segment.state == 'RD': if last_iogroup_segment == segment.text and \ x0 - last_iogroup_time < self.config.TICKS: segment_label = duration font_size = self.config.FONT_SIZE - 1 else: segment_label = "> %s | %s" % (segment.text, duration) font_size = self.config.FONT_SIZE - 0.7 color = 'rgb(128,0,128)' # set text attributes for block_write # elif segment.state == 'WR': if last_iogroup_segment == segment.text and \ x0 - last_iogroup_time < self.config.TICKS: segment_label = duration font_size = self.config.FONT_SIZE - 1 else: segment_label = "> %s | %s" % (segment.text, duration) font_size = self.config.FONT_SIZE - 0.7 color = 'rgb(0,139,139)' # update group info # self.last_iogroup_segment[group_idx] = segment.text self.last_iogroup_time[group_idx] = x0 self.height_iogroup_pos.setdefault(group_idx, 0) # set text position # scaled_pos = self.scaled_height * 0.75 self.height_iogroup_pos[group_idx] += self.config.FONT_SIZE height_pos = self.height_iogroup_pos[group_idx] if height_pos + scaled_pos >= self.scaled_height: height_pos = \ self.height_iogroup_pos[group_idx] = \ self.config.FONT_SIZE # CPU # else: # initialize group data # self.last_group_segment.setdefault(group_idx, None) self.last_group_time.setdefault(group_idx, x0) # set text attributes for same task # if self.last_group_segment[group_idx] == segment.text and \ x0 - self.last_group_time[group_idx] < self.config.TICKS: segment_label = duration color = 'rgb(50,50,50)' font_size = self.config.FONT_SIZE - 1 # set text attributes for new task # else: segment_label = "> %s | %s" % (segment.text, duration) color = 'rgb(255,0,0)' font_size = self.config.FONT_SIZE - 0.5 # update group info # self.last_group_segment[group_idx] = segment.text self.last_group_time[group_idx] = x0 self.height_group_pos.setdefault(group_idx, 0) # set text position # scaled_pos = self.scaled_height * 0.15 self.height_group_pos[group_idx] += self.config.FONT_SIZE height_pos = self.height_group_pos[group_idx] if height_pos + scaled_pos*2.5 >= self.scaled_height: height_pos = self.height_group_pos[group_idx] = 0 xpos = x0 ypos = y0 + scaled_pos + height_pos # draw text # dwg.add(dwg.text(segment_label, (xpos, ypos), fill=color, stroke='none', font_size=font_size, font_weight='normal', transform='rotate(0,%s,%s)' % (xpos, ypos))) def draw(self, dwg): self._draw_background(dwg) self._draw_grid(dwg) self._draw_group_axis(dwg) self._draw_time_axis(dwg) self._draw_segments(dwg) @staticmethod def load(file_name=None, data=None, config=None, tasks=None): if file_name: with open(file_name) as json_file: # get json object # json = SysMgr.getPkg('json') data = json.load(json_file) elif not data: SysMgr.printErr('no path or data for timeline input') sys.exit(0) # get default timeunit # time_unit = '' if "time_unit" in data: time_unit = data["time_unit"] time_unit = time_unit.lower() # get title # if "title" in data: title = data['title'] else: title = '' # get title # if "font_size" in data: fontsize = data['font_size'] else: fontsize = None # get configured timeunit # time_factor = 1.0 if hasattr(config, 'TIMEUNIT') and config.TIMEUNIT: new_time_unit = config.TIMEUNIT.lower() if time_unit == new_time_unit: pass elif time_unit == 'ns': if new_time_unit == 'ms': time_factor = 1/1000.0 elif new_time_unit == 'sec': time_factor = 1/1000000.0 else: SysMgr.printErr( "no support '%s' unit for timeline" % new_time_unit) elif time_unit == 'ms': if new_time_unit == 'ns': time_factor = 1000.0 elif new_time_unit == 'sec': time_factor = 1/1000.0 else: SysMgr.printErr( "no support '%s' unit for timeline" % new_time_unit) else: SysMgr.printErr( "no support '%s' unit for timeline" % new_time_unit) time_unit = new_time_unit config.TIMEFACTOR = time_factor if time_unit: SysMgr.printInfo( "apply '%s' in timeunit" % time_unit) # load segments # segments = Timeline._load_segments(data, time_factor) return Timeline(title, segments, time_unit, fontsize, config, tasks) @staticmethod def _load_segments(data, time_factor=1): segments = [] for segment_data in sorted( data["segments"], key=lambda e: e['time_start']): # apply core filter # if SysMgr.perCoreDrawList: if not segment_data['group'] in SysMgr.perCoreDrawList: continue # verify time # if segment_data["time_start"] > segment_data["time_end"]: SysMgr.printWarn( "time_start is bigger than time_end for %s" % \ segment_data) continue time_start = long(segment_data["time_start"] * time_factor) time_end = long(segment_data["time_end"] * time_factor) # add segment # segments.append(Timeline.Segment( segment_data["group"], time_start, time_end, segment_data)) return segments ''' class GlMgr(object): """ Manager for GL """ instance = None @staticmethod def init(): SysMgr.importPkgItems('ctypes') try: # load libglesobj library # if not SysMgr.libglesObj: SysMgr.libglesObj = SysMgr.loadLib(SysMgr.libglesPath) except: SysMgr.printErr( "fail to load GLES object") sys.exit(0) gl = GlMgr.instance = SysMgr.libglesObj gl.glActiveShaderProgram.argtypes = [c_uint32, c_uint32] gl.glActiveShaderProgram.restype = None gl.glActiveTexture.argtypes = [c_uint] gl.glActiveTexture.restype = None gl.glAttachShader.argtypes = [c_uint32, c_uint32] gl.glAttachShader.restype = None gl.glBeginQuery.argtypes = [c_uint, c_uint32] gl.glBeginQuery.restype = None gl.glBeginTransformFeedback.argtypes = [c_uint] gl.glBeginTransformFeedback.restype = None gl.glBindAttribLocation.argtypes = [c_uint32, c_uint32, POINTER(c_char)] gl.glBindAttribLocation.restype = None gl.glBindBuffer.argtypes = [c_uint, c_uint32] gl.glBindBuffer.restype = None gl.glBindBufferBase.argtypes = [c_uint, c_uint32, c_uint32] gl.glBindBufferBase.restype = None gl.glBindBufferRange.argtypes = [c_uint, c_uint32, c_uint32, c_size_t, c_ssize_t] gl.glBindBufferRange.restype = None gl.glBindFramebuffer.argtypes = [c_uint, c_uint32] gl.glBindFramebuffer.restype = None gl.glBindImageTexture.argtypes = [c_uint32, c_uint32, c_int32, c_ubyte, c_int32, c_uint, c_uint] gl.glBindImageTexture.restype = None gl.glBindProgramPipeline.argtypes = [c_uint32] gl.glBindProgramPipeline.restype = None gl.glBindRenderbuffer.argtypes = [c_uint, c_uint32] gl.glBindRenderbuffer.restype = None gl.glBindSampler.argtypes = [c_uint32, c_uint32] gl.glBindSampler.restype = None gl.glBindTexture.argtypes = [c_uint, c_uint] gl.glBindTexture.restype = None gl.glBindTransformFeedback.argtypes = [c_uint, c_uint32] gl.glBindTransformFeedback.restype = None gl.glBindVertexArray.argtypes = [c_uint32] gl.glBindVertexArray.restype = None gl.glBindVertexBuffer.argtypes = [c_uint32, c_uint32, c_size_t, c_size_t] gl.glBindVertexBuffer.restype = None gl.glBlendColor.argtypes = [c_float, c_float, c_float, c_float] gl.glBlendColor.restype = None gl.glBlendEquation.argtypes = [c_uint] gl.glBlendEquation.restype = None gl.glBlendEquationSeparate.argtypes = [c_uint, c_uint] gl.glBlendEquationSeparate.restype = None gl.glBlendEquationSeparatei.argtypes = [c_uint32, c_uint, c_uint] gl.glBlendEquationSeparatei.restype = None gl.glBlendEquationi.argtypes = [c_uint32, c_uint] gl.glBlendEquationi.restype = None gl.glBlendFunc.argtypes = [c_uint, c_uint] gl.glBlendFunc.restype = None gl.glBlendFuncSeparate.argtypes = [c_uint, c_uint, c_uint, c_uint] gl.glBlendFuncSeparate.restype = None gl.glBlendFuncSeparatei.argtypes = [c_uint32, c_uint, c_uint, c_uint, c_uint] gl.glBlendFuncSeparatei.restype = None gl.glBlendFunci.argtypes = [c_uint32, c_uint, c_uint] gl.glBlendFunci.restype = None gl.glBlitFramebuffer.argtypes = [c_int32, c_int32, c_int32, c_int32, c_int32, c_int32, c_int32, c_int32, c_uint, c_uint] gl.glBlitFramebuffer.restype = None gl.glBufferData.argtypes = [c_uint, c_ssize_t, c_void_p, c_uint] gl.glBufferData.restype = None gl.glBufferSubData.argtypes = [c_uint, c_size_t, c_ssize_t, c_void_p] gl.glBufferSubData.restype = None gl.glCheckFramebufferStatus.argtypes = [c_uint] gl.glCheckFramebufferStatus.restype = c_uint gl.glClear.argtypes = [c_uint] gl.glClear.restype = None gl.glClearBufferfi.argtypes = [c_uint, c_int, c_float, c_int32] gl.glClearBufferfi.restype = None gl.glClearBufferfv.argtypes = [c_uint, c_int, POINTER(c_float)] gl.glClearBufferfv.restype = None gl.glClearBufferiv.argtypes = [c_uint, c_int, POINTER(c_int32)] gl.glClearBufferiv.restype = None gl.glClearBufferuiv.argtypes = [c_uint, c_int, POINTER(c_uint32)] gl.glClearBufferuiv.restype = None gl.glClearColor.argtypes = [c_float, c_float, c_float, c_float] gl.glClearColor.restype = None gl.glClearDepthf.argtypes = [c_float] gl.glClearDepthf.restype = None gl.glClearStencil.argtypes = [c_int] gl.glClearStencil.restype = None gl.glColorMask.argtypes = [c_ubyte, c_ubyte, c_ubyte, c_ubyte] gl.glColorMask.restype = None gl.glColorMaski.argtypes = [c_uint32, c_ubyte, c_ubyte, c_ubyte, c_ubyte] gl.glColorMaski.restype = None gl.glCompileShader.argtypes = [c_uint32] gl.glCompileShader.restype = None gl.glCompressedTexImage2D.argtypes = [c_uint, c_long, c_uint, c_size_t, c_size_t, c_long, c_size_t, c_void_p] gl.glCompressedTexImage2D.restype = None gl.glCompressedTexImage3D.argtypes = [c_uint, c_long, c_uint, c_size_t, c_size_t, c_size_t, c_long, c_size_t, c_void_p] gl.glCompressedTexImage3D.restype = None gl.glCompressedTexSubImage2D.argtypes = [c_uint, c_long, c_long, c_long, c_size_t, c_size_t, c_uint, c_size_t, c_void_p] gl.glCompressedTexSubImage2D.restype = None gl.glCompressedTexSubImage3D.argtypes = [c_uint, c_long, c_long, c_long, c_long, c_size_t, c_size_t, c_size_t, c_uint, c_size_t, c_void_p] gl.glCompressedTexSubImage3D.restype = None gl.glCopyBufferSubData.argtypes = [c_uint, c_uint, c_size_t, c_size_t, c_ssize_t] gl.glCopyBufferSubData.restype = None gl.glCopyImageSubData.argtypes = [c_uint32, c_uint, c_int32, c_int32, c_int32, c_int32, c_uint32, c_uint, c_int32, c_int32, c_int32, c_int32, c_size_t, c_size_t, c_size_t] gl.glCopyImageSubData.restype = None gl.glCopyTexImage2D.argtypes = [c_uint, c_long, c_uint, c_int, c_int, c_size_t, c_size_t, c_long] gl.glCopyTexImage2D.restype = None gl.glCopyTexSubImage2D.argtypes = [c_uint, c_long, c_long, c_long, c_int, c_int, c_size_t, c_size_t] gl.glCopyTexSubImage2D.restype = None gl.glCopyTexSubImage3D.argtypes = [c_uint, c_long, c_long, c_long, c_long, c_int, c_int, c_size_t, c_size_t] gl.glCopyTexSubImage3D.restype = None gl.glCreateProgram.argtypes = None gl.glCreateProgram.restype = c_uint32 gl.glCreateShader.argtypes = [c_uint] gl.glCreateShader.restype = c_uint32 gl.glCreateShaderProgramv.argtypes = [c_uint, c_size_t, POINTER(c_char_p)] gl.glCreateShaderProgramv.restype = c_uint32 gl.glCullFace.argtypes = [c_uint] gl.glCullFace.restype = None gl.glDebugMessageControl.argtypes = [c_uint, c_uint, c_uint, c_size_t, POINTER(c_uint32), c_ubyte] gl.glDebugMessageControl.restype = None gl.glDebugMessageInsert.argtypes = [c_uint, c_uint, c_uint32, c_uint, c_size_t, POINTER(c_char)] gl.glDebugMessageInsert.restype = None gl.glDeleteBuffers.argtypes = [c_size_t, POINTER(c_ulong)] gl.glDeleteBuffers.restype = None gl.glDeleteFramebuffers.argtypes = [c_size_t, POINTER(c_uint32)] gl.glDeleteFramebuffers.restype = None gl.glDeleteProgram.argtypes = [c_uint32] gl.glDeleteProgram.restype = None gl.glDeleteProgramPipelines.argtypes = [c_size_t, POINTER(c_uint32)] gl.glDeleteProgramPipelines.restype = None gl.glDeleteQueries.argtypes = [c_size_t, POINTER(c_uint32)] gl.glDeleteQueries.restype = None gl.glDeleteRenderbuffers.argtypes = [c_size_t, POINTER(c_uint32)] gl.glDeleteRenderbuffers.restype = None gl.glDeleteSamplers.argtypes = [c_size_t, POINTER(c_uint32)] gl.glDeleteSamplers.restype = None gl.glDeleteShader.argtypes = [c_uint32] gl.glDeleteShader.restype = None gl.glDeleteTextures.argtypes = [c_size_t, POINTER(c_uint)] gl.glDeleteTextures.restype = None gl.glDeleteTransformFeedbacks.argtypes = [c_size_t, POINTER(c_uint32)] gl.glDeleteTransformFeedbacks.restype = None gl.glDeleteVertexArrays.argtypes = [c_size_t, POINTER(c_uint32)] gl.glDeleteVertexArrays.restype = None gl.glDepthFunc.argtypes = [c_uint] gl.glDepthFunc.restype = None gl.glDepthMask.argtypes = [c_ubyte] gl.glDepthMask.restype = None gl.glDepthRangef.argtypes = [c_float, c_float] gl.glDepthRangef.restype = None gl.glDetachShader.argtypes = [c_uint32, c_uint32] gl.glDetachShader.restype = None gl.glDisable.argtypes = [c_uint] gl.glDisable.restype = None gl.glDisableVertexAttribArray.argtypes = [c_uint32] gl.glDisableVertexAttribArray.restype = None gl.glDisablei.argtypes = [c_uint, c_uint32] gl.glDisablei.restype = None gl.glDispatchCompute.argtypes = [c_uint32, c_uint32, c_uint32] gl.glDispatchCompute.restype = None gl.glDispatchComputeIndirect.argtypes = [c_size_t] gl.glDispatchComputeIndirect.restype = None gl.glDrawArrays.argtypes = [c_uint, c_int32, c_size_t] gl.glDrawArrays.restype = None gl.glDrawArraysIndirect.argtypes = [c_uint, c_void_p] gl.glDrawArraysIndirect.restype = None gl.glDrawArraysInstanced.argtypes = [c_uint, c_int32, c_size_t, c_size_t] gl.glDrawArraysInstanced.restype = None gl.glDrawBuffers.argtypes = [c_size_t, POINTER(c_uint)] gl.glDrawBuffers.restype = None gl.glDrawElements.argtypes = [c_uint, c_size_t, c_uint, c_void_p] gl.glDrawElements.restype = None gl.glDrawElementsBaseVertex.argtypes = [c_uint, c_size_t, c_uint, c_void_p, c_int32] gl.glDrawElementsBaseVertex.restype = None gl.glDrawElementsIndirect.argtypes = [c_uint, c_uint, c_void_p] gl.glDrawElementsIndirect.restype = None gl.glDrawElementsInstanced.argtypes = [c_uint, c_size_t, c_uint, c_void_p, c_size_t] gl.glDrawElementsInstanced.restype = None gl.glDrawElementsInstancedBaseVertex.argtypes = [c_uint, c_size_t, c_uint, c_void_p, c_size_t, c_int32] gl.glDrawElementsInstancedBaseVertex.restype = None gl.glDrawRangeElements.argtypes = [c_uint, c_uint32, c_uint32, c_size_t, c_uint, c_void_p] gl.glDrawRangeElements.restype = None gl.glDrawRangeElementsBaseVertex.argtypes = [c_uint, c_uint32, c_uint32, c_size_t, c_uint, c_void_p, c_int32] gl.glDrawRangeElementsBaseVertex.restype = None gl.glEnable.argtypes = [c_uint] gl.glEnable.restype = None gl.glEnableVertexAttribArray.argtypes = [c_uint32] gl.glEnableVertexAttribArray.restype = None gl.glEnablei.argtypes = [c_uint, c_uint32] gl.glEnablei.restype = None gl.glEndQuery.argtypes = [c_uint] gl.glEndQuery.restype = None gl.glEndTransformFeedback.argtypes = None gl.glEndTransformFeedback.restype = None gl.glFinish.argtypes = None gl.glFinish.restype = None gl.glFlush.argtypes = None gl.glFlush.restype = None gl.glFlushMappedBufferRange.argtypes = [c_uint, c_size_t, c_ssize_t] gl.glFlushMappedBufferRange.restype = None gl.glFramebufferParameteri.argtypes = [c_uint, c_uint, c_int32] gl.glFramebufferParameteri.restype = None gl.glFramebufferRenderbuffer.argtypes = [c_uint, c_uint, c_uint, c_uint32] gl.glFramebufferRenderbuffer.restype = None gl.glFramebufferTexture.argtypes = [c_uint, c_uint, c_uint32, c_int32] gl.glFramebufferTexture.restype = None gl.glFramebufferTexture2D.argtypes = [c_uint, c_uint, c_uint, c_uint32, c_int32] gl.glFramebufferTexture2D.restype = None gl.glFramebufferTextureLayer.argtypes = [c_uint, c_uint, c_uint, c_long, c_long] gl.glFramebufferTextureLayer.restype = None gl.glFrontFace.argtypes = [c_uint] gl.glFrontFace.restype = None gl.glGenBuffers.argtypes = [c_size_t, POINTER(c_uint32)] gl.glGenBuffers.restype = None gl.glGenFramebuffers.argtypes = [c_size_t, POINTER(c_uint32)] gl.glGenFramebuffers.restype = None gl.glGenProgramPipelines.argtypes = [c_size_t, POINTER(c_uint32)] gl.glGenProgramPipelines.restype = None gl.glGenQueries.argtypes = [c_size_t, POINTER(c_uint32)] gl.glGenQueries.restype = None gl.glGenRenderbuffers.argtypes = [c_size_t, POINTER(c_uint32)] gl.glGenRenderbuffers.restype = None gl.glGenSamplers.argtypes = [c_size_t, POINTER(c_uint32)] gl.glGenSamplers.restype = None gl.glGenTextures.argtypes = [c_size_t, POINTER(c_uint)] gl.glGenTextures.restype = None gl.glGenTransformFeedbacks.argtypes = [c_size_t, POINTER(c_uint32)] gl.glGenTransformFeedbacks.restype = None gl.glGenVertexArrays.argtypes = [c_size_t, POINTER(c_uint32)] gl.glGenVertexArrays.restype = None gl.glGenerateMipmap.argtypes = [c_uint] gl.glGenerateMipmap.restype = None gl.glGetActiveAttrib.argtypes = [c_uint32, c_uint32, c_size_t, POINTER(c_size_t), POINTER(c_int32), POINTER(c_uint), POINTER(c_char)] gl.glGetActiveAttrib.restype = None gl.glGetActiveUniform.argtypes = [c_uint32, c_uint32, c_size_t, POINTER(c_size_t), POINTER(c_int32), POINTER(c_uint), POINTER(c_char)] gl.glGetActiveUniform.restype = None gl.glGetActiveUniformBlockName.argtypes = [c_uint32, c_uint32, c_size_t, POINTER(c_size_t), POINTER(c_char)] gl.glGetActiveUniformBlockName.restype = None gl.glGetActiveUniformBlockiv.argtypes = [c_uint32, c_uint32, c_uint, POINTER(c_int32)] gl.glGetActiveUniformBlockiv.restype = None gl.glGetActiveUniformsiv.argtypes = [c_uint32, c_size_t, POINTER(c_uint32), c_uint, POINTER(c_int32)] gl.glGetActiveUniformsiv.restype = None gl.glGetAttachedShaders.argtypes = [c_uint32, c_size_t, POINTER(c_size_t), POINTER(c_uint32)] gl.glGetAttachedShaders.restype = None gl.glGetAttribLocation.argtypes = [c_uint32, POINTER(c_char)] gl.glGetAttribLocation.restype = c_int32 gl.glGetBooleanv.argtypes = [c_uint, POINTER(c_ubyte)] gl.glGetBooleanv.restype = None gl.glGetBufferParameteri64v.argtypes = [c_uint, c_uint, POINTER(c_int64)] gl.glGetBufferParameteri64v.restype = None gl.glGetBufferParameteriv.argtypes = [c_uint, c_uint, POINTER(c_int32)] gl.glGetBufferParameteriv.restype = None gl.glGetBufferPointerv.argtypes = [c_uint, c_uint, POINTER(c_void_p)] gl.glGetBufferPointerv.restype = None gl.glGetDebugMessageLog.argtypes = [c_uint32, c_size_t, POINTER(c_uint), POINTER(c_uint), POINTER(c_uint32), POINTER(c_uint), POINTER(c_size_t), POINTER(c_char)] gl.glGetDebugMessageLog.restype = c_uint32 gl.glGetError.argtypes = None gl.glGetError.restype = c_uint gl.glGetFloatv.argtypes = [c_uint, POINTER(c_float)] gl.glGetFloatv.restype = None gl.glGetFragDataLocation.argtypes = [c_uint32, POINTER(c_char)] gl.glGetFragDataLocation.restype = c_int32 gl.glGetFramebufferAttachmentParameteriv.argtypes = [c_uint, c_uint, c_uint, POINTER(c_int32)] gl.glGetFramebufferAttachmentParameteriv.restype = None gl.glGetFramebufferParameteriv.argtypes = [c_uint, c_uint, POINTER(c_int32)] gl.glGetFramebufferParameteriv.restype = None gl.glGetInteger64v.argtypes = [c_uint, POINTER(c_int64)] gl.glGetInteger64v.restype = None gl.glGetIntegerv.argtypes = [c_uint, POINTER(c_int32)] gl.glGetIntegerv.restype = None gl.glGetInternalformativ.argtypes = [c_uint, c_uint, c_uint, c_size_t, POINTER(c_int32)] gl.glGetInternalformativ.restype = None gl.glGetMultisamplefv.argtypes = [c_uint, c_uint32, POINTER(c_float)] gl.glGetMultisamplefv.restype = None gl.glGetObjectLabel.argtypes = [c_uint, c_uint32, c_size_t, POINTER(c_size_t), POINTER(c_char)] gl.glGetObjectLabel.restype = None gl.glGetObjectPtrLabel.argtypes = [c_void_p, c_size_t, POINTER(c_size_t), POINTER(c_char)] gl.glGetObjectPtrLabel.restype = None gl.glGetPointerv.argtypes = [c_uint, POINTER(c_void_p)] gl.glGetPointerv.restype = None gl.glGetProgramBinary.argtypes = [c_uint32, c_size_t, POINTER(c_size_t), POINTER(c_uint), c_void_p] gl.glGetProgramBinary.restype = None gl.glGetProgramInfoLog.argtypes = [c_uint32, c_size_t, POINTER(c_size_t), POINTER(c_char)] gl.glGetProgramInfoLog.restype = None gl.glGetProgramInterfaceiv.argtypes = [c_uint32, c_uint, c_uint, POINTER(c_int32)] gl.glGetProgramInterfaceiv.restype = None gl.glGetProgramPipelineInfoLog.argtypes = [c_uint32, c_size_t, POINTER(c_size_t), POINTER(c_char)] gl.glGetProgramPipelineInfoLog.restype = None gl.glGetProgramPipelineiv.argtypes = [c_uint32, c_uint, POINTER(c_int32)] gl.glGetProgramPipelineiv.restype = None gl.glGetProgramResourceIndex.argtypes = [c_uint32, c_uint, POINTER(c_char)] gl.glGetProgramResourceIndex.restype = c_uint32 gl.glGetProgramResourceLocation.argtypes = [c_uint32, c_uint, POINTER(c_char)] gl.glGetProgramResourceLocation.restype = c_int32 gl.glGetProgramResourceName.argtypes = [c_uint32, c_uint, c_uint32, c_size_t, POINTER(c_size_t), POINTER(c_char)] gl.glGetProgramResourceName.restype = None gl.glGetProgramResourceiv.argtypes = [c_uint32, c_uint, c_uint32, c_size_t, POINTER(c_uint), c_size_t, POINTER(c_size_t), POINTER(c_int32)] gl.glGetProgramResourceiv.restype = None gl.glGetProgramiv.argtypes = [c_uint32, c_uint, POINTER(c_int32)] gl.glGetProgramiv.restype = None gl.glGetQueryObjectuiv.argtypes = [c_uint32, c_uint, POINTER(c_uint32)] gl.glGetQueryObjectuiv.restype = None gl.glGetQueryiv.argtypes = [c_uint, c_uint, POINTER(c_int32)] gl.glGetQueryiv.restype = None gl.glGetRenderbufferParameteriv.argtypes = [c_uint, c_uint, POINTER(c_int32)] gl.glGetRenderbufferParameteriv.restype = None gl.glGetSamplerParameterIiv.argtypes = [c_uint32, c_uint, POINTER(c_int32)] gl.glGetSamplerParameterIiv.restype = None gl.glGetSamplerParameterIuiv.argtypes = [c_uint32, c_uint, POINTER(c_uint32)] gl.glGetSamplerParameterIuiv.restype = None gl.glGetSamplerParameterfv.argtypes = [c_uint32, c_uint, POINTER(c_float)] gl.glGetSamplerParameterfv.restype = None gl.glGetSamplerParameteriv.argtypes = [c_uint32, c_uint, POINTER(c_int32)] gl.glGetSamplerParameteriv.restype = None gl.glGetShaderInfoLog.argtypes = [c_uint32, c_size_t, POINTER(c_size_t), POINTER(c_char)] gl.glGetShaderInfoLog.restype = None gl.glGetShaderPrecisionFormat.argtypes = [c_uint, c_uint, POINTER(c_int32), POINTER(c_int32)] gl.glGetShaderPrecisionFormat.restype = None gl.glGetShaderSource.argtypes = [c_uint32, c_size_t, POINTER(c_size_t), POINTER(c_char)] gl.glGetShaderSource.restype = None gl.glGetShaderiv.argtypes = [c_uint32, c_uint, POINTER(c_int32)] gl.glGetShaderiv.restype = None gl.glGetString.argtypes = [c_uint] gl.glGetString.restype = c_char_p gl.glGetStringi.argtypes = [c_uint, c_uint32] gl.glGetStringi.restype = c_char_p gl.glGetTexLevelParameterfv.argtypes = [c_uint, c_long, c_uint, POINTER(c_float)] gl.glGetTexLevelParameterfv.restype = None gl.glGetTexLevelParameteriv.argtypes = [c_uint, c_long, c_uint, POINTER(c_int32)] gl.glGetTexLevelParameteriv.restype = None gl.glGetTexParameterIiv.argtypes = [c_uint, c_uint, POINTER(c_int32)] gl.glGetTexParameterIiv.restype = None gl.glGetTexParameterIuiv.argtypes = [c_uint, c_uint, POINTER(c_uint32)] gl.glGetTexParameterIuiv.restype = None gl.glGetTexParameterfv.argtypes = [c_uint, c_uint, POINTER(c_float)] gl.glGetTexParameterfv.restype = None gl.glGetTexParameteriv.argtypes = [c_uint, c_uint, POINTER(c_int32)] gl.glGetTexParameteriv.restype = None gl.glGetTransformFeedbackVarying.argtypes = [c_uint32, c_uint32, c_size_t, POINTER(c_size_t), POINTER(c_size_t), POINTER(c_uint), POINTER(c_char)] gl.glGetTransformFeedbackVarying.restype = None gl.glGetUniformBlockIndex.argtypes = [c_uint32, POINTER(c_char)] gl.glGetUniformBlockIndex.restype = c_uint32 gl.glGetUniformIndices.argtypes = [c_uint32, c_size_t, POINTER(c_char_p), POINTER(c_uint32)] gl.glGetUniformIndices.restype = None gl.glGetUniformLocation.argtypes = [c_uint32, POINTER(c_char)] gl.glGetUniformLocation.restype = c_int32 gl.glGetUniformfv.argtypes = [c_uint32, c_int32, POINTER(c_float)] gl.glGetUniformfv.restype = None gl.glGetUniformiv.argtypes = [c_uint32, c_int32, POINTER(c_int32)] gl.glGetUniformiv.restype = None gl.glGetUniformuiv.argtypes = [c_uint32, c_int32, POINTER(c_uint32)] gl.glGetUniformuiv.restype = None gl.glGetVertexAttribIiv.argtypes = [c_uint32, c_uint, POINTER(c_int32)] gl.glGetVertexAttribIiv.restype = None gl.glGetVertexAttribIuiv.argtypes = [c_uint32, c_uint, POINTER(c_uint32)] gl.glGetVertexAttribIuiv.restype = None gl.glGetVertexAttribPointerv.argtypes = [c_uint32, c_uint, POINTER(c_void_p)] gl.glGetVertexAttribPointerv.restype = None gl.glGetVertexAttribfv.argtypes = [c_uint32, c_uint, POINTER(c_float)] gl.glGetVertexAttribfv.restype = None gl.glGetVertexAttribiv.argtypes = [c_uint32, c_uint, POINTER(c_int32)] gl.glGetVertexAttribiv.restype = None gl.glHint.argtypes = [c_uint, c_uint] gl.glHint.restype = None gl.glInvalidateFramebuffer.argtypes = [c_uint, c_size_t, POINTER(c_uint)] gl.glInvalidateFramebuffer.restype = None gl.glInvalidateSubFramebuffer.argtypes = [c_uint, c_size_t, POINTER(c_uint), c_int32, c_int32, c_size_t, c_size_t] gl.glInvalidateSubFramebuffer.restype = None gl.glIsBuffer.argtypes = [c_uint32] gl.glIsBuffer.restype = c_ubyte gl.glIsEnabled.argtypes = [c_uint] gl.glIsEnabled.restype = c_ubyte gl.glIsEnabledi.argtypes = [c_uint, c_uint32] gl.glIsEnabledi.restype = c_ubyte gl.glIsFramebuffer.argtypes = [c_uint32] gl.glIsFramebuffer.restype = c_ubyte gl.glIsProgram.argtypes = [c_uint32] gl.glIsProgram.restype = c_ubyte gl.glIsProgramPipeline.argtypes = [c_uint32] gl.glIsProgramPipeline.restype = c_ubyte gl.glIsQuery.argtypes = [c_uint32] gl.glIsQuery.restype = c_ubyte gl.glIsRenderbuffer.argtypes = [c_uint32] gl.glIsRenderbuffer.restype = c_ubyte gl.glIsSampler.argtypes = [c_uint32] gl.glIsSampler.restype = c_ubyte gl.glIsShader.argtypes = [c_uint32] gl.glIsShader.restype = c_ubyte gl.glIsTexture.argtypes = [c_uint] gl.glIsTexture.restype = c_ubyte gl.glIsTransformFeedback.argtypes = [c_uint32] gl.glIsTransformFeedback.restype = c_ubyte gl.glIsVertexArray.argtypes = [c_uint32] gl.glIsVertexArray.restype = c_ubyte gl.glLineWidth.argtypes = [c_float] gl.glLineWidth.restype = None gl.glLinkProgram.argtypes = [c_uint32] gl.glLinkProgram.restype = None gl.glMapBufferRange.argtypes = [c_uint, c_size_t, c_ssize_t, c_uint] gl.glMapBufferRange.restype = c_void_p gl.glMemoryBarrier.argtypes = [c_uint] gl.glMemoryBarrier.restype = None gl.glMinSampleShading.argtypes = [c_float] gl.glMinSampleShading.restype = None gl.glObjectLabel.argtypes = [c_uint, c_uint32, c_size_t, POINTER(c_char)] gl.glObjectLabel.restype = None gl.glObjectPtrLabel.argtypes = [c_void_p, c_size_t, POINTER(c_char)] gl.glObjectPtrLabel.restype = None gl.glPatchParameteri.argtypes = [c_uint, c_int32] gl.glPatchParameteri.restype = None gl.glPauseTransformFeedback.argtypes = None gl.glPauseTransformFeedback.restype = None gl.glPixelStorei.argtypes = [c_uint, c_long] gl.glPixelStorei.restype = None gl.glPolygonOffset.argtypes = [c_float, c_float] gl.glPolygonOffset.restype = None gl.glPopDebugGroup.argtypes = None gl.glPopDebugGroup.restype = None gl.glProgramBinary.argtypes = [c_uint32, c_uint, c_void_p, c_size_t] gl.glProgramBinary.restype = None gl.glProgramParameteri.argtypes = [c_uint32, c_uint, c_int32] gl.glProgramParameteri.restype = None gl.glProgramUniform1f.argtypes = [c_uint32, c_int32, c_float] gl.glProgramUniform1f.restype = None gl.glProgramUniform1fv.argtypes = [c_uint32, c_int32, c_size_t, POINTER(c_float)] gl.glProgramUniform1fv.restype = None gl.glProgramUniform1i.argtypes = [c_uint32, c_int32, c_int32] gl.glProgramUniform1i.restype = None gl.glProgramUniform1iv.argtypes = [c_uint32, c_int32, c_size_t, POINTER(c_int32)] gl.glProgramUniform1iv.restype = None gl.glProgramUniform1ui.argtypes = [c_uint32, c_int32, c_uint32] gl.glProgramUniform1ui.restype = None gl.glProgramUniform1uiv.argtypes = [c_uint32, c_int32, c_size_t, POINTER(c_uint32)] gl.glProgramUniform1uiv.restype = None gl.glProgramUniform2f.argtypes = [c_uint32, c_int32, c_float, c_float] gl.glProgramUniform2f.restype = None gl.glProgramUniform2fv.argtypes = [c_uint32, c_int32, c_size_t, POINTER(c_float)] gl.glProgramUniform2fv.restype = None gl.glProgramUniform2i.argtypes = [c_uint32, c_int32, c_int32, c_int32] gl.glProgramUniform2i.restype = None gl.glProgramUniform2iv.argtypes = [c_uint32, c_int32, c_size_t, POINTER(c_int32)] gl.glProgramUniform2iv.restype = None gl.glProgramUniform2ui.argtypes = [c_uint32, c_int32, c_uint32, c_uint32] gl.glProgramUniform2ui.restype = None gl.glProgramUniform2uiv.argtypes = [c_uint32, c_int32, c_size_t, POINTER(c_uint32)] gl.glProgramUniform2uiv.restype = None gl.glProgramUniform3f.argtypes = [c_uint32, c_int32, c_float, c_float, c_float] gl.glProgramUniform3f.restype = None gl.glProgramUniform3fv.argtypes = [c_uint32, c_int32, c_size_t, POINTER(c_float)] gl.glProgramUniform3fv.restype = None gl.glProgramUniform3i.argtypes = [c_uint32, c_int32, c_int32, c_int32, c_int32] gl.glProgramUniform3i.restype = None gl.glProgramUniform3iv.argtypes = [c_uint32, c_int32, c_size_t, POINTER(c_int32)] gl.glProgramUniform3iv.restype = None gl.glProgramUniform3ui.argtypes = [c_uint32, c_int32, c_uint32, c_uint32, c_uint32] gl.glProgramUniform3ui.restype = None gl.glProgramUniform3uiv.argtypes = [c_uint32, c_int32, c_size_t, POINTER(c_uint32)] gl.glProgramUniform3uiv.restype = None gl.glProgramUniform4f.argtypes = [c_uint32, c_int32, c_float, c_float, c_float, c_float] gl.glProgramUniform4f.restype = None gl.glProgramUniform4fv.argtypes = [c_uint32, c_int32, c_size_t, POINTER(c_float)] gl.glProgramUniform4fv.restype = None gl.glProgramUniform4i.argtypes = [c_uint32, c_int32, c_int32, c_int32, c_int32, c_int32] gl.glProgramUniform4i.restype = None gl.glProgramUniform4iv.argtypes = [c_uint32, c_int32, c_size_t, POINTER(c_int32)] gl.glProgramUniform4iv.restype = None gl.glProgramUniform4ui.argtypes = [c_uint32, c_int32, c_uint32, c_uint32, c_uint32, c_uint32] gl.glProgramUniform4ui.restype = None gl.glProgramUniform4uiv.argtypes = [c_uint32, c_int32, c_size_t, POINTER(c_uint32)] gl.glProgramUniform4uiv.restype = None gl.glProgramUniformMatrix2fv.argtypes = [c_uint32, c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glProgramUniformMatrix2fv.restype = None gl.glProgramUniformMatrix2x3fv.argtypes = [c_uint32, c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glProgramUniformMatrix2x3fv.restype = None gl.glProgramUniformMatrix2x4fv.argtypes = [c_uint32, c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glProgramUniformMatrix2x4fv.restype = None gl.glProgramUniformMatrix3fv.argtypes = [c_uint32, c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glProgramUniformMatrix3fv.restype = None gl.glProgramUniformMatrix3x2fv.argtypes = [c_uint32, c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glProgramUniformMatrix3x2fv.restype = None gl.glProgramUniformMatrix3x4fv.argtypes = [c_uint32, c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glProgramUniformMatrix3x4fv.restype = None gl.glProgramUniformMatrix4fv.argtypes = [c_uint32, c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glProgramUniformMatrix4fv.restype = None gl.glProgramUniformMatrix4x2fv.argtypes = [c_uint32, c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glProgramUniformMatrix4x2fv.restype = None gl.glProgramUniformMatrix4x3fv.argtypes = [c_uint32, c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glProgramUniformMatrix4x3fv.restype = None gl.glPushDebugGroup.argtypes = [c_uint, c_uint32, c_size_t, POINTER(c_char)] gl.glPushDebugGroup.restype = None gl.glReadBuffer.argtypes = [c_uint] gl.glReadBuffer.restype = None gl.glReadPixels.argtypes = [c_int, c_int, c_size_t, c_size_t, c_uint, c_uint, c_void_p] gl.glReadPixels.restype = None gl.glReleaseShaderCompiler.argtypes = None gl.glReleaseShaderCompiler.restype = None gl.glRenderbufferStorage.argtypes = [c_uint, c_uint, c_size_t, c_size_t] gl.glRenderbufferStorage.restype = None gl.glRenderbufferStorageMultisample.argtypes = [c_uint, c_size_t, c_uint, c_size_t, c_size_t] gl.glRenderbufferStorageMultisample.restype = None gl.glResumeTransformFeedback.argtypes = None gl.glResumeTransformFeedback.restype = None gl.glSampleCoverage.argtypes = [c_float, c_ubyte] gl.glSampleCoverage.restype = None gl.glSampleMaski.argtypes = [c_uint32, c_uint] gl.glSampleMaski.restype = None gl.glSamplerParameterIiv.argtypes = [c_uint32, c_uint, POINTER(c_int32)] gl.glSamplerParameterIiv.restype = None gl.glSamplerParameterIuiv.argtypes = [c_uint32, c_uint, POINTER(c_uint32)] gl.glSamplerParameterIuiv.restype = None gl.glSamplerParameterf.argtypes = [c_uint32, c_uint, c_float] gl.glSamplerParameterf.restype = None gl.glSamplerParameterfv.argtypes = [c_uint32, c_uint, POINTER(c_float)] gl.glSamplerParameterfv.restype = None gl.glSamplerParameteri.argtypes = [c_uint32, c_uint, c_int32] gl.glSamplerParameteri.restype = None gl.glSamplerParameteriv.argtypes = [c_uint32, c_uint, POINTER(c_int32)] gl.glSamplerParameteriv.restype = None gl.glScissor.argtypes = [c_int, c_int, c_size_t, c_size_t] gl.glScissor.restype = None gl.glShaderBinary.argtypes = [c_size_t, POINTER(c_uint32), c_uint, c_void_p, c_size_t] gl.glShaderBinary.restype = None gl.glShaderSource.argtypes = [c_uint32, c_size_t, POINTER(c_char_p), POINTER(c_int32)] gl.glShaderSource.restype = None gl.glStencilFunc.argtypes = [c_uint, c_int, c_uint] gl.glStencilFunc.restype = None gl.glStencilFuncSeparate.argtypes = [c_uint, c_uint, c_int, c_uint] gl.glStencilFuncSeparate.restype = None gl.glStencilMask.argtypes = [c_uint] gl.glStencilMask.restype = None gl.glStencilMaskSeparate.argtypes = [c_uint, c_uint] gl.glStencilMaskSeparate.restype = None gl.glStencilOp.argtypes = [c_uint, c_uint, c_uint] gl.glStencilOp.restype = None gl.glStencilOpSeparate.argtypes = [c_uint, c_uint, c_uint, c_uint] gl.glStencilOpSeparate.restype = None gl.glTexBuffer.argtypes = [c_uint, c_uint, c_uint32] gl.glTexBuffer.restype = None gl.glTexBufferRange.argtypes = [c_uint, c_uint, c_uint32, c_size_t, c_ssize_t] gl.glTexBufferRange.restype = None gl.glTexImage2D.argtypes = [c_uint, c_long, c_int, c_size_t, c_size_t, c_long, c_uint, c_uint, c_void_p] gl.glTexImage2D.restype = None gl.glTexParameterIiv.argtypes = [c_uint, c_uint, POINTER(c_int32)] gl.glTexParameterIiv.restype = None gl.glTexParameterIuiv.argtypes = [c_uint, c_uint, POINTER(c_uint32)] gl.glTexParameterIuiv.restype = None gl.glTexParameterf.argtypes = [c_uint, c_uint, c_float] gl.glTexParameterf.restype = None gl.glTexParameterfv.argtypes = [c_uint, c_uint, POINTER(c_float)] gl.glTexParameterfv.restype = None gl.glTexParameteri.argtypes = [c_uint, c_uint, c_long] gl.glTexParameteri.restype = None gl.glTexParameteriv.argtypes = [c_uint, c_uint, POINTER(c_long)] gl.glTexParameteriv.restype = None gl.glTexStorage2D.argtypes = [c_uint, c_size_t, c_uint, c_size_t, c_size_t] gl.glTexStorage2D.restype = None gl.glTexStorage2DMultisample.argtypes = [c_uint, c_size_t, c_uint, c_size_t, c_size_t, c_ubyte] gl.glTexStorage2DMultisample.restype = None gl.glTexStorage3D.argtypes = [c_uint, c_size_t, c_uint, c_size_t, c_size_t, c_size_t] gl.glTexStorage3D.restype = None gl.glTexStorage3DMultisample.argtypes = [c_uint, c_size_t, c_uint, c_size_t, c_size_t, c_size_t, c_ubyte] gl.glTexStorage3DMultisample.restype = None gl.glTexSubImage2D.argtypes = [c_uint, c_long, c_long, c_long, c_size_t, c_size_t, c_uint, c_uint, c_void_p] gl.glTexSubImage2D.restype = None gl.glTexSubImage3D.argtypes = [c_uint, c_long, c_long, c_long, c_long, c_size_t, c_size_t, c_size_t, c_uint, c_uint, c_void_p] gl.glTexSubImage3D.restype = None gl.glTransformFeedbackVaryings.argtypes = [c_uint32, c_size_t, POINTER(c_char_p), c_uint] gl.glTransformFeedbackVaryings.restype = None gl.glUniform1f.argtypes = [c_int32, c_float] gl.glUniform1f.restype = None gl.glUniform1fv.argtypes = [c_int32, c_size_t, POINTER(c_float)] gl.glUniform1fv.restype = None gl.glUniform1i.argtypes = [c_int32, c_int32] gl.glUniform1i.restype = None gl.glUniform1iv.argtypes = [c_int32, c_size_t, POINTER(c_int32)] gl.glUniform1iv.restype = None gl.glUniform1ui.argtypes = [c_int32, c_uint32] gl.glUniform1ui.restype = None gl.glUniform1uiv.argtypes = [c_int32, c_size_t, POINTER(c_uint32)] gl.glUniform1uiv.restype = None gl.glUniform2f.argtypes = [c_int32, c_float, c_float] gl.glUniform2f.restype = None gl.glUniform2fv.argtypes = [c_int32, c_size_t, POINTER(c_float)] gl.glUniform2fv.restype = None gl.glUniform2i.argtypes = [c_int32, c_int32, c_int32] gl.glUniform2i.restype = None gl.glUniform2iv.argtypes = [c_int32, c_size_t, POINTER(c_int32)] gl.glUniform2iv.restype = None gl.glUniform2ui.argtypes = [c_int32, c_uint32, c_uint32] gl.glUniform2ui.restype = None gl.glUniform2uiv.argtypes = [c_int32, c_size_t, POINTER(c_uint32)] gl.glUniform2uiv.restype = None gl.glUniform3f.argtypes = [c_int32, c_float, c_float, c_float] gl.glUniform3f.restype = None gl.glUniform3fv.argtypes = [c_int32, c_size_t, POINTER(c_float)] gl.glUniform3fv.restype = None gl.glUniform3i.argtypes = [c_int32, c_int32, c_int32, c_int32] gl.glUniform3i.restype = None gl.glUniform3iv.argtypes = [c_int32, c_size_t, POINTER(c_int32)] gl.glUniform3iv.restype = None gl.glUniform3ui.argtypes = [c_int32, c_uint32, c_uint32, c_uint32] gl.glUniform3ui.restype = None gl.glUniform3uiv.argtypes = [c_int32, c_size_t, POINTER(c_uint32)] gl.glUniform3uiv.restype = None gl.glUniform4f.argtypes = [c_int32, c_float, c_float, c_float, c_float] gl.glUniform4f.restype = None gl.glUniform4fv.argtypes = [c_int32, c_size_t, POINTER(c_float)] gl.glUniform4fv.restype = None gl.glUniform4i.argtypes = [c_int32, c_int32, c_int32, c_int32, c_int32] gl.glUniform4i.restype = None gl.glUniform4iv.argtypes = [c_int32, c_size_t, POINTER(c_int32)] gl.glUniform4iv.restype = None gl.glUniform4ui.argtypes = [c_int32, c_uint32, c_uint32, c_uint32, c_uint32] gl.glUniform4ui.restype = None gl.glUniform4uiv.argtypes = [c_int32, c_size_t, POINTER(c_uint32)] gl.glUniform4uiv.restype = None gl.glUniformBlockBinding.argtypes = [c_uint32, c_uint32, c_uint32] gl.glUniformBlockBinding.restype = None gl.glUniformMatrix2fv.argtypes = [c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glUniformMatrix2fv.restype = None gl.glUniformMatrix2x3fv.argtypes = [c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glUniformMatrix2x3fv.restype = None gl.glUniformMatrix2x4fv.argtypes = [c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glUniformMatrix2x4fv.restype = None gl.glUniformMatrix3fv.argtypes = [c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glUniformMatrix3fv.restype = None gl.glUniformMatrix3x2fv.argtypes = [c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glUniformMatrix3x2fv.restype = None gl.glUniformMatrix3x4fv.argtypes = [c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glUniformMatrix3x4fv.restype = None gl.glUniformMatrix4fv.argtypes = [c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glUniformMatrix4fv.restype = None gl.glUniformMatrix4x2fv.argtypes = [c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glUniformMatrix4x2fv.restype = None gl.glUniformMatrix4x3fv.argtypes = [c_int32, c_size_t, c_ubyte, POINTER(c_float)] gl.glUniformMatrix4x3fv.restype = None gl.glUnmapBuffer.argtypes = [c_uint] gl.glUnmapBuffer.restype = c_ubyte gl.glUseProgram.argtypes = [c_uint32] gl.glUseProgram.restype = None gl.glUseProgramStages.argtypes = [c_uint32, c_uint, c_uint32] gl.glUseProgramStages.restype = None gl.glValidateProgram.argtypes = [c_uint32] gl.glValidateProgram.restype = None gl.glValidateProgramPipeline.argtypes = [c_uint32] gl.glValidateProgramPipeline.restype = None gl.glVertexAttribBinding.argtypes = [c_uint32, c_uint32] gl.glVertexAttribBinding.restype = None gl.glVertexAttribDivisor.argtypes = [c_uint32, c_uint32] gl.glVertexAttribDivisor.restype = None gl.glVertexAttribFormat.argtypes = [c_uint32, c_int32, c_uint, c_ubyte, c_uint32] gl.glVertexAttribFormat.restype = None gl.glVertexAttribIFormat.argtypes = [c_uint32, c_int32, c_uint, c_uint32] gl.glVertexAttribIFormat.restype = None gl.glVertexAttribIPointer.argtypes = [c_uint32, c_int32, c_uint, c_size_t, c_void_p] gl.glVertexAttribIPointer.restype = None gl.glVertexAttribPointer.argtypes = [c_uint32, c_int32, c_uint, c_ubyte, c_size_t, c_void_p] gl.glVertexAttribPointer.restype = None gl.glVertexBindingDivisor.argtypes = [c_uint32, c_uint32] gl.glVertexBindingDivisor.restype = None gl.glViewport.argtypes = [c_int, c_int, c_size_t, c_size_t] gl.glViewport.restype = None ''' class PageAnalyzer(object): """ Analyzer for kernel page """ # page flags from kernel/include/uapi/linux/kernel-page-flags.h # flagList = [ 'KPF_LOCKED', #0# 'KPF_ERROR', #1# 'KPF_REFERENCED', #2# 'KPF_UPTODATE', #3# 'KPF_DIRTY', #4# 'KPF_LRU', #5# 'KPF_ACTIVE', #6# 'KPF_SLAB', #7# 'KPF_WRITEBACK', #8# 'KPF_RECLAIM', #9# 'KPF_BUDDY', #10# 'KPF_MMAP', #11# 'KPF_ANON', #12# 'KPF_SWAPCACHE', #13# 'KPF_SWAPBACKED', #14# 'KPF_COMPOUND_HEAD', #15# 'KPF_COMPOUND_TAIL', #16# 'KPF_HUGE', #17# 'KPF_UNEVICTABLE', #18# 'KPF_HWPOISON', #19# 'KPF_NOPAGE', #20# 'KPF_KSM', #21# 'KPF_THP', #22# 'KPF_BALLOON', #23# 'KPF_ZERO_PAGE', #24# 'KPF_IDLE' #25# ] @staticmethod def getPageInfo(pid, vaddr): try: if not pid: raise Exception('no pid') elif type(pid) is not list or len(pid) != 1: raise Exception('wrong pid') pids = SysMgr.getPids(pid[0], isThread=False) if not pid: raise Exception('no task') except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to recognize target", reason=True) sys.exit(0) for pid in sorted(pids): comm = SysMgr.getComm(pid) if not vaddr: PageAnalyzer.printMemoryArea( pid, comm=comm, showall=SysMgr.showAll) SysMgr.printPipe(oneLine) continue SysMgr.checkRootPerm() vrange = vaddr.split('-') rangeCnt = len(vrange) if rangeCnt > 2: SysMgr.printErr( "fail to recognize address, " "input address such as 102400 or 0x1234a-0x123ff") sys.exit(0) else: try: if vrange[0].startswith("0x"): addrs = long(vrange[0], base=16) addre = addrs else: addrs = long(vrange[0]) addre = addrs except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to recognize address, " "input address such as 0xabcd or 78901234") sys.exit(0) try: if rangeCnt == 2: if vrange[1].startswith("0x"): addre = long(vrange[1], base=16) else: addre = long(vrange[1]) offset = long(0) else: offset = SysMgr.pageSize if addrs > addre: SysMgr.printErr( "fail to recognize address, " "input bigger second address than first address") sys.exit(0) except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to recognize address, " "input address such as 0x1234-0x4444") sys.exit(0) SysMgr.printPipe( "\n[ TASK: %s(%s) ] [ AREA: %s ] [ HELP: %s ]" % \ (comm, pid, vaddr, "kernel/Documentation/vm/pagemap.txt")) PageAnalyzer.printMemoryArea(pid, addrs, addre) SysMgr.printPipe(twoLine) SysMgr.printPipe(( "{0:^18}|{1:^16}|{2:^9}|{3:^6}|{4:^6}|{5:^5}|" "{6:^8}|{7:^7}| {8}({9})\n{10}").\ format("VADDR", "PFN", "PRESENT", "SWAP", "FILE", "REF", "SDRT", "EXMAP", "FLAG", "FLAGS", oneLine)) for addr in range(addrs, addre + offset, SysMgr.pageSize): entry = PageAnalyzer.getPagemapEntry(pid, addr) pfn = PageAnalyzer.getPfn(entry) isPresent = PageAnalyzer.isPresent(entry) isSwapped = PageAnalyzer.isSwapped(entry) isSoftdirty = PageAnalyzer.isSoftdirty(entry) isExmapped = PageAnalyzer.isExmapped(entry) isFile = PageAnalyzer.isFilePage(entry) bflags = hex(PageAnalyzer.getPageFlags(pfn)).rstrip('L') sflags = PageAnalyzer.getFlagTypes(bflags) SysMgr.printPipe(( "{0:^18}|{1:^16}|{2:^9}|{3:^6}|{4:^6}|{5:^5}|"\ "{6:^8}|{7:^7}| {8}({9} )").format( hex(addr).rstrip('L'), hex(pfn).rstrip('L'), isPresent, isSwapped, isFile,PageAnalyzer.getPagecount(pfn), isSoftdirty, isExmapped, bflags, sflags)) SysMgr.printPipe("%s\n" % oneLine) @staticmethod def printMemoryArea( pid, start=-1, end=-1, comm=None, lastLine=False, showall=True): count = long(0) switch = long(0) fpath = '%s/%s/maps' % (SysMgr.procPath, pid) if start == end == -1 and not showall: printSummary = True else: printSummary = False # read all map info # try: # summary # if printSummary: buf = FileAnalyzer.getProcMapInfo(pid, saveAll=True) else: with open(fpath, 'r') as fd: buf = fd.readlines() except SystemExit: sys.exit(0) except: SysMgr.printOpenErr(fpath) sys.exit(0) if start == end == -1: if not comm: comm = SysMgr.getComm(pid) # get mem stat # convert = UtilMgr.convSize2Unit mlist = SysMgr.getMemStat(pid) vssIdx = ConfigMgr.STATM_TYPE.index("TOTAL") vss = convert(long(mlist[vssIdx]) << 12) rssIdx = ConfigMgr.STATM_TYPE.index("RSS") rss = convert(long(mlist[rssIdx]) << 12) SysMgr.printPipe( "\n[ TASK: %s(%s) ] [ VSS: %s ] [ RSS: %s ]" % \ (comm, pid, vss, rss)) start = hex(start) end = hex(end) all = hex(-1) # print menu # menuStr = '' if printSummary: menuList = \ ['AREA', 'PERM', '%8s' % 'OFFSET', '%6s' % 'DEV', '%7s' % 'INODE'] menuBuf = menuList else: menuList = ['AREA', 'PERM', 'OFFSET', 'DEV', '%12s' % 'INODE'] menuBuf = str(buf[-1]).split() for idx, value in enumerate(menuBuf): if idx < 5: if idx == 0: text = '{0:^38}'.format(menuList[idx]) else: text = menuList[idx] else: break value = ' ' * (len(value) - len(text) + 1) menuStr = '%s%s%s' % (menuStr, text, value) menuStr = '%s %s' % (menuStr, 'TARGET') SysMgr.printPipe('%s\n%s\n%s' % (twoLine, menuStr, oneLine)) # set text position # tstr = menuStr.split() pstr = tstr[1] # print summarized map info # if printSummary: for fname, info in sorted(buf.items(), key=lambda e: e[1]['vstart']): try: soffset = hex(info['vstart']).rstrip('L') eoffset = hex(info['vend']).rstrip('L') if not fname.startswith('/'): fname = '[%s]' % fname SysMgr.printPipe('%18s %18s %4s %8s %6s %7s %s' % \ (soffset, eoffset, info['perm'], info['offset'],\ info['devid'], info['inode'], fname)) except SystemExit: sys.exit(0) except: pass return # print all map info # for line in buf: tmplist = line.split() soffset, eoffset = tmplist[0].split('-') if start == end == all: switch = long(0) elif '-' in line: soffset = hex(long(soffset, base=16)) eoffset = hex(long(eoffset, base=16)) if (start >= soffset and start < eoffset): switch = 1 elif switch == 0: continue elif end < eoffset: break try: target = line[:-1].split() target[4] = '%12s' % target[4] if not soffset.startswith('0x'): soffset = '0x%s' % soffset if not eoffset.startswith('0x'): eoffset = '0x%s' % eoffset SysMgr.printPipe('%18s %18s %s' % \ (soffset, eoffset, ' '.join(target[1:]))) except SystemExit: sys.exit(0) except: pass count += 1 if switch == 1 and end <= eoffset: break if count == 0: SysMgr.printPipe('no involved memory area') elif lastLine: SysMgr.printPipe(oneLine) @staticmethod def getFlagTypes(flags): sflags = ' ' for idx, val in enumerate(PageAnalyzer.flagList): if ((long(flags, 16) & (1 << long(idx))) != 0): sflags = "%s%s|" % (sflags, val[4:]) return sflags[:-1] @staticmethod def readEntry(path, offset, size=8): with open(path, 'rb') as f: f.seek(offset, 0) try: return struct.unpack('Q', f.read(size))[0] except: SysMgr.printErr( "fail to read %s byte from %s of %s" % \ (size, offset, path)) sys.exit(0) @staticmethod def getPagemapEntry(pid, addr): maps_path = "{0}/{1}/pagemap".format(SysMgr.procPath, pid) if not os.path.isfile(maps_path): SysMgr.printErr("fail to find %s process" % pid) sys.exit(0) pageSize = os.sysconf("SC_PAGE_SIZE") pagemap_entry_size = 8 offset = long(addr / pageSize) * pagemap_entry_size return PageAnalyzer.readEntry(maps_path, offset) @staticmethod def getPfn(entry): return entry & 0x7FFFFFFFFFFFFF @staticmethod def isPresent(entry): return ((entry & (1 << 63)) != 0) @staticmethod def isSoftdirty(entry): return ((entry & (1 << 55)) != 0) @staticmethod def isExmapped(entry): return ((entry & (1 << 56)) != 0) @staticmethod def isSwapped(entry): return ((entry & (1 << 62)) != 0) @staticmethod def isFilePage(entry): return ((entry & (1 << 61)) != 0) @staticmethod def getPagecount(pfn): file_path = "%s/kpagecount" % SysMgr.procPath offset = pfn * 8 return PageAnalyzer.readEntry(file_path, offset) @staticmethod def getPageFlags(pfn): file_path = "%s/kpageflags" % SysMgr.procPath offset = pfn * 8 return PageAnalyzer.readEntry(file_path, offset) class FunctionAnalyzer(object): """ Analyzer for function profiling """ symStackIdxTable = [ 'CPU_TICK', 'STACK', 'PAGE_ALLOC', 'PAGE_FREE', 'BLK_READ', 'ARGUMENT', 'HEAP_EXPAND', 'HEAP_REDUCE', 'IGNORE', 'BLK_WRITE', 'LOCK_TRY', 'UNLOCK', 'SYSCALL', 'CUSTOM' ] def __init__(self, logFile): self.cpuEnabled = False self.memEnabled = False self.heapEnabled = False self.breadEnabled = False self.bwriteEnabled = False self.sigEnabled = False self.lockEnabled = False self.sysEnabled = False self.sort = 'sym' self.connObj = None self.finishTime = '0' self.lastTime = '0' self.totalTime = long(0) self.totalTick = long(0) self.prevTime = '0' self.prevTid = '0' self.lastCore = None self.coreCtx = {} self.nowCtx = None self.nowEvent = None self.savedEvent = None self.nestedEvent = None self.nowCnt = long(0) self.savedCnt = long(0) self.nestedCnt = long(0) self.nowArg = long(0) self.savedArg = long(0) self.nestedArg = long(0) self.duplicatedPos = long(0) self.periodicEventCnt = long(0) self.periodicContEventCnt = long(0) self.periodicEventInterval = long(0) self.heapExpEventCnt = long(0) self.heapExpSize = long(0) self.heapRedEventCnt = long(0) self.heapRedSize = long(0) self.pageAllocEventCnt = long(0) self.pageAllocCnt = long(0) self.pageFreeEventCnt = long(0) self.pageFreeCnt = long(0) self.pageUnknownFreeCnt = long(0) self.pageUsageCnt = long(0) self.blockRdEventCnt = long(0) self.blockRdUsageCnt = long(0) self.blockWrEventCnt = long(0) self.blockWrUsageCnt = long(0) self.lockTryEventCnt = long(0) self.unlockEventCnt = long(0) self.customCnt = long(0) self.customTotal = long(0) self.syscallCnt = long(0) self.customEventTable = {} self.ignoreTable = {} self.mapData = [] self.pageTable = {} self.oldPageTable = {} self.heapTable = {} self.oldHeapTable = {} self.posData = {} self.userSymData = {} self.userFileData = {} self.kerSymData = {} self.threadData = {} self.syscallTable = {} self.customCallData = [] self.lockCallData = [] self.sysCallData = [] self.userCallData = [] self.kernelCallData = [] ''' userCallData = kernelCallData = \ [pos, stack, event, eventCnt, eventArg] ''' self.init_threadData = \ {'comm': '?', 'tgid': '-'*5, 'target': False, 'cpuTick': long(0), 'die': False, 'new': False, 'nrPages': long(0), 'userPages': long(0), 'cachePages': long(0), 'kernelPages': long(0), 'heapSize': long(0), 'eventCnt': long(0), 'nrWrBlocks': long(0), 'customCnt': long(0), 'nrUnknownFreePages': long(0), 'nrKnownFreePages': long(0), 'nrRdBlocks': long(0), 'nrLockTry': long(0), 'nrUnlock': long(0), 'customTotal': long(0), 'nrSyscall': long(0), 'syscallTable': None, 'lastNrSyscall': long(-1)} self.init_posData = \ {'symbol': '', 'binary': '', 'origBin': '', 'offset': hex(0), 'posCnt': long(0), 'userPageCnt': long(0), 'cachePageCnt': long(0), 'kernelPageCnt': long(0), 'totalCnt': long(0), 'blockRdCnt': long(0), 'blockWrCnt': long(0), 'pageCnt': long(0), 'heapSize': long(0), 'unknownPageFreeCnt': long(0), 'src': '', 'customCnt': long(0), 'customTotal': long(0), 'lockTryCnt': long(0), 'unlockCnt': long(0), 'syscallCnt': long(0)} self.init_symData = \ {'pos': '', 'origBin': '', 'tickCnt': long(0), 'blockRdCnt': long(0), 'pageCnt': long(0), 'unknownPageFreeCnt': long(0), 'stack': None, 'symStack': None, 'userPageCnt': long(0), 'cachePageCnt': long(0), 'kernelPageCnt': long(0), 'heapSize': long(0), 'blockWrCnt': long(0), 'customCnt': long(0), 'customTotal': long(0), 'pagePair': None, 'pagePairCnt': long(0), 'pagePairTotal': float(0), 'pagePairMin': float(0), 'pagePairMax': float(0), 'pagePairAvr': float(0), 'pageRemainMin': float(0), 'pageRemainMax': float(0), 'pageRemainAvr': float(0), 'pageRemainTotal': float(0), 'lockTryCnt': long(0), 'unlockCnt': long(0), 'syscallCnt': long(0), 'totalTickCnt': long(0)} self.init_ctxData = \ {'nestedEvent': None, 'savedEvent': None, 'nowEvent': None, 'nested': long(0), 'recStat': False, 'nestedCnt': long(0), 'savedCnt': long(0), 'nowCnt': long(0), 'nestedArg': None, 'savedArg': None, 'prevMode': None, 'curMode': None, 'userLastPos': '', 'userStack': None, 'kerLastPos': '', 'kerStack': None, 'prevKerLastPos': '', 'prevKerStack': None, 'nowArg': None, 'prevTid': None, 'prevTime': None} self.init_pageLinkData = \ {'sym': '0', 'subStackAddr': long(0), 'ksym': '0', 'ksubStackAddr': long(0), 'type': '0', 'time': '0'} self.init_heapSegData = \ {'tid': '0', 'size': long(0), 'sym': '0', 'subStackAddr': long(0), 'ksym': '0', 'ksubStackAddr': long(0), 'time': float(0), 'core': '0'} self.init_pageData = \ {'tid': '0', 'page': '0', 'flags': '0', 'type': '0', 'time': '0'} self.init_glueData = \ {'count': long(0), 'size': long(0), 'timeList': None, 'valueList': None} self.init_subStackPageInfo = [0, 0, 0] # subStackPageInfo = [userPageCnt, cachePageCnt, kernelPageCnt] # read trace data # lines = TaskAnalyzer.readTraceData(logFile) # save trace data and stop analysis # if SysMgr.outputFile: SysMgr.saveTraceData(lines) sys.exit(0) # Check target thread setting # if not SysMgr.filterGroup: SysMgr.filterGroup.insert(0, '') self.target = [] else: self.target = SysMgr.filterGroup # Check root path # if SysMgr.userEnable: if SysMgr.rootPath == '': rootPath = '/' else: rootPath = SysMgr.rootPath SysMgr.printInfo( "use %s as sysroot path" % rootPath) # Register None pos # self.posData['0'] = dict(self.init_posData) # get process tree # SysMgr.getProcTreeInfo() # start parsing logs # SysMgr.totalLine = len(lines) SysMgr.printStat( 'start analyzing data... [ STOP(Ctrl+c) ]') self.parseLogs(lines, SysMgr.filterGroup) # Check whether data of target thread is collected or nothing # if not self.userCallData and \ not self.kernelCallData and \ len(self.target) > 0: if not self.target: SysMgr.printErr("no collected stack data") else: targetStr = ', '.join(self.target) SysMgr.printErr( "no collected stack related to '%s'" % targetStr) sys.exit(0) elif SysMgr.userEnable and \ len(self.userCallData) == 1 and \ self.userCallData[0][0] == '0': SysMgr.userEnable = False if self.target == []: SysMgr.printWarn( "no collected user stack data", True) else: targetStr = ', '.join(self.target) SysMgr.printWarn( "no collected user stack related to '%s'" % \ targetStr, True) # Get symbols from call address # SysMgr.printStat( 'start resolving symbols... [ STOP(Ctrl+c) ]') self.getSymbols() # Merge callstacks by symbol and address # SysMgr.printStat( 'start summarizing functions... [ STOP(Ctrl+c) ]') self.mergeStacks() def __del__(self): pass def handleHeapExpand(self, sym, ksym, stackAddr, kstackAddr, size, arg): addr = arg[0] time = arg[1] core = arg[2] tid = arg[3] self.userSymData[sym]['heapSize'] += size self.kerSymData[ksym]['heapSize'] += size self.heapTable.setdefault(addr, dict(self.init_heapSegData)) self.heapTable[addr]['size'] = size self.heapTable[addr]['sym'] = sym self.heapTable[addr]['ksym'] = ksym self.heapTable[addr]['subStackAddr'] = stackAddr self.heapTable[addr]['ksubStackAddr'] = kstackAddr self.heapTable[addr]['time'] = time self.heapTable[addr]['core'] = core self.heapTable[addr]['tid'] = tid def handleHeapReduce(self, size, arg): addr = arg[0] subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') heapExpIndex = FunctionAnalyzer.symStackIdxTable.index('HEAP_EXPAND') try: sym = self.heapTable[addr]['sym'] ksym = self.heapTable[addr]['ksym'] stackAddr = self.heapTable[addr]['subStackAddr'] kstackAddr = self.heapTable[addr]['ksubStackAddr'] self.userSymData[sym]['heapSize'] -= size self.kerSymData[ksym]['heapSize'] -= size except: SysMgr.printWarn( "fail to find heap segment to be freed") return # Set user stack list # if self.sort == 'sym': targetStack = self.userSymData[sym]['symStack'] elif self.sort == 'pos': targetStack = self.userSymData[sym]['stack'] # Find user stack of symbol allocated this segment # for val in targetStack: if id(val[subStackIndex]) == stackAddr: # Increase heap count of subStack # val[heapExpIndex] -= size break # Set kernel stack list # kernelTargetStack = self.kerSymData[ksym]['stack'] # Find kernel stack of symbol allocated this segment # for val in kernelTargetStack: if id(val[subStackIndex]) == kstackAddr: # Increase heap count of subStack # val[heapExpIndex] -= size break self.heapTable.pop(addr) def handlePageFree( self, sym, ksym, stackAddr, kstackAddr, pageFreeCnt, pageType, pfn, atime): subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') pageAllocIndex = FunctionAnalyzer.symStackIdxTable.index('PAGE_ALLOC') pageFreeIndex = FunctionAnalyzer.symStackIdxTable.index('PAGE_FREE') argIndex = FunctionAnalyzer.symStackIdxTable.index('ARGUMENT') for cnt in range(0, pageFreeCnt): pfnv = pfn + cnt subStackPageInfoIdx = long(0) try: # Decrease page count of symbol allocated page # # toDo: fix bug about wrong count of pos # allocSym = self.pageTable[pfnv]['sym'] allocStackAddr = self.pageTable[pfnv]['subStackAddr'] allocKernelSym = self.pageTable[pfnv]['ksym'] allocKernelStackAddr = self.pageTable[pfnv]['ksubStackAddr'] allocTime = self.pageTable[pfnv]['time'] self.pageUsageCnt -= 1 self.userSymData[allocSym]['pageCnt'] -= 1 self.kerSymData[allocKernelSym]['pageCnt'] -= 1 if pageType == 'USER': self.userSymData[allocSym]['userPageCnt'] -= 1 self.kerSymData[allocKernelSym]['userPageCnt'] -= 1 subStackPageInfoIdx = long(0) elif pageType == 'CACHE': self.userSymData[allocSym]['cachePageCnt'] -= 1 self.kerSymData[allocKernelSym]['cachePageCnt'] -= 1 subStackPageInfoIdx = 1 elif pageType == 'KERNEL': self.userSymData[allocSym]['kernelPageCnt'] -= 1 self.kerSymData[allocKernelSym]['kernelPageCnt'] -= 1 subStackPageInfoIdx = 2 # get page lifetime # lifeTime = float(atime) - float(allocTime) # Set user page lifetime # if lifeTime > self.userSymData[allocSym]['pagePairMax']: self.userSymData[allocSym]['pagePairMax'] = lifeTime if self.userSymData[allocSym]['pagePairMin'] == 0 or \ lifeTime < self.userSymData[allocSym]['pagePairMin']: self.userSymData[allocSym]['pagePairMin'] = lifeTime self.userSymData[allocSym]['pagePairTotal'] += lifeTime # Set kernel page lifetime # if lifeTime > self.kerSymData[allocKernelSym]['pagePairMax']: self.kerSymData[allocKernelSym]['pagePairMax'] = lifeTime if self.kerSymData[allocKernelSym]['pagePairMin'] == 0 or \ lifeTime < self.kerSymData[allocKernelSym]['pagePairMin']: self.kerSymData[allocKernelSym]['pagePairMin'] = lifeTime self.kerSymData[allocKernelSym]['pagePairTotal'] += lifeTime # Set user stack list # if self.sort == 'sym': targetStack = self.userSymData[allocSym]['symStack'] elif self.sort == 'pos': targetStack = self.userSymData[allocSym]['stack'] # Find user stack allocated this page # for val in targetStack: if id(val[subStackIndex]) != allocStackAddr: continue val[pageAllocIndex] -= 1 val[argIndex][subStackPageInfoIdx] -= 1 # Set user stack list to free this page # if self.sort == 'sym': subTargetStack = self.userSymData[sym]['symStack'] elif self.sort == 'pos': subTargetStack = self.userSymData[sym]['stack'] # Find user stack to free this page # for sval in subTargetStack: if id(sval[subStackIndex]) != stackAddr: continue if not self.userSymData[allocSym]['pagePair']: self.userSymData[allocSym]['pagePair'] = {} allocCall = '' freeCall = '' try: tsym = val[subStackIndex][0] allocCall = '%s [%s]' % \ (val[subStackIndex][0], self.userSymData[tsym]['origBin']) for usym in val[subStackIndex][1:]: allocCall = '%s <- %s [%s]' % \ (allocCall, usym, self.userSymData[sym]['origBin']) except: if allocCall == '': allocCall = 'None' try: freeCall = '%s [%s]' % \ (sym, self.userSymData[sym]['origBin']) for usym in sval[subStackIndex][1:]: freeCall = '%s <- %s[%s]' % \ (freeCall, usym, self.userSymData[sym]['origBin']) except: if freeCall == '': freeCall = 'None' pairId = '%s#%s' % (allocCall, freeCall) try: self.userSymData[allocSym]['pagePair'][pairId] except: self.userSymData[allocSym]['pagePair'][pairId] = \ dict(self.init_glueData) self.userSymData[allocSym]['pagePairCnt'] += 1 allocator = \ self.userSymData[allocSym]['pagePair'][pairId] allocator['size'] += 1 if not allocator['valueList']: allocator['valueList'] = {} try: allocator['valueList'][pageType] += 1 except: allocator['valueList'][pageType] = 1 break break # Set kernel stack list # kernelTargetStack = self.kerSymData[allocKernelSym]['stack'] # Find kernel stack allocated this page # for val in kernelTargetStack: if id(val[subStackIndex]) != allocKernelStackAddr: continue val[pageAllocIndex] -= 1 val[argIndex][subStackPageInfoIdx] -= 1 # Set kernel stack list to free this page # subTargetStack = self.kerSymData[ksym]['stack'] # Find kernel stack to free this page # for sval in subTargetStack: if id(sval[subStackIndex]) != kstackAddr: continue kernelData = self.kerSymData[allocKernelSym] if not kernelData['pagePair']: kernelData['pagePair'] = {} allocCall = '' freeCall = '' try: allocCall = '%s' % \ self.posData[val[subStackIndex][0]]['symbol'] for addr in val[subStackIndex][1:]: allocCall = '%s <- %s' % \ (allocCall, self.posData[addr]['symbol']) except: if allocCall == '': allocCall = 'None' try: freeCall = '%s' % ksym for addr in sval[subStackIndex]: freeCall = '%s <- %s' % \ (freeCall, self.posData[addr]['symbol']) except: if freeCall == '': freeCall = 'None' pairId = '%s#%s' % (allocCall, freeCall) try: kernelData['pagePair'][pairId] except: kernelData['pagePair'][pairId] = \ dict(self.init_glueData) self.kerSymData[allocKernelSym]['pagePairCnt'] += 1 allocator = kernelData['pagePair'][pairId] allocator['size'] += 1 if not allocator['valueList']: allocator['valueList'] = {} try: allocator['valueList'][pageType] += 1 except: allocator['valueList'][pageType] = 1 break break self.pageTable.pop(pfnv, None) except SystemExit: sys.exit(0) except: # this page is allocated before starting profile # self.pageUnknownFreeCnt += 1 self.userSymData[sym]['unknownPageFreeCnt'] += 1 self.kerSymData[ksym]['unknownPageFreeCnt'] += 1 # Set user stack list # if self.sort == 'sym': targetStack = self.userSymData[sym]['symStack'] elif self.sort == 'pos': targetStack = self.userSymData[sym]['stack'] # Find subStack allocated this page # for val in targetStack: if id(val[subStackIndex]) == stackAddr: val[pageFreeIndex] += 1 break # Set kernel stack list # kernelTargetStack = self.kerSymData[ksym]['stack'] # Find subStack allocated this page # for val in kernelTargetStack: if id(val[subStackIndex]) == kstackAddr: val[pageFreeIndex] += 1 break continue def handlePageAlloc( self, sym, ksym, stackAddr, kstackAddr, pageAllocCnt, pageType, pfn, atime): subStackPageInfoIdx = long(0) subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') pageAllocIndex = FunctionAnalyzer.symStackIdxTable.index('PAGE_ALLOC') argIndex = FunctionAnalyzer.symStackIdxTable.index('ARGUMENT') # Increase counts of page to be allocated # self.userSymData[sym]['pageCnt'] += pageAllocCnt self.kerSymData[ksym]['pageCnt'] += pageAllocCnt if pageType == 'USER': self.userSymData[sym]['userPageCnt'] += pageAllocCnt self.kerSymData[ksym]['userPageCnt'] += pageAllocCnt subStackPageInfoIdx = long(0) elif pageType == 'CACHE': self.userSymData[sym]['cachePageCnt'] += pageAllocCnt self.kerSymData[ksym]['cachePageCnt'] += pageAllocCnt subStackPageInfoIdx = 1 elif pageType == 'KERNEL': self.userSymData[sym]['kernelPageCnt'] += pageAllocCnt self.kerSymData[ksym]['kernelPageCnt'] += pageAllocCnt subStackPageInfoIdx = 2 # Set user stack list # if self.sort == 'sym': targetStack = self.userSymData[sym]['symStack'] elif self.sort == 'pos': targetStack = self.userSymData[sym]['stack'] # Find user stack of symbol allocated this page # for val in targetStack: if id(val[subStackIndex]) == stackAddr: # Increase page count of subStack # val[argIndex][subStackPageInfoIdx] += pageAllocCnt break # Set kernel stack list # kernelTargetStack = self.kerSymData[ksym]['stack'] # Find kernel stack of symbol allocated this page # for val in kernelTargetStack: if id(val[subStackIndex]) == kstackAddr: # Increase page count of subStack # val[argIndex][subStackPageInfoIdx] += pageAllocCnt break # Make PTE in page table # for cnt in range(0, pageAllocCnt): pfnv = pfn + cnt subStackPageInfoIdx = long(0) try: # Check whether this page is already allocated # allocSym = self.pageTable[pfnv]['sym'] allocStackAddr = self.pageTable[pfnv]['subStackAddr'] allocKernelSym = self.pageTable[pfnv]['ksym'] allocKernelStackAddr = self.pageTable[pfnv]['ksubStackAddr'] # Decrease counts of page already allocated but no free log # self.pageUsageCnt -= 1 self.userSymData[allocSym]['pageCnt'] -= 1 self.kerSymData[allocKernelSym]['pageCnt'] -= 1 origPageType = self.pageTable[pfnv]['type'] if origPageType == 'USER': self.userSymData[allocSym]['userPageCnt'] -= 1 self.kerSymData[allocKernelSym]['userPageCnt'] -= 1 subStackPageInfoIdx = long(0) elif origPageType == 'CACHE': self.userSymData[allocSym]['cachePageCnt'] -= 1 self.kerSymData[allocKernelSym]['cachePageCnt'] -= 1 subStackPageInfoIdx = 1 elif origPageType == 'KERNEL': self.userSymData[allocSym]['kernelPageCnt'] -= 1 self.kerSymData[allocKernelSym]['kernelPageCnt'] -= 1 subStackPageInfoIdx = 2 # Set user stack list # if self.sort == 'sym': targetStack = self.userSymData[allocSym]['symStack'] elif self.sort == 'pos': targetStack = self.userSymData[allocSym]['stack'] # Find user stack of symbol allocated this page # for val in targetStack: if id(val[subStackIndex]) == allocStackAddr: # Decrease allocated page count of substack # val[pageAllocIndex] -= 1 val[argIndex][subStackPageInfoIdx] -= 1 break # Set kernel stack list # kernelTargetStack = self.kerSymData[allocKernelSym]['stack'] # Find kernel stack of symbol allocated this page # for val in kernelTargetStack: if id(val[subStackIndex]) == allocKernelStackAddr: # Decrease allocated page count of substack # val[pageAllocIndex] -= 1 val[argIndex][subStackPageInfoIdx] -= 1 break except SystemExit: sys.exit(0) except: self.pageTable[pfnv] = dict(self.init_pageLinkData) self.pageTable[pfnv]['sym'] = sym self.pageTable[pfnv]['ksym'] = ksym self.pageTable[pfnv]['type'] = pageType self.pageTable[pfnv]['subStackAddr'] = stackAddr self.pageTable[pfnv]['ksubStackAddr'] = kstackAddr self.pageTable[pfnv]['time'] = atime def mergeStacks(self): sym = '' ksym = '' stackAddr = long(0) kstackAddr = long(0) lineCnt = -1 lastIdx = len(self.userCallData) # Backup page table used previously and Initialize it # self.oldPageTable = self.pageTable self.pageTable = {} # Backup heap table used previously and Initialize it # self.oldHeapTable = self.heapTable self.heapTable = {} subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') argIndex = FunctionAnalyzer.symStackIdxTable.index('ARGUMENT') # Merge call data by symbol or address # for val in self.userCallData: lineCnt += 1 UtilMgr.printProgress(lineCnt, lastIdx - 1) pos = val[0] stack = val[1] event = val[2] eventCnt = val[3] arg = val[4] ''' Do not merge PAGE_FREE count because it will be merged with unknownPageFreeCnt ''' if event == 'PAGE_FREE': savedEventCnt = eventCnt eventCnt = long(0) try: eventIndex = FunctionAnalyzer.symStackIdxTable.index(event) except: eventIndex = FunctionAnalyzer.symStackIdxTable.index('IGNORE') kernelPos = self.kernelCallData[lineCnt][0] kernelStack = self.kernelCallData[lineCnt][1] subStackPageInfo = list(self.init_subStackPageInfo) targetStack = [] kernelTargetStack = [] # Resolve user symbol # try: # No symbol related to last pos # if self.posData[pos]['symbol'] == '': self.posData[pos]['symbol'] = pos sym = pos else: sym = self.posData[pos]['symbol'] except: continue # Resolve kernel symbol # try: # No symbol related to last pos # if self.posData[kernelPos]['symbol'] == '': self.posData[kernelPos]['symbol'] = kernelPos ksym = kernelPos else: ksym = self.posData[kernelPos]['symbol'] except: continue # Make user file table of last pos in stack # try: path = self.posData[pos]['binary'] self.userFileData[path] except: self.userFileData[path] = dict(self.init_symData) # Make user symbol table of last pos in stack # try: self.userSymData[sym] except: self.userSymData[sym] = dict(self.init_symData) self.userSymData[sym]['stack'] = [] self.userSymData[sym]['symStack'] = [] self.userSymData[sym]['pos'] = pos self.userSymData[sym]['origBin'] = self.posData[pos]['origBin'] # Make kenel symbol table of last pos in stack # try: self.kerSymData[ksym] except: self.kerSymData[ksym] = dict(self.init_symData) self.kerSymData[ksym]['stack'] = [] self.kerSymData[ksym]['pos'] = kernelPos # Set target user stack # if self.sort == 'sym': tempSymStack = [] # Make temporary symbol stack to merge stacks by symbol # for addr in stack: tempSym = self.posData[addr]['symbol'] # Ignore this function if there is no symbol # if not SysMgr.showAll and \ self.posData[addr]['origBin'] == '??' and \ (tempSym == addr or \ tempSym == self.posData[addr]['offset'] or \ addr == '00c0ffee'): continue # No symbol data # if tempSym == '': if self.posData[addr]['origBin'] == '??': tempSym = '%x' % \ long(self.posData[addr]['pos'], 16) else: tempSym = '%x' % \ long(self.posData[addr]['offset'], 16) try: self.userSymData[tempSym] except: self.userSymData[tempSym] = dict(self.init_symData) self.userSymData[tempSym]['stack'] = [] self.userSymData[tempSym]['symStack'] = [] self.userSymData[tempSym]['pos'] = addr self.userSymData[tempSym]['origBin'] = \ self.posData[addr]['origBin'] tempSymStack.append(tempSym) # Switch input stack to symbol stack # stack = tempSymStack targetStack = self.userSymData[sym]['symStack'] elif self.sort == 'pos': targetStack = self.userSymData[sym]['stack'] # First user stack related to this symbol # if not targetStack: tempList = [0] * len(FunctionAnalyzer.symStackIdxTable) tempList[eventIndex] = eventCnt tempList[subStackIndex] = stack tempList[argIndex] = list(subStackPageInfo) targetStack.append(tempList) stackAddr = id(stack) else: found = False # Find same stack by pos in stack list # for stackInfo in targetStack: stackSet = set(stack) subStackSet = set(stackInfo[subStackIndex]) # Found same stack # if not list(stackSet - subStackSet) and \ not list(subStackSet - stackSet): found = True stackInfo[eventIndex] += eventCnt stackAddr = id(stackInfo[subStackIndex]) break # New stack related to this symbol # if found == False: tempList = [0] * len(FunctionAnalyzer.symStackIdxTable) tempList[eventIndex] = eventCnt tempList[subStackIndex] = stack tempList[argIndex] = list(subStackPageInfo) targetStack.append(tempList) stackAddr = id(stack) # Set target kernel stack # kernelTargetStack = self.kerSymData[ksym]['stack'] # First stack related to this symbol # if not kernelTargetStack: tempList = [0] * len(FunctionAnalyzer.symStackIdxTable) tempList[eventIndex] = eventCnt tempList[subStackIndex] = kernelStack tempList[argIndex] = list(subStackPageInfo) kernelTargetStack.append(tempList) kstackAddr = id(kernelStack) else: found = False for stackInfo in kernelTargetStack: kerStackSet = set(kernelStack) kerSubStackSet = set(stackInfo[subStackIndex]) # Found same stack in stack list # if not list(kerStackSet - kerSubStackSet) and \ not list(kerSubStackSet - kerStackSet): found = True stackInfo[eventIndex] += eventCnt kstackAddr = id(stackInfo[subStackIndex]) break # New stack related to this symbol # if found == False: tempList = [0] * len(FunctionAnalyzer.symStackIdxTable) tempList[eventIndex] = eventCnt tempList[subStackIndex] = kernelStack tempList[argIndex] = list(subStackPageInfo) kernelTargetStack.append(tempList) kstackAddr = id(kernelStack) # Recover PAGE_FREE count to merge with unknownPageFreeCnt # if event == 'PAGE_FREE': eventCnt = savedEventCnt # memory allocation event # if event == 'PAGE_ALLOC': pageType = arg[0] pfn = arg[1] atime = arg[2] self.handlePageAlloc( sym, ksym, stackAddr, kstackAddr, eventCnt, pageType, pfn, atime) # memory free event # elif event == 'PAGE_FREE': pageType = arg[0] pfn = arg[1] atime = arg[2] self.handlePageFree( sym, ksym, stackAddr, kstackAddr, eventCnt, pageType, pfn, atime) # heap expand event # elif event == 'HEAP_EXPAND': self.handleHeapExpand( sym, ksym, stackAddr, kstackAddr, eventCnt, arg) # heap expand event # elif event == 'HEAP_REDUCE': self.handleHeapReduce(eventCnt, arg) # block read event # elif event == 'BLK_READ': self.userSymData[sym]['blockRdCnt'] += eventCnt self.kerSymData[ksym]['blockRdCnt'] += eventCnt # block write event # elif event == 'BLK_WRITE': self.userSymData[sym]['blockWrCnt'] += eventCnt self.kerSymData[ksym]['blockWrCnt'] += eventCnt # lock try event # elif event == 'LOCK_TRY': self.userSymData[sym]['lockTryCnt'] += eventCnt self.kerSymData[ksym]['lockTryCnt'] += eventCnt self.userFileData[path]['lockTryCnt'] += eventCnt # unlock event # elif event == 'UNLOCK': self.userSymData[sym]['unlockCnt'] += eventCnt self.kerSymData[ksym]['unlockCnt'] += eventCnt self.userFileData[path]['unlockCnt'] += eventCnt # periodic event such as CPU tick # elif event == 'CPU_TICK': self.userSymData[sym]['tickCnt'] += 1 self.kerSymData[ksym]['tickCnt'] += 1 self.userFileData[path]['tickCnt'] += 1 # syscall event # elif event == 'SYSCALL': self.userSymData[sym]['syscallCnt'] += 1 self.kerSymData[ksym]['syscallCnt'] += 1 self.userFileData[path]['syscallCnt'] += 1 # periodic event such as CPU tick # elif event == 'CUSTOM': if eventCnt > 0: self.userSymData[sym]['customTotal'] += 1 self.kerSymData[ksym]['customTotal'] += 1 self.userFileData[path]['customTotal'] += 1 self.userSymData[sym]['customCnt'] += eventCnt self.kerSymData[ksym]['customCnt'] += eventCnt self.userFileData[path]['customCnt'] += eventCnt # etc event # elif event == 'IGNORE': try: self.ignoreTable[arg]['ignCnt'] += 1 except: self.ignoreTable[arg] = {'ignCnt': long(1)} else: SysMgr.printWarn("fail to recognize event %s" % event) UtilMgr.deleteProgress() # Print summary about ignored events # self.printIgnoreEvents() def printIgnoreEvents(self): for idx, value in self.ignoreTable.items(): SysMgr.printWarn( "ignore %s event %d times" % (idx, value['ignCnt'])) def getBinFromServer(self, remoteObj, src, des): if not remoteObj or remoteObj == 'NONE': SysMgr.printErr( "wrong remote address, " "input in the format {IP:PORT}") sys.exit(0) # set download command # req = 'DOWNLOAD:%s@%s' % (src, des) # get connection with server # self.connObj = NetworkMgr.getServerConn() if not self.connObj: return None # request download command # NetworkMgr.requestCmd(self.connObj, req) def getSymbols(self): binPath = '' offsetList = [] curIdx = long(0) nrNoFile = long(0) lastIdx = len(self.posData) # Set alarm handler to handle hanged addr2line # signal.signal(signal.SIGALRM, SysMgr.timerHandler) # Get symbols and source pos # for idx, value in sorted(self.posData.items(), key=lambda e: e[1]['binary'], reverse=True): curIdx += 1 UtilMgr.printProgress(curIdx, lastIdx) # Handle thumbcode # if idx == '00c0ffee': value['binary'] = '??' value['origBin'] = '??' value['symbol'] = 'ThumbCode' continue # Handle address # if value['binary'] == '': # user pos without offset # if value['symbol'] == '' or value['symbol'] == '??': # toDo: find binary path and symbol of pos # value['binary'] = '??' value['origBin'] = '??' value['symbol'] = idx continue # Get symbols from address list of previous binary # if binPath != value['binary']: if binPath != '': # Get symbols # if self.getFileSymbolInfo(binPath, offsetList) == -1: nrNoFile += 1 offsetList = [] if value['offset'] == hex(0): offsetList.append(idx) else: offsetList.append(value['offset']) # Set new binPath to find symbol from address # binPath = value['binary'] # Get binary from server # if not os.path.isfile(binPath) and \ SysMgr.remoteServObj: self.getBinFromServer( SysMgr.remoteServObj, value['origBin'], binPath) # add address to offsetList # else: # not relocatable binary # if value['offset'] == hex(0): offsetList.append(idx) # relocatable binary # else: offsetList.append(value['offset']) # Get symbols and source path from last binary # if binPath != '': if self.getFileSymbolInfo(binPath, offsetList) == -1: nrNoFile += 1 UtilMgr.deleteProgress() if nrNoFile > 0: SysMgr.printWarn( "fail to find total %s binaries to analyze functions" % \ nrNoFile, True) def getFileSymbolInfo(self, binPath, offsetList, onlyFunc=True): def _updateSymbol(addr, symbol, src, relocated): if not addr: return -1 elif symbol == '??': symbol = addr # Check whether the file is relocatable or not # if not relocated: try: savedSymbol = self.posData[addr]['symbol'] except: return -1 ''' Check whether saved symbol found by previous addr2line is right # ''' if not savedSymbol or savedSymbol == '' or \ savedSymbol == addr or savedSymbol[0] == '$': self.posData[addr]['symbol'] = symbol if SysMgr.showAll: self.posData[addr]['src'] = src else: fileIdx = src.rfind('/') if fileIdx >= 0: self.posData[addr]['src'] = src[fileIdx + 1:] return inBinArea = False for idx, value in sorted(self.posData.items(), key=lambda e: e[1]['binary'], reverse=True): if value['binary'] == binPath: inBinArea = True if value['offset'] == addr: savedSymbol = self.posData[idx]['symbol'] if not savedSymbol or \ savedSymbol == '' or \ savedSymbol == addr or \ savedSymbol[0] == '$': self.posData[idx]['symbol'] = symbol if SysMgr.showAll: self.posData[idx]['src'] = src else: fileIdx = src.rfind('/') if fileIdx >= 0: self.posData[idx]['src'] = \ src[fileIdx + 1:] break elif inBinArea: break # Recognize binary type # relocated = ElfAnalyzer.isRelocFile(binPath) # No file exist # if not os.path.isfile(binPath): for addr in offsetList: try: if not relocated: self.posData[addr]['symbol'] = 'NoFile' self.posData[addr]['src'] = 'NoFile' else: for idx, value in sorted(self.posData.items(), key=lambda e: e[1]['binary'], reverse=True): if value['binary'] == binPath and \ value['offset'] == hex(long(addr, 16)): self.posData[idx]['symbol'] = 'NoFile' self.posData[idx]['src'] = 'NoFile' break except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to find address %s" % addr) return -1 # check user-mode enabled # if not SysMgr.userEnable: return None # check addr2line path # if not 'ADDR2LINE' in SysMgr.environList: try: symbolList = list() binObj = ElfAnalyzer.getObject(binPath) if not binObj: return None for offset in offsetList: symbol, size = binObj.getSymbolByOffset( offset, onlyFunc=onlyFunc) symbolList.append('??') _updateSymbol(offset, symbol, '??', relocated) except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to get symbol from %s" % binPath, True) return None # get system addr2line path # addr2linePath = UtilMgr.which('addr2line') if not addr2linePath: SysMgr.printErr(( "fail to find addr2line to analyze user-level functions, " "use -q option with ADDR2LINE to set binary path")) sys.exit(0) SysMgr.printInfo( "use %s as addr2line path" % ', '.join(addr2linePath)) else: for path in SysMgr.environList['ADDR2LINE']: if not os.path.isfile(path): SysMgr.printErr( "fail to find %s to use addr2line" % path) sys.exit(0) # get subprocess object # subprocess = SysMgr.getPkg('subprocess') if not subprocess: sys.exit(0) for path in SysMgr.environList['ADDR2LINE']: # Set addr2line command # args = [path, "-C", "-f", "-a", "-e", binPath] # Limit the number of arguments to be passed because of ARG_MAX # # ARG_MAX = $(getconf PAGE_SIZE)*32 = 131072 # listLen = len(offsetList) maxArgLine = 256 offset = long(0) timeout = 10 # Get symbol by address of every maxArgLine elements in list # while offset < listLen: # Launch addr2line # try: workload = offsetList[offset:offset+maxArgLine-1] proc = subprocess.Popen(args + workload, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to execute %s to pick symbols from binary" % \ path) sys.exit(0) # Increase offset count in address list # offset += maxArgLine try: # Set alarm to handle hanged addr2line # signal.alarm(timeout) # Wait for addr2line to finish its job # proc.wait() # Cancel alarm after addr2line respond # signal.alarm(0) except SystemExit: sys.exit(0) except: SysMgr.printWarn( 'no response of addr2line for %s' % binPath) continue while 1: # Get return of addr2line # addr = proc.stdout.readline().decode().replace('\n', '')[2:] try: addr = hex(long(addr, 16)).rstrip('L') except SystemExit: sys.exit(0) except: pass symbol = proc.stdout.readline().decode().replace('\n', '') src = proc.stdout.readline().decode().replace('\n', '') err = proc.stderr.readline().decode().replace('\n', '') if len(err) > 0: SysMgr.printWarn(err[err.find(':') + 2:]) if _updateSymbol(addr, symbol, src, relocated): break def initStacks(self): self.nowCtx['userLastPos'] = '0' self.nowCtx['userStack'] = [] self.nowCtx['kerLastPos'] = '0' self.nowCtx['kerStack'] = [] def swapEvents(self): tempEvent = self.nowCtx['nowEvent'] self.nowCtx['nowEvent'] = self.nowCtx['savedEvent'] self.nowCtx['savedEvent'] = tempEvent tempCnt = self.nowCtx['nowCnt'] self.nowCtx['nowCnt'] = self.nowCtx['savedCnt'] self.nowCtx['savedCnt'] = tempCnt tempArg = self.nowCtx['nowArg'] self.nowCtx['nowArg'] = self.nowCtx['savedArg'] self.nowCtx['savedArg'] = tempArg def saveFullStack( self, kernelPos, kernelStack, userPos, userStack, targetEvent, targetCnt, targetArg): # Save userstack # self.userCallData.append( [userPos, userStack, targetEvent, targetCnt, targetArg]) # Save kernelstack # self.kernelCallData.append( [kernelPos, kernelStack, targetEvent, targetCnt, targetArg]) # Save custom event stacks # if SysMgr.showAll and targetEvent == 'CUSTOM': self.customCallData.append( [targetArg[0], targetArg[1], self.userCallData[-1], self.kernelCallData[-1]]) # Save lock event stacks # if SysMgr.showAll and \ (targetEvent == 'LOCK_TRY' or targetEvent == 'UNLOCK'): self.lockCallData.append( [targetArg[0], targetArg[1:], self.userCallData[-1], self.kernelCallData[-1]]) # Save syscall event stacks # if SysMgr.showAll and targetEvent == 'SYSCALL': self.sysCallData.append( [targetArg[0], targetArg[1:], self.userCallData[-1], self.kernelCallData[-1]]) def saveEventStack(self, targetEvent, targetCnt, targetArg): kpos = self.nowCtx['kerLastPos'] upos = self.nowCtx['userLastPos'] # save count data # if targetEvent == 'CPU_TICK': self.periodicEventCnt += 1 elif targetEvent == 'PAGE_ALLOC': self.pageAllocEventCnt += 1 self.pageAllocCnt += targetCnt self.pageUsageCnt += targetCnt self.posData[kpos]['pageCnt'] += targetCnt self.posData[upos]['pageCnt'] += targetCnt pageType = targetArg[0] pfn = targetArg[1] time = targetArg[2] targetArg = [pageType, pfn, time] elif targetEvent == 'PAGE_FREE': self.pageFreeEventCnt += 1 self.pageFreeCnt += targetCnt pageType = targetArg[0] pfn = targetArg[1] time = targetArg[2] targetArg = [pageType, pfn, time] elif targetEvent == 'BLK_READ': self.blockRdEventCnt += 1 self.blockRdUsageCnt += targetCnt self.posData[kpos]['blockRdCnt'] += targetCnt self.posData[upos]['blockRdCnt'] += targetCnt elif targetEvent == 'BLK_WRITE': self.blockWrEventCnt += 1 self.blockWrUsageCnt += targetCnt self.posData[kpos]['blockWrCnt'] += targetCnt self.posData[upos]['blockWrCnt'] += targetCnt elif targetEvent == 'LOCK_TRY': self.lockTryEventCnt += 1 self.posData[kpos]['lockTryCnt'] += targetCnt self.posData[upos]['lockTryCnt'] += targetCnt elif targetEvent == 'UNLOCK': self.unlockEventCnt += 1 self.posData[kpos]['unlockCnt'] += targetCnt self.posData[upos]['unlockCnt'] += targetCnt elif targetEvent == 'HEAP_EXPAND': self.heapExpEventCnt += 1 self.heapExpSize += targetCnt self.posData[kpos]['heapSize'] += targetCnt self.posData[upos]['heapSize'] += targetCnt elif targetEvent == 'HEAP_REDUCE': self.posData[kpos]['heapSize'] += targetCnt self.posData[upos]['heapSize'] += targetCnt elif targetEvent == 'SYSCALL': nrSyscall = targetArg[0] self.syscallCnt += 1 try: self.syscallTable[nrSyscall] += 0 except: self.syscallTable[nrSyscall] = 1 self.posData[kpos]['syscallCnt'] += targetCnt self.posData[upos]['syscallCnt'] += targetCnt elif targetEvent == 'CUSTOM': if targetCnt > 0: self.customTotal += 1 self.customCnt += targetCnt self.posData[kpos]['customTotal'] += 1 self.posData[upos]['customTotal'] += 1 self.posData[kpos]['customCnt'] += targetCnt self.posData[upos]['customCnt'] += targetCnt else: pass # cut stacks by depth # if SysMgr.funcDepth > 0: ksize = len(self.nowCtx['kerStack']) if ksize >= SysMgr.funcDepth: self.nowCtx['kerLastPos'] = \ self.nowCtx['kerStack'][-SysMgr.funcDepth] self.nowCtx['kerStack'] = \ self.nowCtx['kerStack'][-SysMgr.funcDepth + 1:] usize = len(self.nowCtx['userStack']) if usize >= SysMgr.funcDepth: self.nowCtx['userLastPos'] = \ self.nowCtx['userStack'][-SysMgr.funcDepth] self.nowCtx['userStack'] = \ self.nowCtx['userStack'][-SysMgr.funcDepth + 1:] if SysMgr.funcDepth == 1: self.nowCtx['kerStack'] = [] self.nowCtx['userStack'] = [] try: # save both stacks # self.saveFullStack( self.nowCtx['kerLastPos'], self.nowCtx['kerStack'], self.nowCtx['userLastPos'], self.nowCtx['userStack'], targetEvent, targetCnt, targetArg) except: SysMgr.printErr( "fail to save full stacks", True) sys.exit(0) def saveCallStack(self): nowCtx = self.nowCtx # stack of kernel thread # if not SysMgr.userRecordEnable or \ nowCtx['prevMode'] != nowCtx['curMode'] == 'kernel': if not nowCtx['userStack'] and \ len(nowCtx['kerStack']) > 0: # Set userLastPos to None # self.nowCtx['userLastPos'] = '0' self.nowCtx['userStack'].append('0') if not nowCtx['kerStack'] and \ len(nowCtx['userStack']) > 0: # Set kerLastPos to None # self.nowCtx['kerLastPos'] = '0' self.nowCtx['kerStack'].append('0') # complicated situation ;( # elif nowCtx['prevMode'] == nowCtx['curMode']: # previous user stack loss or nested interval # if nowCtx['curMode'] == 'kernel': # nested interval # if nowCtx['nowEvent'] == 'CPU_TICK': # Backup kernel stack # self.nowCtx['prevKerLastPos'] = nowCtx['kerLastPos'] self.nowCtx['prevKerStack'] = nowCtx['kerStack'] # Initialize both stacks # self.initStacks() # previous user stack loss # else: # Set userLastPos to None # self.nowCtx['userLastPos'] = '0' self.nowCtx['userStack'].append('0') # nested interval # elif nowCtx['curMode'] == 'user': ''' CORE/0 EVENT0 CORE/0 CORE/0 CORE/0 EVENT1 CORE/0 CORE/0 EVENT2 CORE/0 CORE/0 CORE/0 ''' # Swap nowEvent and savedEvent # self.swapEvents() ''' Save both stacks of previous event before starting to record new kernel stack # ''' if (len(nowCtx['userStack']) > 0 and \ nowCtx['userLastPos'] != '') and \ (len(nowCtx['kerStack']) > 0 and \ nowCtx['kerLastPos'] != ''): # Remove pc in each stacks # del self.nowCtx['kerStack'][0], self.nowCtx['userStack'][0] # Check whether there is nested event or not # if nowCtx['nested'] > 0: ''' CORE/0 EVENT0 CORE/0 CORE/0 CORE/0 EVENT1 CORE/0 EVENT2 CORE/0 CORE/0 CORE/0 CORE/0 ''' targetEvent = nowCtx['nestedEvent'] targetCnt = nowCtx['nestedCnt'] targetArg = nowCtx['nestedArg'] # Swap nowEvent and savedEvent # self.swapEvents() else: targetEvent = nowCtx['savedEvent'] targetCnt = nowCtx['savedCnt'] targetArg = nowCtx['savedArg'] # Save full stack of previous event # self.saveEventStack( targetEvent, targetCnt, targetArg) # Recover previous kernel stack after handling nested event # if nowCtx['prevMode'] == nowCtx['curMode'] == 'user' and \ nowCtx['prevKerLastPos'] != '0': self.nowCtx['kerLastPos'] = nowCtx['prevKerLastPos'] self.nowCtx['kerStack'] = nowCtx['prevKerStack'] self.nowCtx['prevKerLastPos'] = '0' self.nowCtx['prevKerStack'] = [] else: self.nowCtx['kerLastPos'] = '' self.nowCtx['kerStack'] = [] # Initialize user stack # self.nowCtx['userLastPos'] = '' self.nowCtx['userStack'] = [] self.nowCtx['nestedEvent'] = '' self.nowCtx['nestedCnt'] = long(0) # On stack recording switch # self.nowCtx['recStat'] = True def savePosData(self, pos, path, offset): if self.nowCtx['nested'] > 0: targetEvent = self.nowCtx['savedEvent'] else: targetEvent = self.nowCtx['nowEvent'] # Register pos # try: self.posData[pos] if path and path[0] == '/' and \ path != self.posData[pos]['origBin']: self.duplicatedPos += 1 ''' SysMgr.printWarn( "duplicated address %s in both '%s' and '%s'" % \ (pos, path, self.posData[pos]['origBin'])) ''' except: self.posData[pos] = dict(self.init_posData) # user mode # if self.nowCtx['curMode'] == 'user': # Set path # if path: self.posData[pos]['origBin'] = path self.posData[pos]['binary'] = \ SysMgr.rootPath + path self.posData[pos]['binary'] = \ os.path.normpath(self.posData[pos]['binary']) # Set offset # if offset: if ElfAnalyzer.isRelocFile(path): self.posData[pos]['offset'] = offset # Save pos # if not self.nowCtx['userStack']: self.nowCtx['userLastPos'] = pos if targetEvent == 'CPU_TICK': self.posData[pos]['posCnt'] += 1 elif targetEvent == 'LOCK_TRY': self.posData[pos]['lockTryCnt'] += 1 elif targetEvent == 'UNLOCK': self.posData[pos]['unlockCnt'] += 1 self.nowCtx['userStack'].append(pos) # kernel mode # elif self.nowCtx['curMode'] == 'kernel': # Save pos # if not self.nowCtx['kerStack']: self.nowCtx['kerLastPos'] = pos if targetEvent == 'CPU_TICK': self.posData[pos]['posCnt'] += 1 elif targetEvent == 'LOCK_TRY': self.posData[pos]['lockTryCnt'] += 1 elif targetEvent == 'UNLOCK': self.posData[pos]['unlockCnt'] += 1 # Skip pos because it is usercall or no symbol # elif not SysMgr.showAll and not path: return self.posData[pos]['symbol'] = path self.nowCtx['kerStack'].append(pos) # wrong mode # else: SysMgr.printWarn( 'wrong current mode %s' % self.nowCtx['curMode']) # Increase total call count # if self.nowEvent == 'CPU_TICK': self.posData[pos]['totalCnt'] += 1 def allocHeapSeg(self, tid, size): try: self.heapTable[tid + '-ready']['size'] = size self.heapTable[tid + '-ready']['tid'] = tid self.threadData[tid]['heapSize'] -= size SysMgr.printWarn( 'overwrite heap segment of %s(%s) at %s' % \ (self.threadData[tid]['comm'], tid, SysMgr.dbgEventLine)) except: self.heapTable[tid + '-ready'] = dict(self.init_heapSegData) self.heapTable[tid + '-ready']['size'] = size self.heapTable[tid + '-ready']['tid'] = tid def freeHeapSeg(self, addr): try: self.heapRedEventCnt += 1 self.heapRedSize += self.heapTable[addr]['size'] # get tid # try: tid = self.heapTable[addr]['tid'] except: return self.threadData[tid]['heapSize'] -= \ self.heapTable[addr]['size'] self.heapTable.pop(addr, None) except: SysMgr.printWarn( 'fail to free heap segment %s of %s(%s) at %s' % \ (addr, self.threadData[tid]['comm'], tid, SysMgr.dbgEventLine)) def setHeapSegAddr(self, tid, addr): try: self.heapTable[addr] = dict(self.heapTable['%s-ready' % tid]) del self.heapTable['%s-ready' % tid] except: SysMgr.printWarn( 'fail to set address of heap segment %s of %s(%s) at %s' % \ (addr, self.threadData[tid]['comm'], tid, SysMgr.dbgEventLine)) def parseLogs(self, lines, desc): curIdx = long(0) lastIdx = len(lines) # make custom event table # if SysMgr.customCmd: for cmd in SysMgr.customCmd: cmd = cmd.split(':') if len(cmd) > 1: self.customEventTable[cmd[0]] = cmd[1] else: self.customEventTable[cmd[0]] = None # make kernel event table # if SysMgr.kernelCmd: for cmd in SysMgr.kernelCmd: cmd = cmd.split(':') self.customEventTable[cmd[0]+'_enter'] = None self.customEventTable[cmd[0]+'_exit'] = None # make user event table # if SysMgr.userCmd: for cmd in SysMgr.userCmd: cmd = cmd.split(':') self.customEventTable[cmd[0]+'_enter'] = None self.customEventTable[cmd[0]+'_exit'] = None # get pid filter by comm in advance # plist = {} if SysMgr.groupProcEnable: for key, value in self.getTargetList(lines).items(): for item in desc: if item in value['comm']: plist[value['tgid']] = long(0) # start parsing logs # for liter in lines: curIdx += 1 SysMgr.logSize += len(liter) SysMgr.curLine += 1 SysMgr.dbgEventLine += 1 ret = self.parseEventLog(liter, desc, plist) UtilMgr.printProgress(curIdx, lastIdx) # Skip lines before first meaningful event # if not self.lastCore: continue # Set context of current core # self.nowCtx = self.coreCtx[self.lastCore] # Save full stack to callData table # if ret is True: self.saveCallStack() elif ret is False: ''' Ignore this log because its not event or stack info related to target thread # ''' self.nowCtx['recStat'] = False continue # Save pos into target stack # elif self.nowCtx['recStat']: # decode return value # (pos, path, offset) = ret self.savePosData(pos, path, offset) # update finish time # if self.finishTime == '0': self.finishTime = self.lastTime UtilMgr.deleteProgress() # Save stack of last events per core # for idx in list(self.coreCtx.keys()): self.lastCore = idx self.nowCtx = self.coreCtx[idx] # Recover previous mode # if SysMgr.userEnable: self.nowCtx['prevMode'] = 'user' self.nowCtx['curMode'] = 'kernel' self.saveEventParam('IGNORE', 0, 0) self.nowCtx['nested'] -= 1 self.saveCallStack() if self.duplicatedPos > 0: SysMgr.printWarn( "found %d addresses duplicated" % self.duplicatedPos) def getCustomEventValue(self, func, args, cond): if not cond: return 1 # set condition # if '>' in cond: condVal = cond[cond.find('>') + 1:] condOp = '>' condStr = cond[:cond.find('>')] elif '<' in cond: condVal = cond[cond.find('<') + 1:] condOp = '<' condStr = cond[:cond.find('<')] elif '==' in cond: condVal = cond[cond.find('==') + 2:] condOp = '==' condStr = cond[:cond.find('==')] else: condStr = cond condOp = None condVal = None m = re.match(r'^.+%s=(?P\S+)' % condStr, args) if not m: return 0 d = m.groupdict() value = d['value'] if not condOp and value: try: return long(value) except: return 0 elif condOp == '>': try: if long(value) > long(condVal): return long(value) except: pass return 0 elif condOp == '<': try: if long(value) < long(condVal): return long(value) except: pass return 0 elif condOp == '==': if value == condVal: return 1 else: return 0 else: return 0 def saveEventParam(self, event, count, arg): # save context # self.nowCtx['nestedEvent'] = self.nowCtx['savedEvent'] self.nowCtx['savedEvent'] = self.nowCtx['nowEvent'] self.nowCtx['nowEvent'] = event self.nowCtx['nestedCnt'] = self.nowCtx['savedCnt'] self.nowCtx['savedCnt'] = self.nowCtx['nowCnt'] self.nowCtx['nowCnt'] = count self.nowCtx['nestedArg'] = self.nowCtx['savedArg'] self.nowCtx['savedArg'] = self.nowCtx['nowArg'] self.nowCtx['nowArg'] = arg self.nowCtx['nested'] += 1 if self.nowCtx['nested'] > 2: #self.printDbgInfo() SysMgr.printWarn(( "fail to analyze stack data "\ "because of corruption (overflow) at %s line\n"\ "\tso report results may differ from actual") % \ SysMgr.dbgEventLine, True) def printDbgInfo(self): data = self.nowCtx print('[%s]' % self.lastCore, '(now) %s/%s/%s' % \ (data['nowEvent'], data['nowCnt'], data['nowArg']), '(saved) %s/%s/%s' % \ (data['savedEvent'], data['savedCnt'], data['savedArg']), '(nested) %s/%s/%s' % \ (data['nestedEvent'], data['nestedCnt'], data['nestedArg']), '(user) %s/%s' % \ (data['userLastPos'], len(data['userStack'])), '(kernel) %s/%s' % \ (data['kerLastPos'], len(data['kerStack'])), '(backup) %s/%s' % \ (data['prevKerLastPos'], len(data['prevKerStack'])), 'at %s' % SysMgr.dbgEventLine) def parseEventInfo(self, tid, func, args, time, core): # check core filter # if SysMgr.perCoreList and \ long(core) not in SysMgr.perCoreList and \ func[0] != '<': self.saveEventParam('IGNORE', 0, func[:-1]) return False # check fixed event list # if len(self.customEventTable) > 0 and \ (func[:-1] in self.customEventTable or \ len([event for event in self.customEventTable \ if event.endswith(func[:-1])]) > 0): isFixedEvent = False else: isFixedEvent = True # CPU tick event # # toDo: find shorter periodic event for sampling # if isFixedEvent and func == "hrtimer_start:": if 'tick_sched_timer' in args: self.cpuEnabled = True self.saveEventParam('CPU_TICK', 1, 0) else: self.saveEventParam('IGNORE', 0, func[:-1]) return False # memory allocation event # elif isFixedEvent and func == "mm_page_alloc:": m = re.match(( r'^\s*page=\s*(?P\S+)\s+pfn=(?P[0-9]+)\s+' r'order=(?P[0-9]+)\s+migratetype=(?P[0-9]+)\s+' r'gfp_flags=(?P\S+)'), args) if m: d = m.groupdict() # check whether it is huge page # if d['page'] == '(null)': page = 'huge' else: page = d['page'] pfn = long(d['pfn']) flags = d['flags'] pageCnt = pow(2, long(d['order'])) # Increase page count of thread # self.threadData[tid]['nrPages'] += pageCnt # Increase page counts of thread # pageType = None if 'NOFS' in flags or \ 'GFP_WRITE' in flags or \ '0x1000000' in flags: pageType = 'CACHE' self.threadData[tid]['cachePages'] += pageCnt elif 'USER' in flags: pageType = 'USER' self.threadData[tid]['userPages'] += pageCnt else: pageType = 'KERNEL' self.threadData[tid]['kernelPages'] += pageCnt # Make PTE in page table # for cnt in range(0, pageCnt): pfnv = pfn + cnt try: ''' Decrease page count of it's owner \ because this page was already allocated but no free log ''' ownerTid = self.pageTable[pfnv]['tid'] self.threadData[ownerTid]['nrPages'] -= 1 origPageType = self.pageTable[pfnv]['type'] if origPageType == 'USER': self.threadData[ownerTid]['userPages'] -= 1 elif origPageType == 'CACHE': self.threadData[ownerTid]['cachePages'] -= 1 elif origPageType == 'KERNEL': self.threadData[ownerTid]['kernelPages'] -= 1 except: self.pageTable[pfnv] = dict(self.init_pageData) self.pageTable[pfnv]['tid'] = tid self.pageTable[pfnv]['page'] = page self.pageTable[pfnv]['flags'] = flags self.pageTable[pfnv]['type'] = pageType self.pageTable[pfnv]['time'] = time self.memEnabled = True self.saveEventParam( 'PAGE_ALLOC', pageCnt, [pageType, pfn, time]) else: self.saveEventParam('IGNORE', 0, func[:-1]) SysMgr.printWarn( "fail to recognize event %s at %d" % \ (func[:-1], SysMgr.dbgEventLine)) return False # memory free event # elif isFixedEvent and \ (func == "mm_page_free:" or func == "mm_page_free_direct:"): m = re.match((r'^\s*page=(?P\S+)\s+pfn=(?P[0-9]+)\s+' r'order=(?P[0-9]+)'), args) if m: d = m.groupdict() page = d['page'] pfn = long(d['pfn']) pageCnt = pow(2, long(d['order'])) # Update page table # origPageType = None for cnt in range(0, pageCnt): pfnv = pfn + cnt try: owner = self.pageTable[pfnv]['tid'] origPageType = self.pageTable[pfnv]['type'] self.threadData[owner]['nrPages'] -= 1 if origPageType == 'CACHE': self.threadData[owner]['cachePages'] -= 1 elif origPageType == 'USER': self.threadData[owner]['userPages'] -= 1 elif origPageType == 'KERNEL': self.threadData[owner]['kernelPages'] -= 1 self.threadData[tid]['nrKnownFreePages'] += 1 self.pageTable.pop(pfnv) except: # this page was allocated before starting profile # self.threadData[tid]['nrUnknownFreePages'] += 1 continue self.memEnabled = True self.saveEventParam( 'PAGE_FREE', pageCnt, [origPageType, pfn, time]) return False SysMgr.printWarn("fail to recognize event %s at %d" % \ (func[:-1], SysMgr.dbgEventLine)) self.saveEventParam('IGNORE', 0, func[:-1]) return False # syscall / heap / lock events # elif isFixedEvent and func == "sys_enter:": m = re.match(r'^\s*NR (?P[0-9]+) (?P.+)', args) if m: b = m.groupdict() nr = b['nr'] self.threadData[tid]['lastNrSyscall'] = long(nr) # syscall event # if SysMgr.sysEnable: self.sysEnabled = True nrSyscall = long(b['nr']) syscallList = SysMgr.syscallList if not syscallList or nrSyscall in syscallList: args = b['args'][1:-1] self.threadData[tid]['nrSyscall'] += 1 # set syscall table # if not self.threadData[tid]['syscallTable']: self.threadData[tid]['syscallTable'] = {} try: self.threadData[tid]['syscallTable'][nrSyscall] += 1 except: self.threadData[tid]['syscallTable'][nrSyscall] = 1 self.saveEventParam( 'SYSCALL', 1, [nrSyscall, args, time, core, tid]) return False # heap increasement event # elif long(b['nr']) == ConfigMgr.getMmapId(): self.heapEnabled = True try: size = long(b['args'].split(',')[1], 16) # just brk call to check data segment address # if size == 0: pass self.threadData[tid]['heapSize'] += size except: self.saveEventParam('IGNORE', 0, func[:-1]) return False # make heap segment tid-ready # self.allocHeapSeg(tid, size) self.saveEventParam('IGNORE', 0, func[:-1]) return False # heap decreasement event # elif long(b['nr']) == ConfigMgr.sysList.index('sys_munmap'): self.heapEnabled = True try: addr = long(b['args'][1:].split(',')[0], 16) size = self.heapTable[addr]['size'] # remove heap segment # self.freeHeapSeg(addr) self.saveEventParam( 'HEAP_REDUCE', size, [addr, time, core, tid]) return False except: pass # lock event # elif long(b['nr']) == ConfigMgr.sysList.index('sys_futex'): n = re.match(( r'^\s*(?P\S+), (?P\S+), ' r'(?P\S+), (?P\S+),'), b['args']) if n: l = n.groupdict() FUTEX_CMD_MASK = ~(128|256) # FUTEX_PRIVATE_FLAG: 128, FUTEX_CLOCK_REALTIME: 256 # maskedOp = long(l['op'], base=16) & FUTEX_CMD_MASK addr = l['uaddr'][1:] flist = ConfigMgr.FUTEX_TYPE try: event = flist[maskedOp] except: event = 'LOCK' # try to lock # if maskedOp == flist.index("FUTEX_LOCK_PI") or \ maskedOp == flist.index("FUTEX_TRYLOCK_PI"): self.lockEnabled = True self.threadData[tid]['nrLockTry'] += 1 self.saveEventParam( 'LOCK_TRY', 1, [event, addr, time, core, tid]) return False # wait # elif maskedOp == flist.index("FUTEX_WAIT") or \ maskedOp == flist.index("FUTEX_WAIT_REQUEUE_PI") or \ maskedOp == flist.index("FUTEX_WAIT_BITSET"): self.lockEnabled = True self.threadData[tid]['nrLockTry'] += 1 self.saveEventParam( 'LOCK_TRY', 1, [event, addr, time, core, tid]) return False # try to unlock # elif maskedOp == flist.index("FUTEX_UNLOCK_PI"): self.lockEnabled = True self.threadData[tid]['nrUnlock'] += 1 self.saveEventParam( 'UNLOCK', 1, [event, addr, time, core, tid]) return False else: SysMgr.printWarn( "fail to recognize event %s at %d" % \ (func[:-1], SysMgr.dbgEventLine)) self.saveEventParam('IGNORE', 0, func[:-1]) return False # syscall / heap events # elif isFixedEvent and func == "sys_exit:": m = re.match(r'^\s*NR (?P\S+) = (?P.+)', args) if m: b = m.groupdict() nr = long(b['nr']) # handle wrong syscall number # if nr < 0: if self.threadData[tid]['lastNrSyscall'] >= 0: nr = self.threadData[tid]['lastNrSyscall'] # heap increasement event # if nr == ConfigMgr.getMmapId(): self.heapEnabled = True addr = long(b['ret']) # rename heap segment from tid-ready to addr # self.setHeapSegAddr(tid, addr) try: size = self.heapTable[addr]['size'] self.saveEventParam( 'HEAP_EXPAND', size, [addr, time, core, tid]) return False except: pass # heap decreasement event # elif nr == ConfigMgr.sysList.index('sys_brk'): self.heapEnabled = True addr = long(b['ret']) try: pid = self.threadData[tid]['tgid'] if pid.startswith('-'): pid = SysMgr.savedProcTree[tid] self.threadData[pid] except: pid = tid try: self.threadData[pid]['lastBrk'] if addr > self.threadData[pid]['lastBrk']: size = addr - self.threadData[pid]['lastBrk'] self.threadData[pid]['heapSize'] += size self.saveEventParam( 'HEAP_EXPAND', size, [addr, time, core, tid]) return False except: self.threadData[pid]['lastBrk'] = addr else: SysMgr.printWarn( "fail to recognize event %s at %d" % \ (func[:-1], SysMgr.dbgEventLine)) self.saveEventParam('IGNORE', 0, func[:-1]) return False # block request event # elif isFixedEvent and func == "block_bio_queue:": m = re.match(( r'^\s*(?P[0-9]+),(?P[0-9]+)\s*(?P\S+)\s*' r'(?P
\S+)\s+\+\s+(?P[0-9]+)'), args) if m: b = m.groupdict() opt = b['operation'] if opt[0] == 'R': self.breadEnabled = True blockRdCnt = long(b['size']) self.threadData[tid]['nrRdBlocks'] += blockRdCnt self.saveEventParam('BLK_READ', blockRdCnt, 0) return False elif opt == 'WS': self.bwriteEnabled = True blockWrCnt = long(b['size']) self.threadData[tid]['nrWrBlocks'] += blockWrCnt self.saveEventParam('BLK_WRITE', blockWrCnt, 0) return False SysMgr.printWarn("fail to recognize event %s at %d" % \ (func[:-1], SysMgr.dbgEventLine)) self.saveEventParam('IGNORE', 0, func[:-1]) return False # block write request event # elif isFixedEvent and func == "writeback_dirty_page:": m = re.match((r'^\s*bdi\s+(?P[0-9]+):(?P[0-9]+):\s*' r'ino=(?P\S+)\s+index=(?P\S+)'), args) if m: b = m.groupdict() self.bwriteEnabled = True self.threadData[tid]['nrWrBlocks'] += 8 self.saveEventParam('BLK_WRITE', 8, 0) return False self.saveEventParam('IGNORE', 0, func[:-1]) return False # block write request event # elif isFixedEvent and func == "wbc_writepage:": m = re.match((r'^\s*bdi\s+(?P[0-9]+):(?P[0-9]+):\s*' r'towrt=(?P\S+)\s+skip=(?P\S+)'), args) if m: d = m.groupdict() if d['skip'] == '0': self.bwriteEnabled = True self.threadData[tid]['nrWrBlocks'] += 8 self.saveEventParam('BLK_WRITE', 8, 0) return False self.saveEventParam('IGNORE', 0, func[:-1]) return False # segmentation fault generation event # elif isFixedEvent and func == "signal_generate:": m = re.match((r'^\s*sig=(?P[0-9]+) errno=(?P[0-9]+) ' r'code=(?P.*) comm=(?P.*) ' r'pid=(?P[0-9]+)'), args) if m: b = m.groupdict() if b['sig'] == str(signal.SIGSEGV): self.sigEnabled = True self.saveEventParam('SIGSEGV_GEN', 0, 0) return False SysMgr.printWarn("fail to recognize event %s at %d" % \ (func[:-1], SysMgr.dbgEventLine)) self.saveEventParam('IGNORE', 0, func[:-1]) return False elif isFixedEvent and func == "signal_deliver:": m = re.match(( r'^\s*sig=(?P[0-9]+) errno=(?P[0-9]+) code=(?P.*) ' r'sa_handler=(?P.*) sa_flags=(?P.*)'), args) if m: b = m.groupdict() if b['sig'] == str(signal.SIGSEGV): self.sigEnabled = True self.saveEventParam('SIGSEGV_DLV', 0, 0) else: self.saveEventParam('IGNORE', 0, func[:-1]) else: self.saveEventParam('IGNORE', 0, func[:-1]) return False elif isFixedEvent and func == "locks_get_lock_context:": m = re.match(( r'^\s*dev=(?P.+)\s+ino=(?P.+)'\ r'\s+type=(?P.+)\s+ctx=(?P.+)'), args) if m: d = m.groupdict() if d['type'] == 'F_UNLCK': self.saveEventParam('IGNORE', 0, func[:-1]) else: self.lockEnabled = True self.threadData[tid]['nrLockTry'] += 1 self.saveEventParam( 'LOCK_TRY', 1, ['FLOCK', d['ino'], time, core, tid]) else: self.saveEventParam('IGNORE', 0, func[:-1]) return False # Start to record user stack # elif func == " 0: self.threadData[tid]['customTotal'] += customCnt self.saveEventParam( 'CUSTOM', customCnt, [func[:-1], [args, time, core, tid]]) except: self.saveEventParam('IGNORE', 0, func[:-1]) return False # Ignore event # else: self.saveEventParam('IGNORE', 0, func[:-1]) return False def getTargetList(self, tlist): threadData = {} for liter in tlist: m = SysMgr.getTraceItem(liter) if m: d = m.groupdict() # Make thread entity # thread = d['thread'] try: threadData[thread]['comm'] = d['comm'] except: threadData[thread] = dict() threadData[thread]['comm'] = d['comm'] # set tgid # try: threadData[thread]['tgid'] = d['tgid'] except: try: threadData[thread]['tgid'] = \ SysMgr.savedProcTree[thread] except: pass return threadData def parseEventLog(self, string, desc, plist=[]): m = SysMgr.getTraceItem(string) if m: d = m.groupdict() self.lastTime = d['time'] if SysMgr.countEnable and \ SysMgr.repeatCount * SysMgr.intervalEnable <= \ float(d['time']) - float(SysMgr.startTime): self.lastCore = None return False # Make thread entity # thread = d['thread'] try: self.threadData[thread]['comm'] = d['comm'] except: self.threadData[thread] = dict(self.init_threadData) self.threadData[thread]['comm'] = d['comm'] # set tgid # try: if d['tgid'].startswith('-'): raise Exception('no tgid') self.threadData[thread]['tgid'] = d['tgid'] except: try: self.threadData[thread]['tgid'] = \ SysMgr.savedProcTree[thread] except: pass # increase event count # self.threadData[thread]['eventCnt'] += 1 # set current core # self.lastCore = d['core'] # Make core entity # try: self.coreCtx[self.lastCore] except: self.coreCtx[self.lastCore] = dict(self.init_ctxData) self.coreCtx[self.lastCore]['userStack'] = [] self.coreCtx[self.lastCore]['kerStack'] = [] self.coreCtx[self.lastCore]['prevKerStack'] = [] # set context of current core # self.nowCtx = self.coreCtx[self.lastCore] # Check core filter # if SysMgr.perCoreList and \ long(d['core']) not in SysMgr.perCoreList and \ not d['func'].startswith("tracing_mark_write") and \ d['func'] != '0:': pass # Calculate a total of CPU usage # elif d['func'] == "hrtimer_start:" and \ 'tick_sched_timer' in d['etc']: self.totalTick += 1 self.threadData[thread]['cpuTick'] += 1 # Set global interval # if self.nowCtx['prevTid']: diff = float(d['time']) - float(self.nowCtx['prevTime']) self.periodicEventInterval += diff self.periodicContEventCnt += 1 self.nowCtx['prevTid'] = thread self.nowCtx['prevTime'] = d['time'] # Set max core to calculate CPU usage of thread # if SysMgr.maxCore < long(d['core']): SysMgr.maxCore = long(d['core']) # Mark die flag of thread that is not able to be profiled # elif d['func'] == "sched_process_exit:": m = re.match( r'^\s*comm=(?P.*)\s+pid=(?P[0-9]+)', d['etc']) if m: p = m.groupdict() pid = p['pid'] try: self.threadData[pid] except: self.threadData[pid] = dict(self.init_threadData) self.threadData[pid]['comm'] = p['comm'] self.threadData[pid]['die'] = True # Make thread name # elif d['func'] == "sched_process_fork:": m = re.match(( r'^\s*comm=(?P.*)\s+pid=(?P[0-9]+)\s+'\ r'child_comm=(?P.*)\s+'\ r'child_pid=(?P[0-9]+)'), d['etc']) if m: p = m.groupdict() cpid = p['child_pid'] ccomm = p['child_comm'] try: self.threadData[cpid] except: self.threadData[cpid] = dict(self.init_threadData) self.threadData[cpid]['comm'] = ccomm self.threadData[cpid]['new'] = True # Make thread name # elif d['func'] == "task_newtask:": m = re.match( r'^\s*pid=(?P[0-9]+)\s+comm=(?P\S+)', d['etc']) if m: p = m.groupdict() pid = p['pid'] try: self.threadData[pid] except: self.threadData[pid] = dict(self.init_threadData) self.threadData[pid]['comm'] = p['comm'] self.threadData[pid]['new'] = True # Save user event # elif d['func'].startswith("tracing_mark_write") or \ d['func'] == '0:': m = re.match(r'^.+EVENT_(?P\S+)', d['etc']) if m: gd = m.groupdict() EventAnalyzer.addEvent(d['time'], gd['event']) if gd['event'] == 'STOP': self.finishTime = float(d['time']) # Return False because no stack data with this event # return False # apply filter # if SysMgr.isExceptTarget( thread, self.threadData, plist=plist): return False else: self.threadData[thread]['target'] = True return self.parseEventInfo( thread, d['func'], d['etc'], d['time'], d['core']) # Parse call stack # else: # exist path, offset, pos # m = re.match(( r' => (?P.+)\[\+0x(?P.\S*)\] '\ r'\<(?P.\S+)\>'), string) if m: d = m.groupdict() return (d['pos'], d['path'], hex(long(d['offset'], 16))) # exist only pos # pos = string.find('=> <') if pos > -1: return (string[pos+5:len(string)-2], None, None) # no user stack tracing supported # if '??' in string: if SysMgr.userEnable and SysMgr.userEnableWarn: SysMgr.printWarn(( "enable CONFIG_USER_STACKTRACE_SUPPORT kernel option " "if it is not enabled"), True) SysMgr.userEnableWarn = False return ('0', None, None) # exist symbol, pos # m = re.match(r' => (?P.+) \<(?P.\S+)\>', string) if m: d = m.groupdict() return (d['pos'], d['symbol'], None) # garbage log # return False def getBinInfo(self, addr): for data in self.mapData: if long(data['startAddr'], 16) <= long(addr, 16) and \ long(data['endAddr'], 16) >= long(addr, 16): if ElfAnalyzer.isRelocFile(data['binName']): # Return full path and offset in mapping table # return SysMgr.rootPath + data['binName'],\ hex(long(addr, 16) - long(data['startAddr'], 16)) else: return SysMgr.rootPath + data['binName'],\ hex(long(addr, 16)) SysMgr.printWarn( "fail to get the binary info of %s in mapping table" % addr) def printSyscallSummary(self): # no effective syscall event # if self.syscallCnt == 0: return convertNum = UtilMgr.convNum SysMgr.clearPrint() SysMgr.printPipe( '[Function Syscall Info] [Cnt: %s]' % \ convertNum(self.syscallCnt)) SysMgr.printPipe(twoLine) SysMgr.printPipe( '{0:>16}({1:>7}/{2:>7}) {3:>30}({4:>3}) {5:>12}'.format( "Name", "TID", "PID", "Syscall", "SID", "Count")) SysMgr.printPipe(twoLine) outputCnt = long(0) for key, value in sorted(self.threadData.items(), key=lambda e: e[1]['nrSyscall'], reverse=True): threadInfo = '' syscallInfo = '' if key[0:2] == '0[': continue try: if len(value['syscallTable']) > 0: threadInfo = "%16s(%7s/%7s)" % \ (value['comm'], key, value['tgid']) else: continue except: continue for sysId, val in sorted(value['syscallTable'].items(), key=lambda e: e[1], reverse=True): if val == 0: continue try: syscall = ConfigMgr.sysList[sysId][4:] except: SysMgr.printErr( "fail to get syscall name by number %s" % sysId) syscall = sysId syscallInfo = \ ('{0:1} {1:>30}({2:>3}) {3:>12}\n').format( '%s%s' % (syscallInfo, ' ' * len(threadInfo)), syscall, sysId, convertNum(val)) if syscallInfo != '': outputCnt += 1 SysMgr.printPipe(threadInfo) SysMgr.printPipe('%s%s' % (syscallInfo, oneLine)) if outputCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n\n') def printUsage(self): targetCnt = long(0) self.totalTime = \ float(self.finishTime) - float(SysMgr.startTime) convertFunc = UtilMgr.convSize2Unit convertNum = UtilMgr.convNum SysMgr.printLogo(big=True) # print system information # SysMgr.printInfoBuffer() # choose syscall / heap menu in table # if self.sysEnabled: cmenu = 'SYSTEM' cmenu2 = 'CALLS' else: cmenu = 'HEAP' cmenu2 = 'EVENTS' # Print thread list # SysMgr.printPipe( "[%s] [ %s: %0.3f ] [ %s: %0.3f ] [ Threads: %d ] [ LogSize: %s ]" % \ ('Function Thread Info', 'Elapsed', round(self.totalTime, 7), 'Start', round(float(SysMgr.startTime), 7), len(self.threadData), convertFunc(SysMgr.logSize))) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:_^46}|{1:_^7}|{2:_^54}|{3:_^8}|{4:_^18}|{5:_^6}|{6:_^8}|".\ format("Thread", "CPU", "PAGE", cmenu, "BLOCK", "LOCK", "CUSTOM")) SysMgr.printPipe( (("{0:^16}|{1:^7}|{2:^7}|{3:^6}|{4:^6}|{5:^7}|" "{6:^9}{7:^8}{8:^8}{9:^12}|{10:^8}|{11:^7}|{12:^8}|" "{13:^8}|{14:^9}|{15:^6}|{16:^8}|")).\ format(" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ")) SysMgr.printPipe( (("{0:_^16}|{1:_^7}|{2:_^7}|{3:_^6}|{4:_^6}|" "{5:_^7}|{6:_^9}({7:_^8}/{8:_^8}/{9:_^8})|{10:_^8}|" "{11:_^7}|{12:_^8}|{13:_^8}|{14:_^9}|{15:_^6}|{16:_^8}|")).\ format("Name", "TID", "PID", "PICK", "LIFE", "PER", "ALLOC", "USER", "BUF", "KERN", "FREE", "UFREE", cmenu2, "READ", "WRITE", "TRY", "EVENTS")) SysMgr.printPipe(twoLine) # set sort value # if SysMgr.sort == 'm': sortedThreadData = sorted(self.threadData.items(), key=lambda e: e[1]['nrPages'], reverse=True) elif SysMgr.sort == 'b': sortedThreadData = sorted(self.threadData.items(), key=lambda e: e[1]['nrRdBlocks'], reverse=True) elif SysMgr.sort == 'L': sortedThreadData = sorted(self.threadData.items(), key=lambda e: e[1]['nrLockTry'], reverse=True) elif SysMgr.sort == 'h': sortedThreadData = sorted(self.threadData.items(), key=lambda e: e[1]['heapSize'], reverse=True) elif SysMgr.sort == 's': sortedThreadData = sorted(self.threadData.items(), key=lambda e: e[1]['nrSyscall'], reverse=True) else: # set CPU usage as default # sortedThreadData = sorted(self.threadData.items(), key=lambda e: e[1]['cpuTick'], reverse=True) for idx, value in sortedThreadData: targetMark = '' # skip no event count thread # if value['eventCnt'] == 0: continue # check target thread # if value['target']: targetCnt += 1 if targetCnt == 2: SysMgr.printWarn( "multiple target threads are selected") targetMark = '*' # get CPU usage # if self.totalTick > 0: cpuPer = \ '%.1f%%' % \ (float(value['cpuTick']) / float(self.totalTick) * 100) else: cpuPer = '0.0%%' # set break condition # if SysMgr.sort == 'm': breakCond = value['nrPages'] elif SysMgr.sort == 'b': breakCond = value['nrRdBlocks'] else: breakCond = long(cpuPer[:cpuPer.rfind('.')]) # check condition for stop # if breakCond < 1 and not SysMgr.showAll: pass # set lifecycle flags # if value['new']: life = 'N' else: life = ' ' if value['die']: life = '%sD' % life if self.cpuEnabled: # remove percentage if no tick # if float(value['cpuTick']) == 0: cpuPer = '-' else: cpuPer = cpuPer else: cpuPer = '-' if self.sysEnabled: cval = '%s' % convertNum(value['nrSyscall']) elif self.heapEnabled: cval = '%s' % convertFunc(value['heapSize']) else: cval = '-' if self.memEnabled: allocMem = '%s' % convertFunc(value['nrPages'] << 12) userMem = '%s' % convertFunc(value['userPages'] << 12) cacheMem = '%s' % convertFunc(value['cachePages'] << 12) kernelMem = '%s' % convertFunc(value['kernelPages'] << 12) knownFreeMem = '%s' % \ convertFunc(value['nrKnownFreePages'] << 12) unknownFreeMem = '%s' % \ convertFunc(value['nrUnknownFreePages'] << 12) else: allocMem = '-' userMem = '-' cacheMem = '-' kernelMem = '-' knownFreeMem = '-' unknownFreeMem = '-' if self.breadEnabled: readBlock = '%s' % convertFunc(value['nrRdBlocks'] << 9) else: readBlock = '-' if self.bwriteEnabled: writeBlock = '%s' % convertFunc(value['nrWrBlocks'] << 9) else: writeBlock = '-' if self.lockEnabled: nrLock = convertNum(value['nrLockTry']) else: nrLock = '-' if self.customTotal > 0: nrCustom = convertNum(value['customTotal']) else: nrCustom = '-' # update comm # if value['comm'] == '<...>' and idx in SysMgr.commCache: comm = SysMgr.commCache[idx] else: comm = value['comm'] SysMgr.printPipe( (("{0:>16}|{1:>7}|{2:>7}|{3:^6}|{4:^6}|" "{5:>7}|{6:>9}({7:>8}/{8:>8}/{9:>8})|{10:>7}|{11:>8}|" "{12:>8}|{13:>8}|{14:>9}|{15:>6}|{16:>8}|")).\ format(comm[:16], idx, value['tgid'], targetMark, life, cpuPer, allocMem, userMem, cacheMem, kernelMem, knownFreeMem, unknownFreeMem, cval, readBlock, writeBlock, nrLock, nrCustom)) if targetCnt == 0: SysMgr.printPipe('\tNone') SysMgr.printPipe("%s\n\n\n" % oneLine) # Exit because of no target # if not self.target: SysMgr.printWarn( "no specific thread targeted, input value for TID") # Print syscall usage of threads # self.printSyscallSummary() # Print resource usage of functions # self.printCpuUsage() self.printMemUsage() self.printHeapUsage() self.printBlockRdUsage() self.printBlockWrUsage() self.printLockUsage() self.printSyscallUsage() self.printCustomUsage() def makeKernelSymList(self, subStack, indentLen): symbolStack = '' stackIdx = long(0) appliedIndentLen = indentLen if not subStack: return ' None' try: for pos in subStack: if self.posData[pos]['symbol'] == '': symbolSet = ' <- %s' % hex(long(pos, 16)) elif not self.posData[pos]['symbol'] and \ SysMgr.showAll: symbolSet = ' <- %s' % hex(long(pos, 16)) else: symbolSet = ' <- %s' % str(self.posData[pos]['symbol']) lpos = appliedIndentLen + \ len(symbolStack[stackIdx:]) + len(symbolSet) if symbolStack != '' and lpos > SysMgr.lineLength: stackIdx = len(symbolStack) symbolStack = '%s\n%s' % (symbolStack, ' ' * indentLen) appliedIndentLen = long(0) symbolStack = '%s%s' % (symbolStack, symbolSet) except SystemExit: sys.exit(0) except: pass return symbolStack def makeUserSymList(self, subStack, indentLen): symbolStack = '' stackIdx = long(0) appliedIndentLen = indentLen if self.sort == 'sym': for sym in subStack: if not sym or sym == '0': symbolSet = '' elif self.userSymData[sym]['origBin'] == '??': symbolSet = ' <- %s' % sym else: symbolSet = \ ' <- %s [%s]' % (sym, self.userSymData[sym]['origBin']) lpos = appliedIndentLen + \ len(symbolStack[stackIdx:]) + len(symbolSet) if symbolStack != '' and lpos > SysMgr.lineLength: stackIdx = len(symbolStack) symbolStack = \ '%s\n%s' % (symbolStack, ' ' * indentLen) appliedIndentLen = long(0) symbolStack = '%s%s' % (symbolStack, symbolSet) elif self.sort == 'pos': for pos in subStack: if not pos: symbolStack += ' <- None' # No symbol so that just print pos # elif self.posData[pos]['symbol'] == '': symbolStack = '%s <- %s [%s]' % \ (symbolStack, hex(long(pos, 16)), self.posData[pos]['origBin']) # Print symbol # else: symbolStack = '%s <- %s [%s]' % \ (symbolStack, self.posData[pos]['symbol'], self.posData[pos]['origBin']) if not symbolStack: return '\tNone' else: return symbolStack def printSyscallUsage(self): # no effective syscall event # if self.syscallCnt == 0 or \ not SysMgr.userEnable: return subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') eventIndex = FunctionAnalyzer.symStackIdxTable.index('SYSCALL') convertNum = UtilMgr.convNum # Print syscall event # SysMgr.clearPrint() SysMgr.printPipe( '[Function Syscall Info] [Cnt: %s] (USER)' % \ convertNum(self.syscallCnt)) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^47}|{2:_^49}|{3:_^46}".\ format("Usage", "Function", "Binary", "Source")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userSymData.items(), key=lambda e: e[1]['syscallCnt'], reverse=True): if value['syscallCnt'] == 0: break SysMgr.printPipe( "{0:>7} |{1:^47}| {2:48}| {3:37}".format( convertNum(value['syscallCnt']), idx, self.posData[value['pos']]['origBin'], self.posData[value['pos']]['src'])) # Set target stack # targetStack = self.getTargetStack(value, eventIndex) # Merge and Print symbols in stack # for stack in targetStack: eventCnt = stack[eventIndex] subStack = list(stack[subStackIndex]) if eventCnt == 0: break if not subStack: continue else: indentLen = len("\t" * 4 * 4) + 3 symbolStack = self.makeUserSymList(subStack, indentLen) SysMgr.printPipe( "\t\t +{0:>7} |{1:32}".format( convertNum(eventCnt), symbolStack)) SysMgr.printPipe(oneLine) SysMgr.printPipe() # Print syscall file # SysMgr.printPipe( '[Function Syscall File Info] [Cnt: %s] (USER)' % \ convertNum(self.syscallCnt)) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^144}".\ format("Usage", "Binary")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userFileData.items(), key=lambda e: e[1]['syscallCnt'], reverse=True): if value['syscallCnt'] == 0: break SysMgr.printPipe( "{0:>8} | {1:<142}".format( convertNum(value['syscallCnt']), idx)) SysMgr.printPipe(oneLine) if self.periodicEventCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe() # Print syscall history # if not SysMgr.showAll or not self.sysCallData: SysMgr.printPipe('\n\n') return SysMgr.clearPrint() SysMgr.printPipe( '[Function Syscall History] [Cnt: %s]' % \ convertNum(self.syscallCnt)) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:_^32}|{1:_^17}({2:_^7})|{3:_^8}|{4:_^17}|".\ format("Event", "COMM", "TID", "CORE", "TIME")) SysMgr.printPipe(twoLine) # sort by time # for call in self.sysCallData: event = ConfigMgr.sysList[call[0]][4:] args = call[1][0] time = call[1][1] core = call[1][2] tid = call[1][3] title = "{0:^32}| {1:>16}({2:>7})| {3:>6} | {4:>15} |".\ format(event, self.threadData[tid]['comm'], tid, core, time) SysMgr.printPipe('%s\n%s' % (title, len(title) * '-')) # Make argument info # argsInfo = ' %s' % args # Make user call info # indentLen = 32 nowLen = indentLen try: last = call[2][0] stack = call[2][1] userCall = ' %s[%s]' % \ (self.posData[last]['symbol'], self.posData[last]['binary']) nowLen += len(userCall) for subcall in stack: try: symbol = self.posData[subcall]['symbol'] binary = self.posData[subcall]['binary'] nextCall = ' <- %s[%s]' % (symbol, binary) if SysMgr.lineLength > nowLen + len(nextCall): userCall = '%s%s' % (userCall, nextCall) nowLen += len(nextCall) else: userCall = '%s\n%s %s' % \ (userCall, ' ' * indentLen, nextCall) nowLen = indentLen + len(nextCall) except: pass except SystemExit: sys.exit(0) except: pass SysMgr.printPipe( "{0:>32}| {1:<121}".format('[Args] ', argsInfo.strip())) SysMgr.printPipe( "{0:>32}|{1:<121}".format('[User] ', userCall)) SysMgr.printPipe(oneLine) SysMgr.printPipe('\n\n') def printCustomUsage(self): # no effective custom event # if self.customTotal == 0: return subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') eventIndex = FunctionAnalyzer.symStackIdxTable.index('CUSTOM') convertNum = UtilMgr.convNum # Make custom event list # customList = ', '.join(list(self.customEventTable.keys())) # Print custom event in user space # if SysMgr.userEnable: SysMgr.clearPrint() SysMgr.printPipe( '[Function %s Info] [Cnt: %s] [Total: %s] (USER)' % \ (customList, convertNum(self.customTotal), convertNum(self.customCnt))) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^47}|{2:_^49}|{3:_^46}".\ format("Usage", "Function", "Binary", "Source")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userSymData.items(), key=lambda e: e[1]['customCnt'], reverse=True): if value['customCnt'] == 0: break SysMgr.printPipe( "{0:>7} |{1:^47}| {2:48}| {3:37}".format( convertNum(value['customCnt']), idx, self.posData[value['pos']]['origBin'], self.posData[value['pos']]['src'])) # Set target stack # targetStack = self.getTargetStack(value, eventIndex) # Merge and Print symbols in stack # for stack in targetStack: eventCnt = stack[eventIndex] subStack = list(stack[subStackIndex]) if eventCnt == 0: break if not subStack: continue else: indentLen = len("\t" * 4 * 4) + 3 symbolStack = self.makeUserSymList(subStack, indentLen) SysMgr.printPipe( "\t\t +{0:>7} |{1:32}".format( convertNum(eventCnt), symbolStack)) SysMgr.printPipe(oneLine) SysMgr.printPipe() # Print custom event file in user space # SysMgr.printPipe( '[Function %s File Info] [Cnt: %s] [Total: %s] (USER)' % \ (customList, convertNum(self.customTotal), convertNum(self.customCnt))) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^144}".\ format("Usage", "Binary")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userFileData.items(), key=lambda e: e[1]['customCnt'], reverse=True): if value['customCnt'] == 0: break SysMgr.printPipe( "{0:>8} | {1:<142}".format( convertNum(value['customCnt']), idx)) SysMgr.printPipe(oneLine) if self.periodicEventCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe() # Print custom event in kernel space # SysMgr.clearPrint() SysMgr.printPipe( '[Function %s Info] [Cnt: %s] [Total: %s] (KERNEL)' % \ (customList, convertNum(self.customTotal), convertNum(self.customCnt))) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:_^9}|{1:_^144}".format("Usage", "Function")) SysMgr.printPipe(twoLine) # Print custom usage of stacks # for idx, value in sorted(self.kerSymData.items(), key=lambda e: e[1]['customCnt'], reverse=True): if value['customCnt'] == 0: break SysMgr.printPipe( "{0:>7} |{1:^134}".format( convertNum(value['customCnt']), idx)) # Sort stacks by usage # value['stack'] = \ sorted(value['stack'], key=lambda x: x[eventIndex], reverse=True) # Print stacks by symbol # for stack in value['stack']: eventCnt = stack[eventIndex] subStack = list(stack[subStackIndex]) if eventCnt == 0: break if not subStack: continue elif len(subStack) == 1 and not SysMgr.showAll and \ (not self.posData[subStack[0]]['symbol'] or \ self.posData[subStack[0]]['symbol'] == 'NoFile'): # Pass unmeaningful part # continue else: indentLen = len("\t" * 4 * 4) + 3 symbolStack = self.makeKernelSymList(subStack, indentLen) SysMgr.printPipe( "\t\t +{0:>7} |{1:32}".format( convertNum(eventCnt), symbolStack)) SysMgr.printPipe(oneLine) SysMgr.printPipe() # Print custom call history # if not SysMgr.showAll or not self.customCallData: SysMgr.printPipe('\n\n') return SysMgr.clearPrint() SysMgr.printPipe( '[Function %s History] [Cnt: %s] [Total: %s]' % \ (customList, convertNum(self.customTotal), convertNum(self.customCnt))) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:_^32}|{1:_^17}({2:_^7})|{3:_^8}|{4:_^17}|".\ format("Event", "COMM", "TID", "CORE", "TIME")) SysMgr.printPipe(twoLine) # sort by time # for call in sorted(self.customCallData, key=lambda e: e[1][1]): event = call[0] args = call[1][0] time = call[1][1] core = call[1][2] tid = call[1][3] title = "{0:^32}| {1:>16}({2:>7})| {3:>6} | {4:>15} |".\ format(event, self.threadData[tid]['comm'], tid, core, time) SysMgr.printPipe('%s\n%s' % (title, len(title) * '-')) # Make argument info # argsInfo = ' %s' % args # Make user call info # indentLen = 32 nowLen = indentLen try: last = call[2][0] stack = call[2][1] userCall = ' %s[%s]' % \ (self.posData[last]['symbol'], self.posData[last]['binary']) nowLen += len(userCall) for subcall in stack: try: symbol = self.posData[subcall]['symbol'] binary = self.posData[subcall]['binary'] nextCall = ' <- %s[%s]' % (symbol, binary) if SysMgr.lineLength > nowLen + len(nextCall): userCall = '%s%s' % (userCall, nextCall) nowLen += len(nextCall) else: userCall = '%s\n%s %s' % \ (userCall, ' ' * indentLen, nextCall) nowLen = indentLen + len(nextCall) except: pass except SystemExit: sys.exit(0) except: pass # Make kernel call info # indentLen = 32 nowLen = indentLen try: last = call[3][0] stack = call[3][1] kernelCall = ' %s' % (self.posData[last]['symbol']) nowLen += len(kernelCall) for subcall in stack: try: nextCall = \ ' <- %s' % (self.posData[subcall]['symbol']) if SysMgr.lineLength > nowLen + len(nextCall): kernelCall = '%s%s' % (kernelCall, nextCall) nowLen += len(nextCall) else: kernelCall = \ '%s\n%s %s' % \ (kernelCall, ' ' * indentLen, nextCall) nowLen = indentLen + len(nextCall) except: pass except SystemExit: sys.exit(0) except: pass SysMgr.printPipe( "{0:>32}| {1:<121}".format('[Args] ', argsInfo.strip())) SysMgr.printPipe( "{0:>32}|{1:<121}".format('[User] ', userCall)) SysMgr.printPipe( "{0:>32}|{1:<121}".format('[Kernel] ', kernelCall)) SysMgr.printPipe(oneLine) SysMgr.printPipe('\n\n') def printCpuUsage(self): # no CPU event # if not self.cpuEnabled or self.periodicEventCnt == 0: return subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') cpuTickIndex = FunctionAnalyzer.symStackIdxTable.index('CPU_TICK') tCnt = UtilMgr.convNum(self.periodicEventCnt) # average tick interval # if self.periodicContEventCnt > 0: self.periodicEventInterval /= self.periodicContEventCnt # Print CPU usage in user space # if SysMgr.userEnable: SysMgr.clearPrint() title = 'Function CPU-Tick Info' SysMgr.printPipe( '[%s] [Cnt: %s] [Interval: %dms] (USER)' % \ (title, tCnt, self.periodicEventInterval * 1000)) # Print call stack # SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^47}|{2:_^96}".\ format("Usage", "Function", "Binary")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userSymData.items(), key=lambda e: e[1]['tickCnt'], reverse=True): if value['tickCnt'] == 0: break cpuPer = \ round(float(value['tickCnt']) / \ float(self.periodicEventCnt) * 100, 1) if cpuPer < 1 and not SysMgr.showAll: break SysMgr.printPipe( "{0:7.1f}% |{1:^47}| {2:48}".format(cpuPer, idx, self.posData[value['pos']]['origBin'])) # Increase total CPU usage per symbol # value['totalTickCnt'] += value['tickCnt'] # Set target stack # targetStack = self.getTargetStack(value) # Merge and Print symbols in stack # for stack in targetStack: cpuCnt = stack[cpuTickIndex] subStack = list(stack[subStackIndex]) if cpuCnt == 0: break if not subStack: continue else: # Increase total tick count of symbols in stack # for sym in subStack: self.userSymData[sym]['totalTickCnt'] += 1 cpuPer = \ round(float(cpuCnt) / float(value['tickCnt']) * 100, 1) if cpuPer < 1 and not SysMgr.showAll: break indentLen = len("\t" * 4 * 4) symbolStack = self.makeUserSymList(subStack, indentLen) SysMgr.printPipe( "\t +{0:7.1f}% |{1:32}".format(cpuPer, symbolStack)) SysMgr.printPipe(oneLine) if self.periodicEventCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') # Print per-symbol # title = 'Function CPU-Tick Symbol Info' SysMgr.printPipe( '[%s] [Cnt: %s] [Interval: %dms] (USER)' % \ (title, tCnt, self.periodicEventInterval * 1000)) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^47}|{2:_^96}".\ format("Usage", "Function", "Binary")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userSymData.items(), key=lambda e: e[1]['totalTickCnt'], reverse=True): if value['totalTickCnt'] == 0: break cpuPer = \ round(float(value['totalTickCnt']) / \ float(self.periodicEventCnt) * 100, 1) if cpuPer < 1 and not SysMgr.showAll: break SysMgr.printPipe( "{0:7.1f}% |{1:^47}| {2:48}".format(cpuPer, idx, self.posData[value['pos']]['origBin'])) SysMgr.printPipe(oneLine) if self.periodicEventCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') # Print tick per-file # title = 'Function CPU-Tick File Info' SysMgr.printPipe( '[%s] [Cnt: %s] [Interval: %dms] (USER)' % \ (title, tCnt, self.periodicEventInterval * 1000)) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^144}".\ format("Usage", "Binary")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userFileData.items(), key=lambda e: e[1]['tickCnt'], reverse=True): if value['tickCnt'] == 0: break cpuPer = \ round(float(value['tickCnt']) / \ float(self.periodicEventCnt) * 100, 1) if cpuPer < 1 and not SysMgr.showAll: break SysMgr.printPipe( "{0:7.1f}% | {1:<142}".format(cpuPer, idx)) SysMgr.printPipe(oneLine) if self.periodicEventCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') # Print CPU usage in kernel space # title = 'Function CPU-Tick Info' SysMgr.clearPrint() SysMgr.printPipe( '[%s] [Cnt: %s] [Interval: %dms] (KERNEL)' % \ (title, tCnt, self.periodicEventInterval * 1000)) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:_^9}|{1:_^144}".format("Usage", "Function")) SysMgr.printPipe(twoLine) # Make exception list to remove a redundant part of stack # exceptList = {} for pos, value in self.posData.items(): if value['symbol'] == '__irq_usr' or \ value['symbol'] == '__irq_svc' or \ value['symbol'] == 'el1_irq' or \ value['symbol'] == 'gic_handle_irq' or \ value['symbol'] == 'apic_timer_interrupt': exceptList.setdefault(pos, dict()) # Print CPU usage of stacks # for idx, value in sorted(self.kerSymData.items(), key=lambda e: e[1]['tickCnt'], reverse=True): if value['tickCnt'] == 0: break ''' disable to print last symbol because it is only one tickCnt = float(value['tickCnt']) eventCnt = float(self.periodicEventCnt) cpuPer = round(tickCnt / eventCnt * 100, 1) if cpuPer < 1 and not SysMgr.showAll: break SysMgr.printPipe("{0:7}% |{1:^134}".format(cpuPer, idx)) ''' # Sort stacks by usage # value['stack'].sort(reverse=True) # Define merge list # mergedSymbolChain = {} # Merge by symbol chain # for stack in value['stack']: cpuCnt = stack[cpuTickIndex] subStack = list(stack[subStackIndex]) if cpuCnt == 0: break else: # Find index of the backmost exception value # maxIdx = -1 for pos in list(exceptList.keys()): try: ridx = subStack.index(pos) if ridx >= 0 and ridx > maxIdx: maxIdx = ridx except: pass # Remove a redundant part # if maxIdx >= 0: maxIdx += 1 if maxIdx == len(subStack): subStack = [] else: subStack = subStack[maxIdx:] if not subStack: symbolStack = ' <- USER' elif len(subStack) == 1 and not SysMgr.showAll and \ (not self.posData[subStack[0]]['symbol'] or \ self.posData[subStack[0]]['symbol'] == 'NoFile'): # Pass unmeaningful part # continue else: indentLen = 10 symbolStack = self.makeKernelSymList(subStack, indentLen) try: mergedSymbolChain[symbolStack] += cpuCnt except: mergedSymbolChain[symbolStack] = cpuCnt # Print stacks by symbol # for chain, tick in sorted( mergedSymbolChain.items(), key=lambda e:e[1], reverse=True): cpuPer = \ round(tick / float(value['tickCnt']) * 100, 1) if cpuPer < 1 and not SysMgr.showAll: break SysMgr.printPipe( "{0:7.1f}% |{1:32}".format(cpuPer, chain)) SysMgr.printPipe(oneLine) if self.periodicEventCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n\n') def printUnknownMemFreeInfo(self): # check memory event # if not self.memEnabled: return SysMgr.printPipe('\n') title = 'Function Free-Only-Page Info' subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') pageFreeIndex = FunctionAnalyzer.symStackIdxTable.index('PAGE_FREE') convertFunc = UtilMgr.convSize2Unit size = convertFunc(self.pageUnknownFreeCnt << 12) if SysMgr.userEnable: # Print memory reduce by page free in user space # SysMgr.clearPrint() SysMgr.printPipe('[%s] [Size: %s] (USER)' % (title, size)) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^47}|{2:_^49}|{3:_^46}".\ format("Free", "Function", "Binary", "Source")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userSymData.items(), key=lambda e: e[1]['unknownPageFreeCnt'], reverse=True): if value['unknownPageFreeCnt'] == 0: break SysMgr.printPipe("{0:>8} |{1:^47}| {2:48}| {3:37}".\ format(convertFunc(value['unknownPageFreeCnt'] << 12), idx, self.posData[value['pos']]['origBin'], self.posData[value['pos']]['src'])) # Set target stack # targetStack = self.getTargetStack(value, pageFreeIndex) # Merge and Print symbols in stack # for stack in targetStack: pageFreeCnt = stack[pageFreeIndex] subStack = list(stack[subStackIndex]) if pageFreeCnt == 0: break if not subStack: continue else: indentLen = len("\t" * 4 * 4) symbolStack = self.makeUserSymList(subStack, indentLen) SysMgr.printPipe("\t+ {0:>8} |{1:32}".\ format(convertFunc(pageFreeCnt << 12), symbolStack)) SysMgr.printPipe(oneLine) if self.pageUnknownFreeCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') # Print memory reduce by page free in kernel space # SysMgr.clearPrint() SysMgr.printPipe('[%s] [Size: %s] (KERNEL)' % (title, size)) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^144}".format("FREE", "Function")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.kerSymData.items(), key=lambda e: e[1]['unknownPageFreeCnt'], reverse=True): if value['unknownPageFreeCnt'] == 0: break SysMgr.printPipe("{0:>8} |{1:^144}".\ format(convertFunc(value['unknownPageFreeCnt'] << 12), idx)) # Sort stacks by usage # value['stack'] = \ sorted(value['stack'], key=lambda x: x[pageFreeIndex], reverse=True) # Print stacks by symbol # for stack in value['stack']: pageFreeCnt = stack[pageFreeIndex] subStack = list(stack[subStackIndex]) if pageFreeCnt == 0: continue if not subStack: symbolStack = '\tNone' else: indentLen = len("\t" * 4 * 4) symbolStack = self.makeKernelSymList(subStack, indentLen) SysMgr.printPipe("\t+ {0:>8} |{1:32}".\ format(convertFunc(pageFreeCnt << 12), symbolStack)) SysMgr.printPipe(oneLine) if self.pageUnknownFreeCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) def printKnownMemFreeInfo(self): title = 'Function Alloc-Free-Page Info' lineLength = SysMgr.lineLength diff = self.pageAllocCnt - self.pageUsageCnt convertFunc = UtilMgr.convSize2Unit size = convertFunc(diff << 12) # Print page alloc-free pair in user space # if SysMgr.userEnable: SysMgr.clearPrint() SysMgr.printPipe('[%s] [Total: %s] (USER)' % (title, size)) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:^7}({1:^6}/{2:^6}/{3:^6})|{4:_^47}|{5:_^40}|{6:_^35}".\ format("Usage", "Usr", "Buf", "Ker", "Function", "LifeTime", "Binary")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userSymData.items(), key=lambda e: e[1]['pagePairCnt'], reverse=True): if value['pagePairCnt'] == 0: break typeList = \ {'USER': long(0), 'KERNEL': long(0), 'CACHE': long(0)} for pairId, item in value['pagePair'].items(): for ptype, cnt in item['valueList'].items(): try: typeList[ptype] += cnt except: pass try: avrTime = \ float(value['pagePairTotal'] / value['pagePairCnt']) except: avrTime = long(0) lifeTime = ' AVR: %.3f / MIN: %.3f / MAX: %.3f' % \ (avrTime, value['pagePairMin'], value['pagePairMax']) SysMgr.printPipe( "{0:>7}({1:>6}/{2:>6}/{3:>6})|{4:^47}|{5:40}| {6:1}".\ format(convertFunc(value['pagePairCnt'] << 12), convertFunc(typeList['USER'] << 12), convertFunc(typeList['CACHE'] << 12), convertFunc(typeList['KERNEL'] << 12), idx, lifeTime, self.posData[value['pos']]['origBin'])) for pairId, item in sorted(value['pagePair'].items(), key=lambda e: e[1]['size'], reverse=True): try: userPages = item['valueList']['USER'] except: userPages = long(0) try: cachePages = item['valueList']['CACHE'] except: cachePages = long(0) try: kernelPages = item['valueList']['KERNEL'] except: kernelPages = long(0) # get user alloc and free call # allocCall, freeCall = pairId.split('#') printBuf = "{0:4}+ {1:>7}({2:>6}/{3:>6}/{4:>6})| ".\ format(' ', convertFunc(item['size'] << 12), convertFunc(userPages << 12), convertFunc(cachePages << 12), convertFunc(kernelPages <<12)) indentLen = len(printBuf) appliedIndentLen = indentLen for seq, call in enumerate(allocCall.split(' <- ')): if seq > 0 and \ appliedIndentLen + len(call) > lineLength: printBuf = "%s\n%s" % (printBuf, ' ' * indentLen) appliedIndentLen = indentLen printBuf = "%s<- %s " % (printBuf, call) appliedIndentLen += (len(call) + 4) SysMgr.printPipe(printBuf) printBuf = "{0:5}{1:>30}|".format(' ', '[FREE]') indentLen = len(printBuf) appliedIndentLen = indentLen for index, call in enumerate(freeCall.split(' <- ')): clen = len(call) + 4 if index == 0: clen -= 4 if index > 0 and appliedIndentLen + clen > lineLength: printBuf = "%s\n%s" % (printBuf, ' ' * indentLen) appliedIndentLen = indentLen if index == 0: printBuf = "%s %s" % (printBuf, call) else: printBuf = "%s <- %s" % (printBuf, call) appliedIndentLen += clen SysMgr.printPipe(printBuf) SysMgr.printPipe(oneLine) if self.pageAllocCnt - self.pageUsageCnt <= 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') # Print page alloc-free pair in kernel space # SysMgr.clearPrint() SysMgr.printPipe('[%s] [Total: %s] (KERNEL)' % (title, size)) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:^7}({1:^6}/{2:^6}/{3:^6})|{4:_^47}|{5:_^76}".\ format("Usage", "Usr", "Buf", "Ker", "Function", "LifeTime")) SysMgr.printPipe(twoLine) # Print mem usage of stacks # for idx, value in sorted(self.kerSymData.items(), key=lambda e: e[1]['pagePairCnt'], reverse=True): if value['pagePairCnt'] == 0: break typeList = {'USER': long(0), 'KERNEL': long(0), 'CACHE': long(0)} for pairId, item in value['pagePair'].items(): for ptype, cnt in item['valueList'].items(): try: typeList[ptype] += cnt except: pass try: avrTime = float(value['pagePairTotal'] / value['pagePairCnt']) except: avrTime = long(0) lifeTime = ' AVR: %.3f / MIN: %.3f / MAX: %.3f' % \ (avrTime, value['pagePairMin'], value['pagePairMax']) SysMgr.printPipe( "{0:>7}({1:>6}/{2:>6}/{3:>6})|{4:^47}|{5:^75}".\ format(convertFunc(value['pagePairCnt'] << 12), convertFunc(typeList['USER'] << 12), convertFunc(typeList['CACHE'] << 12), convertFunc(typeList['KERNEL'] << 12), idx, lifeTime)) for pairId, item in sorted(value['pagePair'].items(), key=lambda e: e[1]['size'], reverse=True): try: userPages = item['valueList']['USER'] except: userPages = long(0) try: cachePages = item['valueList']['CACHE'] except: cachePages = long(0) try: kernelPages = item['valueList']['KERNEL'] except: kernelPages = long(0) # get kernel alloc and free call # allocCall, freeCall = pairId.split('#') printBuf = "{0:4}+ {1:>7}({2:>6}/{3:>6}/{4:>6})| ".\ format(' ', convertFunc(item['size'] << 12), convertFunc(userPages << 12), convertFunc(cachePages << 12), convertFunc(kernelPages << 12)) indentLen = len(printBuf) appliedIndentLen = indentLen for seq, call in enumerate(allocCall.split(' <- ')): if seq > 0 and appliedIndentLen + len(call) > lineLength: printBuf = "%s\n%s" % (printBuf, ' ' * indentLen) appliedIndentLen = indentLen printBuf = "%s<- %s " % (printBuf, call) appliedIndentLen += (len(call) + 4) SysMgr.printPipe(printBuf) printBuf = "{0:5}{1:>30}|".format(' ', '[FREE]') indentLen = len(printBuf) appliedIndentLen = indentLen for index, call in enumerate(freeCall.split(' <- ')): clen = len(call) + 4 if index == 0: clen -= 4 if index > 0 and appliedIndentLen + clen > lineLength: printBuf = "%s\n%s" % (printBuf, ' ' * indentLen) appliedIndentLen = indentLen if index == 0: printBuf = "%s %s" % (printBuf, call) else: printBuf = "%s <- %s" % (printBuf, call) appliedIndentLen += clen SysMgr.printPipe(printBuf) SysMgr.printPipe(oneLine) if self.pageAllocCnt - self.pageUsageCnt <= 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe() def printMemUsage(self): # check memory event # if not self.memEnabled: return title = 'Function Alloc-Only-Page Info' subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') pageAllocIndex = FunctionAnalyzer.symStackIdxTable.index('PAGE_ALLOC') argIndex = FunctionAnalyzer.symStackIdxTable.index('ARGUMENT') convertFunc = UtilMgr.convSize2Unit userSize = convertFunc(self.pageUsageCnt << 12) allocSize = convertFunc(self.pageAllocCnt << 12) freeSize = convertFunc(self.pageFreeCnt << 12) allocCnt = UtilMgr.convNum(self.pageAllocEventCnt) freeCnt = UtilMgr.convNum(self.pageFreeEventCnt) # Calculate page lifetime # for pfn, item in self.pageTable.items(): if not item: continue # calculate time # time = float(item['time']) if time > 0: lifeTime = float(self.finishTime) - time else: lifeTime = long(0) # Set user page lifetime # self.userSymData[item['sym']]['pageRemainTotal'] += lifeTime if self.userSymData[item['sym']]['pageRemainMin'] == 0 or \ self.userSymData[item['sym']]['pageRemainMin'] > lifeTime: self.userSymData[item['sym']]['pageRemainMin'] = lifeTime if self.userSymData[item['sym']]['pageRemainMax'] < lifeTime: self.userSymData[item['sym']]['pageRemainMax'] = lifeTime # Set kernel page lifetime # self.kerSymData[item['ksym']]['pageRemainTotal'] += lifeTime if self.kerSymData[item['ksym']]['pageRemainMin'] == 0 or \ self.kerSymData[item['ksym']]['pageRemainMin'] > lifeTime: self.kerSymData[item['ksym']]['pageRemainMin'] = lifeTime if self.kerSymData[item['ksym']]['pageRemainMax'] < lifeTime: self.kerSymData[item['ksym']]['pageRemainMax'] = lifeTime # Print memory usage by page allocation in user space # if SysMgr.userEnable: SysMgr.clearPrint() SysMgr.printPipe( '[%s] [Total: %s] [Alloc: %s(%s)] [Free: %s(%s)] (USER)' % \ (title, userSize, allocSize, allocCnt, freeSize, freeCnt)) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:^7}({1:^6}/{2:^6}/{3:^6})|{4:_^47}|{5:_^40}|{6:_^35}".\ format("Usage", "Usr", "Buf", "Ker", "Function", "LifeTime", "Binary")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userSymData.items(), key=lambda e: e[1]['pageCnt'], reverse=True): if value['pageCnt'] == 0: break try: avrTime = \ float(value['pageRemainTotal'] / value['pageCnt']) except: avrTime = long(0) lifeTime = ' AVR: %.3f / MIN: %.3f / MAX: %.3f' % \ (avrTime, value['pageRemainMin'], value['pageRemainMax']) SysMgr.printPipe( "{0:>7}({1:>6}/{2:>6}/{3:>6})|{4:^47}|{5:40}| {6:1}".\ format(convertFunc(value['pageCnt'] << 12), convertFunc(value['userPageCnt'] << 12), convertFunc(value['cachePageCnt'] << 12), convertFunc(value['kernelPageCnt'] << 12), idx, lifeTime, self.posData[value['pos']]['origBin'])) # Set target stack # targetStack = self.getTargetStack(value, pageAllocIndex) # Merge and Print symbols in stack # for stack in targetStack: subStack = list(stack[subStackIndex]) pageCnt = stack[pageAllocIndex] userPageCnt = stack[argIndex][0] cachePageCnt = stack[argIndex][1] kernelPageCnt = stack[argIndex][2] if pageCnt == 0: break if not subStack: continue else: indentLen = len("\t" * 4 * 9) symbolStack = self.makeUserSymList(subStack, indentLen) SysMgr.printPipe( "\t+ {0:>7}({1:>6}/{2:>6}/{3:>6})|{4:32}".\ format(convertFunc(pageCnt << 12), convertFunc(userPageCnt << 12), convertFunc(cachePageCnt << 12), convertFunc(kernelPageCnt << 12), symbolStack)) SysMgr.printPipe(oneLine) if self.pageUsageCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') # Print memory usage by page allocation in kernel space # SysMgr.clearPrint() SysMgr.printPipe( '[%s] [Total: %s] [Alloc: %s(%s)] [Free: %s(%s)] (KERNEL)' % \ (title, userSize, allocSize, allocCnt, freeSize, freeCnt)) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:^7}({1:^6}/{2:^6}/{3:^6})|{4:_^47}|{5:_^76}".\ format("Usage", "Usr", "Buf", "Ker", "Function", "LifeTime")) SysMgr.printPipe(twoLine) # Print mem usage of stacks # for idx, value in sorted(self.kerSymData.items(), key=lambda e: e[1]['pageCnt'], reverse=True): if value['pageCnt'] == 0: break try: avrTime = float(value['pageRemainTotal'] / value['pageCnt']) except: avrTime = long(0) lifeTime = ' AVR: %.3f / MIN: %.3f / MAX: %.3f' % \ (avrTime, value['pageRemainMin'], value['pageRemainMax']) SysMgr.printPipe( "{0:>7}({1:>6}/{2:>6}/{3:>6})|{4:^47}|{5:^76}".\ format(convertFunc(value['pageCnt'] << 12), convertFunc(value['userPageCnt'] << 12), convertFunc(value['cachePageCnt'] << 12), convertFunc(value['kernelPageCnt'] << 12), idx, lifeTime)) # Sort stacks by usage # value['stack'] = sorted(value['stack'], key=lambda x: x[pageAllocIndex], reverse=True) # Print stacks by symbol # for stack in value['stack']: subStack = list(stack[subStackIndex]) pageCnt = stack[pageAllocIndex] userPageCnt = stack[argIndex][0] cachePageCnt = stack[argIndex][1] kernelPageCnt = stack[argIndex][2] if pageCnt == 0: continue if not subStack: continue else: indentLen = len("\t" * 4 * 9) symbolStack = self.makeKernelSymList(subStack, indentLen) SysMgr.printPipe( "\t+ {0:>7}({1:>6}/{2:>6}/{3:>6})|{4:32}".format( convertFunc(pageCnt << 12), convertFunc(userPageCnt << 12), convertFunc(cachePageCnt << 12), convertFunc(kernelPageCnt << 12), symbolStack)) SysMgr.printPipe(oneLine) if self.pageUsageCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') self.printKnownMemFreeInfo() self.printUnknownMemFreeInfo() SysMgr.printPipe('\n\n') def printHeapUsage(self): # check heap memory event # if not self.heapEnabled or \ not SysMgr.userEnable: return title = 'Function Expand-Heap' subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') heapExpIndex = FunctionAnalyzer.symStackIdxTable.index('HEAP_EXPAND') convertFunc = UtilMgr.convSize2Unit # Print heap usage in user space # SysMgr.clearPrint() SysMgr.printPipe( '[%s Info] [Total: %s] [Alloc: %s(%s)] [Free: %s(%s)] (USER)' % \ (title, convertFunc(self.heapExpSize - self.heapRedSize), convertFunc(self.heapExpSize), UtilMgr.convNum(self.heapExpEventCnt), convertFunc(self.heapRedSize), UtilMgr.convNum(self.heapRedEventCnt))) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^47}|{2:_^49}|{3:_^46}".\ format("Usage", "Function", "Binary", "Source")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userSymData.items(), key=lambda e: e[1]['heapSize'], reverse=True): if value['heapSize'] == 0: break binary = self.posData[value['pos']]['origBin'] source = self.posData[value['pos']]['src'] SysMgr.printPipe("{0:>8} |{1:^47}| {2:48}| {3:37}".\ format(convertFunc(value['heapSize']), idx, binary, source)) if idx == value['pos']: SysMgr.printPipe(oneLine) continue # Set target stack # targetStack = self.getTargetStack(value, heapExpIndex) # Merge and Print symbols in stack # for stack in targetStack: heapSize = stack[heapExpIndex] subStack = list(stack[subStackIndex]) if heapSize == 0: break if not subStack: continue else: indentLen = len("\t" * 4 * 4) symbolStack = self.makeUserSymList(subStack, indentLen) SysMgr.printPipe("\t+ {0:>8} |{1:32}".\ format(convertFunc(heapSize), symbolStack)) SysMgr.printPipe(oneLine) if not self.heapTable: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') # Print remaining heap history # if not SysMgr.showAll or not self.heapTable: SysMgr.printPipe('\n\n') return SysMgr.clearPrint() SysMgr.printPipe( '[%s History] [Cnt: %s]' % \ (title, UtilMgr.convNum(len(self.heapTable)))) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:_^32}|{1:_^12}|{2:_^17}({3:_^7})|{4:_^8}|{5:_^17}|".\ format("VAddr", "Size", "COMM", "TID", "CORE", "TIME")) SysMgr.printPipe(twoLine) # sort by time # for segment in sorted(self.heapTable.items(), key=lambda e: e[1]['time']): addr = segment[0] size = segment[1]['size'] time = segment[1]['time'] core = segment[1]['core'] tid = segment[1]['tid'] usersym = segment[1]['sym'] kernelsym = segment[1]['ksym'] userstack = segment[1]['subStackAddr'] kernelstack = segment[1]['ksubStackAddr'] title = \ "{0:^32}| {1:>10} | {2:>16}({3:>7})| {4:>6} | {5:>15} |".\ format(addr, convertFunc(size), self.threadData[tid]['comm'], tid, long(core), time) SysMgr.printPipe('%s\n%s' % (title, len(title) * '-')) # Make user call info # indentLen = 32 nowLen = indentLen try: userCall = ' %s[%s]' % \ (usersym, self.userSymData[usersym]['origBin']) nowLen += len(userCall) # Set user stack list # if self.sort == 'sym': targetStack = self.userSymData[usersym]['symStack'] elif self.sort == 'pos': targetStack = self.userSymData[usersym]['stack'] # Find user stack by addr # stack = [] for val in targetStack: if id(val[subStackIndex]) == userstack: stack = val[subStackIndex] break for subcall in stack: try: nextCall = ' <- %s[%s]' % \ (subcall, self.userSymData[subcall]['origBin']) if SysMgr.lineLength > nowLen + len(nextCall): userCall = '%s%s' % (userCall, nextCall) nowLen += len(nextCall) else: userCall = '%s\n%s %s' % \ (userCall, ' ' * indentLen, nextCall) nowLen = indentLen + len(nextCall) except: pass except: pass # Make kernel call info # indentLen = 32 nowLen = indentLen try: kernelCall = ' %s' % (kernelsym) nowLen += len(kernelCall) # Set kernel stack list # if self.sort == 'sym': targetStack = self.kerSymData[kernelsym]['symStack'] elif self.sort == 'pos': targetStack = self.kerSymData[kernelsym]['stack'] # Find kernel stack by addr # stack = [] for val in targetStack: if id(val[subStackIndex]) == kernelstack: stack = val[subStackIndex] break for subcall in stack: try: nextCall = ' <- %s' % (subcall) if SysMgr.lineLength > nowLen + len(nextCall): kernelCall = '%s%s' % (kernelCall, nextCall) nowLen += len(nextCall) else: kernelCall = '%s\n%s %s' % \ (kernelCall, ' ' * indentLen, nextCall) nowLen = indentLen + len(nextCall) except: pass except: pass if userCall != ' 0': SysMgr.printPipe( "{0:>32}|{1:<121}".format('[User] ', userCall)) if kernelCall != ' 0': SysMgr.printPipe( "{0:>32}|{1:<121}".format('[Kernel] ', kernelCall)) SysMgr.printPipe(oneLine) SysMgr.printPipe('\n\n') def printLockUsage(self): # no lock event # if not self.lockEnabled or \ not SysMgr.userEnable: return subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') lockIndex = FunctionAnalyzer.symStackIdxTable.index('LOCK_TRY') unlockIndex = FunctionAnalyzer.symStackIdxTable.index('UNLOCK') # Print lock try # title = 'Function Lock-Try Info' SysMgr.clearPrint() SysMgr.printPipe( '[%s] [Cnt: %d] (USER)' % (title, self.lockTryEventCnt)) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^47}|{2:_^49}|{3:_^46}".\ format("Usage", "Function", "Binary", "Source")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userSymData.items(), key=lambda e: e[1]['lockTryCnt'], reverse=True): if value['lockTryCnt'] == 0: break binary = self.posData[value['pos']]['origBin'] source = self.posData[value['pos']]['src'] SysMgr.printPipe("{0:8} |{1:^47}| {2:48}| {3:37}".\ format(value['lockTryCnt'], idx, binary, source)) # Set target stack # targetStack = self.getTargetStack(value, lockIndex) # Merge and Print symbols in stack # for stack in targetStack: lockTryCnt = stack[lockIndex] subStack = list(stack[subStackIndex]) if lockTryCnt == 0: break if not subStack: continue else: indentLen = len("\t" * 4 * 4) symbolStack = self.makeUserSymList(subStack, indentLen) SysMgr.printPipe("\t+ {0:8} |{1:32}".\ format(lockTryCnt, symbolStack)) SysMgr.printPipe(oneLine) if self.lockTryEventCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') # Print lock per-file # title = 'Function Lock-Try File Info' SysMgr.printPipe( '[%s] [Cnt: %d] (USER)' % (title, self.lockTryEventCnt)) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^144}".format("Usage", "Binary")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userFileData.items(), key=lambda e: e[1]['lockTryCnt'], reverse=True): if value['lockTryCnt'] == 0: break SysMgr.printPipe( "{0:8} | {1:<142}".format(value['lockTryCnt'], idx)) SysMgr.printPipe(oneLine) if self.periodicEventCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') # Print unlock # title = 'Function Unlock Info' SysMgr.clearPrint() SysMgr.printPipe( '[%s] [Cnt: %d] (USER)' % (title, self.unlockEventCnt)) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^47}|{2:_^49}|{3:_^46}".\ format("Usage", "Function", "Binary", "Source")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userSymData.items(), key=lambda e: e[1]['unlockCnt'], reverse=True): if value['unlockCnt'] == 0: break binary = self.posData[value['pos']]['origBin'] source = self.posData[value['pos']]['src'] SysMgr.printPipe("{0:8} |{1:^47}| {2:48}| {3:37}".\ format(value['unlockCnt'], idx, binary, source)) # Set target stack # targetStack = self.getTargetStack(value, unlockIndex) # Merge and Print symbols in stack # for stack in targetStack: unlockCnt = stack[unlockIndex] subStack = list(stack[subStackIndex]) if unlockCnt == 0: break if not subStack: continue else: indentLen = len("\t" * 4 * 4) symbolStack = self.makeUserSymList(subStack, indentLen) SysMgr.printPipe("\t+ {0:8} |{1:32}".\ format(unlockCnt, symbolStack)) SysMgr.printPipe(oneLine) if self.unlockEventCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') # Print unlock per-file # title = 'Function Unlock File Info' SysMgr.printPipe( '[%s] [Cnt: %d] (USER)' % (title, self.lockTryEventCnt)) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^144}".\ format("Usage", "Binary")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userFileData.items(), key=lambda e: e[1]['unlockCnt'], reverse=True): if value['unlockCnt'] == 0: break SysMgr.printPipe( "{0:8} | {1:<142}".format(value['unlockCnt'], idx)) SysMgr.printPipe(oneLine) if self.periodicEventCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') # Print lock history # if not SysMgr.showAll or not self.lockCallData: SysMgr.printPipe('\n\n') return title = 'Function Lock History' SysMgr.clearPrint() SysMgr.printPipe( '[%s] [Lock: %d] [Unlock: %d]' % \ (title, self.lockTryEventCnt, self.unlockEventCnt)) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:_^32}|{1:_^16}|{2:_^17}({3:_^7})|{4:_^8}|{5:_^17}|".\ format("Event", "TARGET", "COMM", "TID", "CORE", "TIME")) SysMgr.printPipe(twoLine) # sort by time # for call in self.lockCallData: event = call[0] target = call[1][0] time = call[1][1] core = call[1][2] tid = call[1][3] userstack = call[2] comm = self.threadData[tid]['comm'] title = "{0:^32}|{1:^16}|{2:>16}({3:>7})| {4:>6} | {5:>15} |".\ format(event, target, comm, tid, core, time) SysMgr.printPipe('%s\n%s' % (title, len(title) * '-')) # Make user call info # indentLen = 32 nowLen = indentLen try: last = userstack[0] stack = userstack[1] symbol = self.posData[last]['symbol'] binary = self.posData[last]['binary'] userCall = ' %s[%s]' % (symbol, binary) nowLen += len(userCall) for subcall in stack: try: symbol = self.posData[subcall]['symbol'] binary = self.posData[subcall]['binary'] nextCall = ' <- %s[%s]' % (symbol, binary) if SysMgr.lineLength > nowLen + len(nextCall): userCall = '%s%s' % (userCall, nextCall) nowLen += len(nextCall) else: userCall = '%s\n%s %s' % \ (userCall, ' ' * indentLen, nextCall) nowLen = indentLen + len(nextCall) except: pass except SystemExit: sys.exit(0) except: pass SysMgr.printPipe( "{0:>32}|{1:<121}".format('[User] ', userCall)) SysMgr.printPipe(oneLine) SysMgr.printPipe('\n\n') def printBlockWrUsage(self): # no block write event # if not self.bwriteEnabled: return title = 'Function Write-Block Info' subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') blkWrIndex = FunctionAnalyzer.symStackIdxTable.index('BLK_WRITE') convertFunc = UtilMgr.convSize2Unit convertNum = UtilMgr.convNum size = convertFunc(self.blockWrUsageCnt << 9) # Print block write in user space # if SysMgr.userEnable: SysMgr.clearPrint() SysMgr.printPipe( '[%s] [Size: %s] [Cnt: %s] (USER)' % \ (title, size, convertNum(self.blockWrEventCnt))) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^47}|{2:_^49}|{3:_^46}".\ format("Usage", "Function", "Binary", "Source")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userSymData.items(), key=lambda e: e[1]['blockWrCnt'], reverse=True): if value['blockWrCnt'] == 0: break binary = self.posData[value['pos']]['origBin'] source = self.posData[value['pos']]['src'] SysMgr.printPipe("{0:>8} |{1:^47}| {2:48}| {3:37}".\ format(convertFunc(value['blockWrCnt'] << 9), idx, binary, source)) # Set target stack # targetStack = self.getTargetStack(value, blkWrIndex) # Merge and Print symbols in stack # for stack in targetStack: blockWrCnt = stack[blkWrIndex] subStack = list(stack[subStackIndex]) if blockWrCnt == 0: break if not subStack: continue else: indentLen = len("\t" * 4 * 4) symbolStack = self.makeUserSymList(subStack, indentLen) SysMgr.printPipe("\t+ {0:>8} |{1:32}".\ format(convertFunc(blockWrCnt << 9), symbolStack)) SysMgr.printPipe(oneLine) if self.blockWrUsageCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n') # Print block write in kernel space # SysMgr.clearPrint() SysMgr.printPipe( '[%s] [Size: %s] [Cnt: %s] (KERNEL)' % \ (title, size, convertNum(self.blockWrEventCnt))) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^144}".format("Usage", "Function")) SysMgr.printPipe(twoLine) # Print block write usage of stacks # for idx, value in sorted(self.kerSymData.items(), key=lambda e: e[1]['blockWrCnt'], reverse=True): if value['blockWrCnt'] == 0: break SysMgr.printPipe("{0:>8} |{1:^134}".\ format(convertFunc(value['blockWrCnt'] << 9), idx)) # Sort stacks by usage # value['stack'] = \ sorted(value['stack'], key=lambda x: x[blkWrIndex], reverse=True) # Print stacks by symbol # for stack in value['stack']: blockWrCnt = stack[blkWrIndex] subStack = list(stack[subStackIndex]) if blockWrCnt == 0: continue if not subStack: symbolStack = '\tNone' else: indentLen = len("\t" * 4 * 4) symbolStack = self.makeKernelSymList(subStack, indentLen) SysMgr.printPipe("\t+ {0:>8} |{1:32}".\ format(convertFunc(blockWrCnt << 9), symbolStack)) SysMgr.printPipe(oneLine) if self.blockWrUsageCnt == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) SysMgr.printPipe('\n\n') def getExceptionList(self): exceptList = {} # do not use this function now # return exceptList for pos, value in self.posData.items(): if value['symbol'] == 'None': try: exceptList[pos] except: exceptList[pos] = dict() return exceptList def getTargetStack(self, value, index=None): targetStack = [] if self.sort == 'sym': targetStack = value['symStack'] elif self.sort == 'pos': targetStack = value['stack'] # Sort by usage # if index: targetStack = \ sorted(targetStack, key=lambda x: x[index], reverse=True) else: targetStack.sort(reverse=True) return targetStack def printBlockRdUsage(self): # no block read event # if not self.breadEnabled: return title = 'Function Read-Block Info' subStackIndex = FunctionAnalyzer.symStackIdxTable.index('STACK') blkRdIndex = FunctionAnalyzer.symStackIdxTable.index('BLK_READ') convertFunc = UtilMgr.convSize2Unit convertNum = UtilMgr.convNum size = convertFunc(self.blockRdUsageCnt << 9) # Print block read in user space # if SysMgr.userEnable: SysMgr.clearPrint() SysMgr.printPipe( '[%s] [Size: %s] [Cnt: %s] (USER)' % \ (title, size, convertNum(self.blockRdEventCnt))) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^47}|{2:_^49}|{3:_^46}".\ format("Usage", "Function", "Binary", "Source")) SysMgr.printPipe(twoLine) for idx, value in sorted(self.userSymData.items(), key=lambda e: e[1]['blockRdCnt'], reverse=True): if value['blockRdCnt'] == 0: break binary = self.posData[value['pos']]['origBin'] source = self.posData[value['pos']]['src'] SysMgr.printPipe("{0:>8} |{1:^47}| {2:48}| {3:37}".\ format(convertFunc(value['blockRdCnt'] << 9), idx, binary, source)) # Set target stack # targetStack = self.getTargetStack(value, blkRdIndex) # Merge and Print symbols in stack # for stack in targetStack: blockRdCnt = stack[blkRdIndex] subStack = list(stack[subStackIndex]) if blockRdCnt == 0: break if not subStack: continue else: indentLen = len("\t" * 4 * 4) symbolStack = self.makeUserSymList(subStack, indentLen) SysMgr.printPipe("\t+ {0:8} |{1:32}".\ format(convertFunc(blockRdCnt << 9), symbolStack)) SysMgr.printPipe(oneLine) SysMgr.printPipe('\n') # Print block read in kernel space # SysMgr.clearPrint() SysMgr.printPipe( '[%s] [Size: %s] [Cnt: %s] (KERNEL)' % \ (title, size, convertNum(self.blockRdEventCnt))) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^9}|{1:_^144}".format("Usage", "Function")) SysMgr.printPipe(twoLine) # Print block read usage of stacks # for idx, value in sorted(self.kerSymData.items(), key=lambda e: e[1]['blockRdCnt'], reverse=True): if value['blockRdCnt'] == 0: break SysMgr.printPipe("{0:>8} |{1:^144}".\ format(convertFunc(value['blockRdCnt'] << 9), idx)) # Sort stacks by usage # value['stack'] = \ sorted(value['stack'], key=lambda x: x[blkRdIndex], reverse=True) # Print stacks by symbol # for stack in value['stack']: blockRdCnt = stack[blkRdIndex] subStack = list(stack[subStackIndex]) if blockRdCnt == 0: continue if not subStack: symbolStack = '\tNone' else: indentLen = len("\t" * 4 * 4) symbolStack = self.makeKernelSymList(subStack, indentLen) SysMgr.printPipe("\t+ {0:>8} |{1:32}".\ format(convertFunc(blockRdCnt << 9), symbolStack)) SysMgr.printPipe(oneLine) SysMgr.printPipe('\n\n') class LeakAnalyzer(object): """ Analyzer for leaktracing """ # use SIGRT1 and SIGRT2 as default signals # startSig = 35 stopSig = 36 def __init__(self, file=None, pid=None): self.pid = pid self.posData = {} self.symData = {} self.fileData = {} self.callData = [] self.totalLeakSize = long(0) self.init_posData = \ {'offset': long(0), 'path': None, 'lastPosCnt': long(0), 'callList': None, 'count': long(0), 'size': long(0), 'lastPosSize': long(0), 'sym': '??'} self.init_symData = \ {'offset': long(0), 'path': None, 'lastPosCnt': long(0), 'substack': None, 'count': long(0), 'size': long(0), 'lastPosSize': long(0)} self.init_fileData = \ {'lastPosCnt': long(0), 'count': long(0), 'size': long(0), 'lastPosSize': long(0)} # Get file size # try: stat = os.stat(file) size = UtilMgr.convSize2Unit(stat.st_size) except SystemExit: sys.exit(0) except: size = '??' # Open log file # try: SysMgr.printInfo( "start loading '%s' [%s]" % (file, size)) fd = open(file, 'r') except SystemExit: sys.exit(0) except: SysMgr.printOpenErr(file) sys.exit(0) SysMgr.printInfo("start processing data...") self.callData = self.parseLines(fd) # Get process object # try: proc = Debugger(pid=int(pid), attach=False) except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to analyze leakage", True) SysMgr.printInfo("start resolving symbols...") # Resolve symbols # self.resolveSymbols(proc) SysMgr.printInfo("start merging symbols...") # Merge symbols # self.mergeSymbols() def printLeakage(self, runtime, profiletime): convert = UtilMgr.convSize2Unit try: mlist = SysMgr.getMemStat(self.pid) vssIdx = ConfigMgr.STATM_TYPE.index("TOTAL") vss = convert(long(mlist[vssIdx]) << 12) rssIdx = ConfigMgr.STATM_TYPE.index("RSS") rss = convert(long(mlist[rssIdx]) << 12) except: vss = rss = '?' proc = '%s(%s)' % (SysMgr.getComm(self.pid), self.pid) # function leakage info # title = 'Function Leakage Info' SysMgr.printPipe(( '\n[%s] [Process: %s] [Runtime: %s] [ProfileTime: %s] ' '[VSS: %s] [RSS: %s] [LeakSize: %s] [NrCall: %s]') % \ (title, proc, runtime, profiletime, vss, rss, convert(self.totalLeakSize), convert(len(self.callData)))) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:^7} | {1:^7} | {2:^7} | {3:^122} |".\ format("Size", "Count", "Avg", "Function")) SysMgr.printPipe(oneLine) count = long(0) for sym, val in sorted(self.symData.items(), key=lambda e: long(e[1]['lastPosSize']), reverse=True): if val['lastPosSize'] == 0: break SysMgr.printPipe( "{0:>7} | {1:>7} | {2:>7} | {3:<122} ".\ format(convert(val['lastPosSize']), convert(val['count']), convert(long(val['lastPosSize'] / val['count'])), '%s[%s]' % (sym, val['path']))) for substack, size in sorted(val['substack'].items(), key=lambda e: e[1], reverse=True): SysMgr.printPipe( "{0:>7} | {1:>7} | {2:<132} ".\ format('', convert(size), substack)) count += 1 SysMgr.printPipe(oneLine) if count == 0: SysMgr.printPipe('\tNone\n%s' % oneLine) # file leakage info # title = 'File Leakage Info' SysMgr.printPipe(( '\n[%s] [Process: %s] [Runtime: %s] [ProfileTime: %s] ' '[VSS: %s] [RSS: %s] [LeakSize: %s] [NrCall: %s]') % \ (title, proc, runtime, profiletime, vss, rss, convert(self.totalLeakSize), convert(len(self.callData)))) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:^7} | {1:^7} | {2:^7} | {3:^122} |".format( "Size", "Count", "Avg", "Path")) SysMgr.printPipe(oneLine) count = long(0) for file, val in sorted(self.fileData.items(), key=lambda e: long(e[1]['lastPosSize']), reverse=True): if val['lastPosSize'] == 0: break SysMgr.printPipe( "{0:>7} | {1:>7} | {2:>7} | {3:<122} |".format( convert(val['lastPosSize']), convert(val['count']), convert(long(val['lastPosSize'] / val['count'])), file)) count += 1 if count == 0: SysMgr.printPipe('\tNone') SysMgr.printPipe(oneLine) if not SysMgr.showAll or not self.callData: return # leakage history # title = 'Leakage History' SysMgr.printPipe( '\n[%s] [Total: %s] [CallCount: %s]' % \ (title, convert(self.totalLeakSize, True), convert(len(self.callData), True))) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:^16} | {1:^6} |{2:^50}| {3:^73} |".\ format("Time", "Size", "Data", "Stack")) SysMgr.printPipe(oneLine) for time, items in sorted(self.callData.items(), key=lambda e: e[0], reverse=False): stack = list(items['symstack']) SysMgr.printPipe( "{0:>16} | {1:>6} |{2:50}| {3:<73} |".\ format(time, convert(long(items['size'])), items['data'][:-1], ' <- '.join(stack))) count += 1 SysMgr.printPipe(oneLine) def mergeSymbols(self): cnt = long(0) total = len(self.posData) dobj = Debugger() for pos, val in self.posData.items(): UtilMgr.printProgress(cnt, total) cnt += 1 # merge by symbol # sym = val['sym'] try: self.symData[sym]['count'] += val['count'] self.symData[sym]['size'] += val['size'] self.symData[sym]['lastPosCnt'] += val['lastPosCnt'] self.symData[sym]['lastPosSize'] += val['lastPosSize'] except SystemExit: sys.exit(0) except: self.symData[sym] = dict(self.init_symData) self.symData[sym]['offset'] = val['offset'] self.symData[sym]['path'] = val['path'] self.symData[sym]['count'] = val['count'] self.symData[sym]['size'] = val['size'] self.symData[sym]['lastPosCnt'] = val['lastPosCnt'] self.symData[sym]['lastPosSize'] = val['lastPosSize'] self.symData[sym]['substack'] = dict() if val['callList']: for time in list(val['callList'].keys()): callinfo = self.callData[time] substack = dobj.getBacktraceStr(callinfo['symstack'][1:]) dobj.btStr = None try: self.symData[sym]['substack'][substack] += \ long(callinfo['size']) except: self.symData[sym]['substack'][substack] = \ long(callinfo['size']) # merge by file # path = val['path'] try: self.fileData[path]['count'] += val['count'] self.fileData[path]['size'] += val['size'] self.fileData[path]['lastPosCnt'] += val['lastPosCnt'] self.fileData[path]['lastPosSize'] += val['lastPosSize'] except SystemExit: sys.exit(0) except: self.fileData[path] = dict(self.init_fileData) self.fileData[path]['count'] = val['count'] self.fileData[path]['size'] = val['size'] self.fileData[path]['lastPosCnt'] = val['lastPosCnt'] self.fileData[path]['lastPosSize'] = val['lastPosSize'] self.totalLeakSize += val['lastPosSize'] UtilMgr.deleteProgress() def resolveSymbols(self, proc): cnt = long(0) total = len(self.posData) + len(self.callData) # resolve all symbols # for pos, val in self.posData.items(): UtilMgr.printProgress(cnt, total) cnt += 1 try: ret = proc.getSymbolInfo(long(pos, 16)) except: SysMgr.printWarn( "fail to get symbol for %s" % pos, reason=True) continue if ret and len(ret) > 3: val['sym'] = ret[0] val['path'] = ret[1] val['offset'] = ret[2] # resolve symbols in stacks # for pos, val in self.callData.items(): UtilMgr.printProgress(cnt, total) cnt += 1 if not 'stack' in val: continue symstack = list(val['stack']) for idx, offset in enumerate(val['stack']): data = self.posData[offset] symstack[idx] = [data['offset'], data['sym'], data['path']] val['symstack'] = symstack try: posid = val['stack'][0] self.posData[posid]['callList'][pos] = None except: self.posData[posid]['callList'] = dict() self.posData[posid]['callList'][pos] = None UtilMgr.deleteProgress() def parseLines(self, fd): callinfo = {} while 1: try: line = fd.readline() except SystemExit: sys.exit(0) except: continue if not line: break # print progress # cur = fd.tell() total = os.fstat(fd.fileno()).st_size UtilMgr.printProgress(cur, total) items = line.split(', ') if items[0] != 'leak': continue time = None item = dict() for content in items[1:]: try: name, body = content.split('=', 1) except SystemExit: sys.exit(0) except: continue if name == 'time': time = body elif name == 'stack': # split callstack # item[name] = body.split() else: item[name] = body if not item or \ not 'size' in item or \ not item['size'].isdigit(): continue # save pos in common area # for pos in item['stack']: try: self.posData[pos]['count'] += 1 self.posData[pos]['size'] += long(item['size']) except SystemExit: sys.exit(0) except: self.posData[pos] = dict(self.init_posData) self.posData[pos]['count'] = 1 self.posData[pos]['size'] = long(item['size']) self.posData[pos]['callList'] = dict() try: lastPos = item['stack'][0] except: continue self.posData[lastPos]['lastPosSize'] += long(item['size']) callinfo[time] = item UtilMgr.deleteProgress() return callinfo class FileAnalyzer(object): """ Analyzer for file profiling """ init_mapData = \ {'offset': long(0), 'size': long(0), 'pageCnt': long(0), 'fd': None, 'totalSize': long(0), 'fileMap': None, 'pids': None, 'linkCnt': long(0), 'inode': None, 'accessTime': None, 'devid': None, 'isRep': True, 'perm': None, 'repFile': None, 'hardLink': long(1), 'linkList': None, 'vstart': long(0), 'vend': long(0), 'elfInfo': None} def __init__(self): self.profSuccessCnt = long(0) self.profFailedCnt = long(0) self.profPageCnt = long(0) self.procData = {} self.fileData = {} self.inodeData = {} self.target = [''] self.procList = {} self.fileList = {} self.intervalProcData = [] self.intervalFileData = [] self.init_procData = \ {'tids': None, 'pageCnt': long(0), 'procMap': None, 'comm': ''} self.init_threadData = {'comm': ''} self.init_inodeData = {} # handle no target case # if SysMgr.filterGroup: self.target = SysMgr.filterGroup if not SysMgr.guiderObj: # load libc # SysMgr.loadLibcObj(exit=True) # define mmap types # SysMgr.libcObj.mmap.argtypes = \ [POINTER(None), c_size_t, c_int, c_int, c_int, c_long] SysMgr.libcObj.mmap.restype = POINTER(None) # define munmap types # SysMgr.libcObj.munmap.argtypes = \ [POINTER(None), c_size_t] SysMgr.libcObj.munmap.restype = c_int # define mincore types # SysMgr.libcObj.mincore.argtypes = \ [POINTER(None), c_size_t, POINTER(c_ubyte)] SysMgr.libcObj.mincore.restype = c_int # set system maximum fd number # SysMgr.setMaxFd() while 1: # scan proc directory and save map information of processes # self.scanProcs() # merge maps of processes into a integrated file map # self.mergeFileMapInfo() # get file map info on memory # self.getFilePageMaps() # fill file map of each processes # self.fillFileMaps() if SysMgr.intervalEnable > 0: # save previous file usage and initialize all variables # self.intervalProcData.append(self.procData) self.intervalFileData.append(self.fileData) self.procData = {} self.fileData = {} self.inodeData = {} self.profSuccessCnt = long(0) self.profFailedCnt = long(0) # check exit condition for interval profile # if not SysMgr.condExit: SysMgr.waitEvent() else: break else: break def __del__(self): pass def printIntervalInfo(self): # Merge process info into a global list # for procData in self.intervalProcData: for pid, procInfo in procData.items(): try: if self.procList[pid]['pageCnt'] < procInfo['pageCnt']: self.procList[pid]['pageCnt'] = procInfo['pageCnt'] except: self.procList[pid] = dict(self.init_procData) self.procList[pid]['tids'] = {} self.procList[pid]['pageCnt'] = procInfo['pageCnt'] self.procList[pid]['comm'] = procInfo['comm'] for tid, val in procInfo['tids'].items(): try: self.procList[pid]['tids'][tid] except: self.procList[pid]['tids'][tid] = \ dict(self.init_threadData) self.procList[pid]['tids'][tid]['comm'] = val['comm'] if not self.procList: SysMgr.printErr('no process profiled') sys.exit(0) # Merge file info into a global list # for fileData in self.intervalFileData: for fileName, fileStat in fileData.items(): try: fl = self.fileList[fileName] if fl['pageCnt'] < fileStat['pageCnt']: fl['pageCnt'] = fileStat['pageCnt'] except: self.fileList[fileName] = dict(FileAnalyzer.init_mapData) self.fileList[fileName]['pageCnt'] = fileStat['pageCnt'] self.fileList[fileName]['totalSize'] = fileStat['totalSize'] if not self.fileList: SysMgr.printErr('no file profiled') sys.exit(0) SysMgr.printLogo(big=True) # Print system information # SysMgr.printInfoBuffer() # define alias # pageSize = SysMgr.pageSize convert = UtilMgr.convSize2Unit convColor = UtilMgr.convColor # Print process list # SysMgr.printPipe(( "[%s] [ Process : %d ] [ LastRAM: %s ]" " [ Keys: Foward/Back/Save/Quit ] [ Capture: Ctrl+\\ ]") % \ ('File Process Info', len(self.procList), convert(self.profPageCnt * 4 << 10))) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:_^16}({1:_^6})|{2:_^12}|{3:_^16}({4:_^5}) |".\ format("Process", "PID", "MaxRAM", "ThreadName", "TID")) SysMgr.printPipe(twoLine) procInfo = "{0:_^16}({1:^6})|{2:11} |".format('', '', '') threadInfo = " {0:^16}({1:^6}) |".format('', '') procLength = len(procInfo) threadLength = len(threadInfo) lineLength = SysMgr.lineLength for pid, val in sorted(self.procList.items(), key=lambda e: long(e[1]['pageCnt']), reverse=True): try: rsize = val['pageCnt'] * pageSize except: SysMgr.printWarn( 'fail to get total mapped size for %s' % val['comm'], reason=True) continue if rsize > 0: rsize = convColor(convert(rsize), 'YELLOW', 11) printMsg = "{0:>16}({1:>6})|{2:>11} |".\ format(val['comm'][:SysMgr.commLen], pid, rsize) linePos = len(printMsg) for tid, threadVal in sorted(val['tids'].items(), reverse=True): threadInfo = \ "{0:>16}({1:>6}) |".format( threadVal['comm'][:SysMgr.commLen], tid) linePos += threadLength if linePos > lineLength: linePos = procLength + threadLength printMsg += "\n" + (' ' * (procLength - 1)) + '|' printMsg += threadInfo SysMgr.printPipe(printMsg) SysMgr.printPipe("%s\n\n" % oneLine) # Print file list # SysMgr.printPipe(( "[%s] [ File: %d ] [ LastRAM: %s ] " "[ Keys: Foward/Back/Save/Quit ]") % \ ('File Usage Info', len(self.fileList), convert(self.profPageCnt * 4 << 10))) SysMgr.printPipe(twoLine) printMsg = "{0:_^11}|{1:_^8}|{2:_^3}|".format( "InitRAM", "File", "%") if len(self.intervalFileData) > 1: for idx in range(1, len(self.intervalFileData)): printMsg += "{0:_^15}|".format(str(idx)) printMsg += "{0:_^11}|{1:_^3}|".format("LastRAM", "%") lineLength = SysMgr.lineLength printMsg += '_' * (long((lineLength - len(printMsg)) / 2) - 2) printMsg += 'Library' printMsg += '_' * (lineLength - len(printMsg)) SysMgr.printPipe(printMsg) SysMgr.printPipe(twoLine) # print interval usage # for fileName, val in sorted(self.fileList.items(), key=lambda e: long(e[1]['pageCnt']), reverse=True): try: memSize = \ self.intervalFileData[0][fileName]['pageCnt'] * pageSize except: memSize = long(0) try: idx = val['totalSize'] + pageSize - 1 fileSize = long(idx / pageSize) * pageSize except: fileSize = long(0) # set percentage # if fileSize != 0: per = long(long(memSize) / float(fileSize) * 100) if per >= SysMgr.cpuPerHighThreshold: per = UtilMgr.convColor(per, 'RED', 3) else: per = UtilMgr.convColor(per, 'YELLOW', 3) else: per = long(0) if memSize > 0: memSize = convColor(convert(memSize), 'YELLOW', 10) # check whether this file was profiled or not # isRep = False for fileData in reversed(self.intervalFileData): if fileName in fileData and fileData[fileName]['isRep']: printMsg = \ "{0:>10} |{1:>7} |{2:>3}|".format( memSize, convert(fileSize), per) isRep = True break if not isRep: continue # calculate diff of on-memory file size # if len(self.intervalFileData) > 1: for idx in range(1, len(self.intervalFileData)): diffNew = long(0) diffDel = long(0) try: nowFileMap = \ self.intervalFileData[idx][fileName]['fileMap'] except: nowFileMap = None try: prevFileMap = \ self.intervalFileData[idx - 1][fileName]['fileMap'] except: prevFileMap = None fileData = self.intervalFileData if not nowFileMap: if prevFileMap: diffDel = fileData[idx - 1][fileName]['pageCnt'] else: if not prevFileMap: diffNew = fileData[idx][fileName]['pageCnt'] else: if len(nowFileMap) == len(prevFileMap): for i in range(len(nowFileMap)): if nowFileMap[i] > prevFileMap[i]: diffNew += 1 elif nowFileMap[i] < prevFileMap[i]: diffDel += 1 if diffNew > 0: diffNew = convColor( convert(diffNew * pageSize), 'RED', 6) else: diffNew = ' ' if diffDel > 0: diffDel = convColor( convert(diffDel * pageSize), 'RED', 6) else: diffDel = ' ' printMsg += "+%6s/-%6s|" % (diffNew, diffDel) finalData = self.intervalFileData[-1][fileName] totalMemSize = finalData['pageCnt'] * pageSize if fileSize != 0: per = long(long(totalMemSize) / float(fileSize) * 100) if per >= SysMgr.cpuPerHighThreshold: per = UtilMgr.convColor(per, 'RED', 3) else: per = UtilMgr.convColor(per, 'YELLOW', 3) else: per = long(0) if totalMemSize > 0: totalMemSize = convColor( convert(totalMemSize), 'YELLOW', 11) printMsg += \ "{0:11}|{1:3}| {2:1}".format(totalMemSize, per, fileName) SysMgr.printPipe(printMsg) SysMgr.printPipe("%s\n\n\n" % oneLine) def makeReadaheadList(self): pass @staticmethod def getMapAddr(pid, fname, fd=None): if not fname: SysMgr.printWarn( "no memory-mapped file name to be searched") return if not fd: fd = FileAnalyzer.getMapFd(pid) if not fd: return None # read maps # fd.seek(0, 0) mapBuf = fd.readlines() for item in mapBuf: mdict = FileAnalyzer.parseMapLine(item) if mdict and mdict['binName']: if mdict['binName'].endswith(fname): return str(mdict['startAddr']), str(mdict['endAddr']) return None @staticmethod def getMapFilePath(pid, fname, fd=None): if not fname: SysMgr.printWarn( "no file name to be searched on memory-map") return if not fd: fd = FileAnalyzer.getMapFd(pid) if not fd: return None # read maps # fd.seek(0, 0) mapBuf = fd.readlines() for item in mapBuf: mdict = FileAnalyzer.parseMapLine(item) if mdict and mdict['binName']: if os.path.basename(mdict['binName']).startswith(fname): return str(mdict['binName']) return None @staticmethod def getEmptyMapAddr(pid, fd=None, size=0, onlyExec=False): if not fd: fd = FileAnalyzer.getMapFd(pid) if not fd: return None # search empty space # mapBuf = fd.readlines() for item in mapBuf: mdict = FileAnalyzer.parseMapLine(item) if not mdict: mapLine = item.split() addrs = \ list(map(lambda x: long(x, 16), mapLine[0].split('-'))) perm = mapLine[1] if onlyExec and not 'x' in perm: continue return addrs[0] @staticmethod def getMapFd(pid, verb=False): # open maps # try: path = '%s/%s/maps' % (SysMgr.procPath, pid) return open(path, 'r') except SystemExit: sys.exit(0) except: SysMgr.printOpenWarn(path, verb) return None @staticmethod def getProcMapInfo(pid, fd=None, onlyExec=False, saveAll=False): if not fd: fd = FileAnalyzer.getMapFd(pid, True) if not fd: comm = SysMgr.getComm(pid) SysMgr.printErr( 'fail to get memory map for %s(%s)' % (comm, pid)) sys.exit(0) # read maps # fd.seek(0, 0) mapBuf = fd.readlines() # parse and merge lines in maps # fileMap = dict() for val in mapBuf: FileAnalyzer.mergeMapLine(val, fileMap, saveAll=saveAll) # remove non-executable files # if onlyExec: for fname in list(fileMap.keys()): if fname != 'stack' and not fileMap[fname]['exec']: fileMap.pop(fname, None) return fileMap @staticmethod def addMapLine(dataObj, fileName, newOffset, newSize): newEnd = newOffset + newSize try: savedOffset = dataObj[fileName]['offset'] savedSize = dataObj[fileName]['size'] savedEnd = savedOffset + savedSize # start address bigger than saved one # if savedOffset <= newOffset: # merge bigger end address than saved one # if savedEnd < newEnd: dataObj[fileName]['size'] += \ (newEnd - savedOffset - savedSize) # ignore lesser end address than saved one # else: pass # start address lesser than saved one # else: if savedEnd >= newEnd: dataObj[fileName]['size'] += (savedOffset - newOffset) else: dataObj[fileName]['size'] = newSize dataObj[fileName]['offset'] = newOffset except SystemExit: sys.exit(0) except: dataObj[fileName] = dict(FileAnalyzer.init_mapData) dataObj[fileName]['offset'] = newOffset dataObj[fileName]['size'] = newSize @staticmethod def parseMapLine(string): m = re.match(( r'^(?P.\S+)-(?P.\S+) (?P.\S+) ' r'(?P.\S+) (?P.\S+) (?P0|.\S+).\s*' r'(?P.+)'), string) if not m: return None return m.groupdict() @staticmethod def mergeMapLine(string, procMap, onlyExec=False, saveAll=False): d = FileAnalyzer.parseMapLine(string) if not d: return # get execution permission # if d['perm'][-2] == '-': isExec = False else: isExec = True # check execution permission # if onlyExec and not isExec: return fileName = d['binName'] if fileName.startswith('['): fileName = fileName[1:-1] startAddr = long(d['startAddr'], 16) endAddr = long(d['endAddr'], 16) newOffset = long(d['offset'], 16) newSize = endAddr - startAddr # handle discontiguous segments # if fileName in procMap and \ procMap[fileName]['vend'] != startAddr: cnt = 0 while 1: newFileName = \ '%s%s%s' % (fileName, SysMgr.magicStr, cnt) # check next segment is contiguous with this line # if newFileName in procMap and \ procMap[newFileName]['vend'] != startAddr: cnt += 1 continue else: break fileName = newFileName # merge map line # FileAnalyzer.addMapLine(procMap, fileName, newOffset, newSize) # apply attributes # if saveAll: procMap[fileName]['perm'] = d['perm'] procMap[fileName]['devid'] = d['devid'] procMap[fileName]['inode'] = d['inode'] procMap[fileName]['offset'] = d['offset'] # set mapped addr # if procMap[fileName]['vstart'] == 0: procMap[fileName]['vstart'] = startAddr # set executable flag # if 'exec' not in procMap[fileName] or \ not procMap[fileName]['exec']: procMap[fileName]['exec'] = isExec procMap[fileName]['vend'] = endAddr def printUsage(self): if not self.procData: SysMgr.printErr('no process profiled') sys.exit(0) if not self.fileData: SysMgr.printErr('no file profiled') sys.exit(0) SysMgr.printLogo(big=True) # print system information # SysMgr.printInfoBuffer() # define alias # convert = UtilMgr.convSize2Unit convColor = UtilMgr.convColor pageSize = SysMgr.pageSize # Print process list # SysMgr.printPipe(( "[%s] [ Process : %d ] [ RAM: %s ]" "[ Keys: Foward/Back/Save/Quit ] [ Capture: Ctrl+\\ ]") % \ ('File Process Info', len(self.procData), convert(self.profPageCnt * 4 << 10))) SysMgr.printPipe(twoLine) SysMgr.printPipe( "{0:_^16}({1:_^6})|{2:_^13}|{3:_^16}({4:_^6}) |".\ format("Process", "PID", "RAM", "Thread", "TID")) SysMgr.printPipe(twoLine) procInfo = "{0:^16}({0:^6})|{0:12} |".format('') threadInfo = " {0:^16}({0:^6}) |".format('') procLength = len(procInfo) threadLength = len(threadInfo) lineLength = SysMgr.lineLength for pid, val in sorted(self.procData.items(), key=lambda e: long(e[1]['pageCnt']), reverse=True): try: rsize = val['pageCnt'] * pageSize except: SysMgr.printWarn( 'fail to get total mapped size for %s' % val['comm'], reason=True) continue if rsize > 0: rsize = convColor(convert(rsize), 'YELLOW', 12) printMsg = "{0:>16}({1:>6})|{2:>12} |".\ format(val['comm'][:SysMgr.commLen], pid, rsize) linePos = len(printMsg) for tid, threadVal in sorted(val['tids'].items(), reverse=True): threadInfo = \ "{0:^16}({1:>6}) |".format( threadVal['comm'][:SysMgr.commLen], tid) linePos += threadLength if linePos > lineLength: linePos = procLength + threadLength printMsg += "\n" + (' ' * (procLength - 1)) + '|' printMsg += threadInfo SysMgr.printPipe(printMsg) SysMgr.printPipe("%s\n\n" % oneLine) # Print file list # SysMgr.printPipe( "[%s] [ File: %d ] [ RAM: %s ] [ Keys: Foward/Back/Save/Quit ]" % \ ('File Usage Info', len(self.fileData), convert(self.profPageCnt * 4 << 10))) SysMgr.printPipe(twoLine) SysMgr.printPipe("{0:_^12}|{1:_^10}|{2:_^6}|{3:_^123}".\ format("RAM", "File", "%", "Library & Process")) SysMgr.printPipe(twoLine) for fileName, val in sorted(self.fileData.items(), key=lambda e: long(e[1]['pageCnt']), reverse=True): memSize = val['pageCnt'] * pageSize idx = val['totalSize'] + pageSize - 1 fileSize = long(idx / pageSize) * pageSize if fileSize != 0: per = long(long(memSize) / float(fileSize) * 100) if per >= SysMgr.cpuPerHighThreshold: per = UtilMgr.convColor(per, 'RED', 5) else: per = UtilMgr.convColor(per, 'YELLOW', 5) else: per = long(0) if memSize > 0: memSize = convColor(convert(memSize), 'YELLOW', 11) if not val['isRep']: continue else: SysMgr.printPipe(( "{0:>11} |{1:>9} |{2:>5} | {3:1} " "[Proc: {4:1}] [Link: {5:1}]").\ format(memSize, convert(fileSize), per, fileName, len(val['pids']), val['hardLink'])) # prepare for printing process list # pidInfo = '' lineLength = SysMgr.lineLength pidLength = len(" %16s (%6s) |" % ('', '')) indentLength = len("{0:>11} |{1:>9} |{2:>5} ".format('','','')) linePos = indentLength + pidLength # print hard-linked list # if val['hardLink'] > 1: for fileLink, tmpVal in val['linkList'].items(): if fileName != fileLink: SysMgr.printPipe( (' ' * indentLength) + '| -> ' + fileLink) # print process list # for pid, comm in val['pids'].items(): if linePos > lineLength: linePos = indentLength + pidLength pidInfo += '\n' + (' ' * indentLength) + '|' pidInfo += " %16s (%6s) |" % \ (comm[:SysMgr.commLen], pid) linePos += pidLength SysMgr.printPipe((' ' * indentLength) + '|' + pidInfo) SysMgr.printPipe(oneLine) SysMgr.printPipe('\n\n\n') def scanProcs(self): # get process list in proc filesystem # try: pids = os.listdir(SysMgr.procPath) except SystemExit: sys.exit(0) except: SysMgr.printOpenErr(SysMgr.procPath) sys.exit(0) # scan comms include words in target list # for pid in pids: try: long(pid) except: continue # make path of comm # procPath = "%s/%s" % (SysMgr.procPath, pid) commPath = "%s/%s" % (procPath, 'comm') pidComm = '' # make comm path of process # try: self.procData[pid]['comm'] except: try: fd = open(commPath, 'r') pidComm = fd.readline() pidComm = pidComm[0:len(pidComm) - 1] fd.close() except SystemExit: sys.exit(0) except: SysMgr.printOpenWarn(commPath) continue # make path of tid # taskPath = "%s/%s" % (procPath, 'task') try: tids = os.listdir(taskPath) except SystemExit: sys.exit(0) except: SysMgr.printOpenWarn(taskPath) continue # make thread list in process object # for tid in tids: try: long(tid) except: continue # make comm path of thread # threadPath = "%s/%s" % (taskPath, tid) commPath = "%s/%s" % (threadPath, 'comm') try: fd = open(commPath, 'r') comm = fd.readline() comm = comm[0:len(comm) - 1] fd.close() except SystemExit: sys.exit(0) except: SysMgr.printOpenWarn(commPath) continue # save process info # for val in self.target: if val in comm or tid == val: # access procData # try: self.procData[pid] except: self.procData[pid] = dict(self.init_procData) self.procData[pid]['tids'] = {} self.procData[pid]['procMap'] = {} self.procData[pid]['comm'] = pidComm # make or update mapInfo per process # self.procData[pid]['procMap'] = \ FileAnalyzer.getProcMapInfo(pid) # access threadData # try: self.procData[pid]['tids'][tid] except: self.procData[pid]['tids'][tid] = \ dict(self.init_threadData) self.procData[pid]['tids'][tid]['comm'] = comm def fillFileMaps(self): self.profPageCnt = long(0) for fileName, val in self.fileData.items(): if val['fileMap'] and val['isRep']: val['pageCnt'] = val['fileMap'].count(1) self.profPageCnt += val['pageCnt'] pageSize = SysMgr.pageSize for pid, val in self.procData.items(): for fileName, mapInfo in val['procMap'].items(): if not self.fileData[fileName]['fileMap'] or not mapInfo: continue # convert address and size to index in mapping table # offset = mapInfo['offset'] - self.fileData[fileName]['offset'] offset = \ long((offset + pageSize - 1) / pageSize) size = \ long((mapInfo['size'] + pageSize - 1) / pageSize) mapInfo['fileMap'] = \ list(self.fileData[fileName]['fileMap'][offset:size]) mapInfo['pageCnt'] = mapInfo['fileMap'].count(1) val['pageCnt'] += mapInfo['pageCnt'] def mergeFileMapInfo(self): for pid, val in self.procData.items(): for fileName, scope in val['procMap'].items(): newOffset = scope['offset'] newSize = scope['size'] # merge map line # FileAnalyzer.addMapLine( self.fileData, fileName, newOffset, newSize) # add pid into file info # if not self.fileData[fileName]['pids']: self.fileData[fileName]['pids'] = dict() if not pid in self.fileData[fileName]['pids']: self.fileData[fileName]['pids'][pid] = val['comm'] def getFilePageMaps(self): pageSize = SysMgr.pageSize self.profSuccessCnt = long(0) self.profFailedCnt = long(0) for fileName, val in self.fileData.items(): if not fileName.startswith('/'): continue elif fileName.startswith('/dev'): SysMgr.printWarn( "skip analyzing %s because it is device node" % fileName) continue if len(self.intervalFileData) > 0: # use file descriptor already saved as possible # try: fileData = self.intervalFileData fileInfo = \ fileData[len(self.intervalFileData) - 1][fileName] val['fd'] = fileInfo['fd'] val['totalSize'] = fileInfo['totalSize'] val['isRep'] = fileInfo['isRep'] except SystemExit: sys.exit(0) except: pass if not val['isRep']: continue if not val['fd']: ''' no fd related to this file case 1) no opened case 2) closed by mincore error case 3) closed because of rlimit ''' try: # check whether pages are on memory or not # stat = os.stat(fileName) devid = stat.st_dev inode = stat.st_ino # check whether this file was profiled or not # if inode in self.inodeData: found = False repFile = '' fileList = {} procList = dict(val['pids'].items()) for fileIdx, fileDevid in self.inodeData[inode].items(): # this hard-lined file was already profiled # if devid == fileDevid: found = True # add file into same file list # fileList[fileName] = True fileList[fileIdx] = True # merge process list related to this file # procList = \ dict(procList.items() + \ self.fileData[fileIdx]['pids'].items()) if self.fileData[fileIdx]['isRep']: repFile = fileIdx if found: self.inodeData[inode][fileName] = devid self.fileData[fileName]['isRep'] = False hardLinkCnt = len(fileList) # set representative file # for fileIdx, value in fileList.items(): self.fileData[fileIdx]['repFile'] = repFile self.fileData[fileIdx]['hardLink'] = hardLinkCnt # assign merged process list to representative file # self.fileData[repFile]['pids'] = procList self.fileData[repFile]['hardLink'] = hardLinkCnt if self.fileData[repFile]['linkList']: linkList = self.fileData[repFile]['linkList'] self.fileData[repFile]['linkList'] = \ dict(linkList.items() + fileList.items()) else: self.fileData[repFile]['linkList'] = fileList continue else: self.inodeData[inode][fileName] = devid else: self.inodeData[inode] = dict(self.init_inodeData) self.inodeData[inode][fileName] = devid size = stat.st_size linkCnt = stat.st_nlink time = stat.st_atime val['inode'] = inode val['totalSize'] = size val['linkCnt'] = linkCnt val['accessTime'] = time fd = open(fileName, "r") val['fd'] = fd except SystemExit: sys.exit(0) except: self.profFailedCnt += 1 if SysMgr.warnEnable: SysMgr.printOpenWarn(fileName) continue # check file size whether it is readable or not # if val['totalSize'] <= 0: self.profFailedCnt += 1 if SysMgr.warnEnable: SysMgr.printWarn('fail to mmap %s' % fileName) continue # prepare variables for mincore syscall # fd = val['fd'].fileno() offset = val['offset'] size = val['size'] if SysMgr.guiderObj: # map a file to ram with PROT_NONE(0), MAP_SHARED(0x10) flags # mm = SysMgr.guiderObj.mmap(0, size, 0, 2, fd, offset) # pylint: disable=no-member # call mincore syscall by standard libc library # pagemap = SysMgr.guiderObj.mincore(mm, size) # pylint: disable=no-member # unmap # SysMgr.guiderObj.munmap(mm, size) # pylint: disable=no-member else: # get ctypes object # SysMgr.importPkgItems('ctypes') # map a file to ram with PROT_NONE(0), MAP_SHARED(0x10) flags # mm = SysMgr.libcObj.mmap( POINTER(c_char)(), size, 0, 2, fd, offset) # get the size of the table to map file segment # tsize = long((size + pageSize - 1) / pageSize); # make a pagemap table # pagemap = (tsize * c_ubyte)() # call mincore syscall by standard libc library # ret = SysMgr.libcObj.mincore( mm, size, cast(pagemap, POINTER(c_ubyte))) if ret < 0: pagemap = None # unmap # SysMgr.libcObj.munmap(mm, size) # save the on-memory file page table # if pagemap: try: if SysMgr.guiderObj: val['fileMap'] = \ [ord(pagemap[i]) for i in \ range(long(size / pageSize))] else: val['fileMap'] = \ [pagemap[i] for i in range(long(size / pageSize))] self.profSuccessCnt += 1 # fd resource is about to run out # if SysMgr.maxKeepFd < fd: val['fd'].close() val['fd'] = None except SystemExit: sys.exit(0) except: SysMgr.printWarn('fail to access %s' % fileName) val['fileMap'] = None self.profFailedCnt += 1 else: val['fd'].close() val['fd'] = None if len(self.fileData) > 0: SysMgr.printGood( 'profiled a total of %d files' % self.profSuccessCnt) else: SysMgr.printErr('fail to profile files') sys.exit(0) if self.profFailedCnt > 0: SysMgr.printWarn( 'fail to open a total of %d files' % self.profFailedCnt) class LogMgr(object): """ Manager for error log """ # define log level # LOG_EMERG = 0 LOG_ALERT = 1 LOG_CRIT = 2 LOG_ERR = 3 LOG_WARNING = 4 LOG_NOTICE = 5 LOG_INFO = 6 LOG_DEBUG = 7 # define syslog type # SYSLOG_ACTION_CLOSE = 0 SYSLOG_ACTION_OPEN = 1 SYSLOG_ACTION_READ = 2 SYSLOG_ACTION_READ_ALL = 3 SYSLOG_ACTION_READ_CLEAR = 4 SYSLOG_ACTION_CLEAR = 5 SYSLOG_ACTION_CONSOLE_OFF = 6 SYSLOG_ACTION_CONSOLE_ON = 7 SYSLOG_ACTION_CONSOLE_LEVEL = 8 SYSLOG_ACTION_SIZE_UNREAD = 9 SYSLOG_ACTION_SIZE_BUFFER = 10 # define journal type # SD_JOURNAL_LOCAL_ONLY = 1 << 0 SD_JOURNAL_RUNTIME_ONLY = 1 << 1 SD_JOURNAL_SYSTEM = 1 << 2 SD_JOURNAL_CURRENT_USER = 1 << 3 SD_JOURNAL_OS_ROOT = 1 << 4 SD_JOURNAL_SYSTEM_ONLY = SD_JOURNAL_SYSTEM def __init__(self, target='error'): if target == 'error': self.terminal = sys.stderr self.notified = False self.error = False else: # backup # SysMgr.backupFile(target) # open # try: self.terminal = open(target, 'w') self.error = True except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to open %s" % target, True) def write(self, message): try: self.terminal.write(message) self.terminal.flush() except SystemExit: sys.exit(0) except: return if self.error: return # check cache dir # if not os.path.exists(SysMgr.cacheDirPath): try: os.makedirs(SysMgr.cacheDirPath) except SystemExit: sys.exit(0) except: err = SysMgr.getErrMsg() SysMgr.printWarn(( 'fail to make %s directory because %s ' 'so that use /tmp dir') % \ (SysMgr.cacheDirPath, err), True) SysMgr.cacheDirPath = '/tmp' # set file path for error log # errorFile = '%s/guider.err' % SysMgr.cacheDirPath if not SysMgr.isWritable(errorFile): SysMgr.printWarn(( 'fail to get write permission for %s ' 'so that use /tmp/guider.err') % errorFile, True) SysMgr.cacheDirPath = '/tmp' errorFile = '%s/guider.err' % SysMgr.cacheDirPath try: if not self.notified: SysMgr.printErr(( 'please report %s file to ' 'https://github.com/iipeace/guider/issues') % \ errorFile) self.notified = True with open(errorFile, 'a') as fd: SysMgr.writeErr(fd, message) except SystemExit: sys.exit(0) except: self.error = True SysMgr.printOpenErr(errorFile) def flush(self): pass def __getattr__(self, attr): return getattr(self.terminal, attr) @staticmethod def lock(fd): if not SysMgr.isLinux: return try: SysMgr.importPkgItems('fcntl') lockf(fd, LOCK_EX, 1, 0, 0) except SystemExit: sys.exit(0) except: name = fd.name if fd else 'logger' reason = SysMgr.getErrMsg() print('\n[ERROR] fail to get lock for %s because %s' % \ (name, reason)) @staticmethod def unlock(fd): if not SysMgr.isLinux: return try: SysMgr.importPkgItems('fcntl') lockf(fd, LOCK_UN, 1, 0, 0) except SystemExit: sys.exit(0) except: name = fd.name if fd else 'logger' reason = SysMgr.getErrMsg() print('\n[ERROR] fail to free lock for %s because %s' % \ (name, reason)) @staticmethod def printSyslog(console=False): # open syslog file # try: if not SysMgr.syslogFd: SysMgr.syslogFd = open(SysMgr.syslogPath, 'r') except: SysMgr.printOpenErr(SysMgr.syslogPath) sys.exit(0) SysMgr.printInfo( "start printing syslog... [ STOP(Ctrl+c) ]") # set file posiion # SysMgr.syslogFd.seek(0) while 1: log = SysMgr.syslogFd.readline() if not UtilMgr.isValidStr(log): continue if SysMgr.outPath and console: print(log) SysMgr.printPipe(log, newline=False) @staticmethod def printJournal(console=False): # get ctypes object # SysMgr.importPkgItems('ctypes') ''' struct sd_journal { int toplevel_fd; char *path; char *prefix; char *namespace; OrderedHashmap *files; IteratedCache *files_cache; MMapCache *mmap; Location current_location; JournalFile *current_file; uint64_t current_field; Match *level0, *level1, *level2; pid_t original_pid; int inotify_fd; unsigned current_invalidate_counter, last_invalidate_counter; usec_t last_process_usec; unsigned generation; /* Iterating through unique fields and their data values */ char *unique_field; JournalFile *unique_file; uint64_t unique_offset; /* Iterating through known fields */ JournalFile *fields_file; uint64_t fields_offset; uint64_t fields_hash_table_index; char *fields_buffer; size_t fields_buffer_allocated; int flags; bool on_network:1; bool no_new_files:1; bool no_inotify:1; bool unique_file_lost:1; /* File we were iterating over got removed, and there were no more files, so sd_j_enumerate_unique will return a value equal to 0. */ bool fields_file_lost:1; bool has_runtime_files:1; bool has_persistent_files:1; size_t data_threshold; Hashmap *directories_by_path; Hashmap *directories_by_wd; Hashmap *errors; }; ''' # load libsystemd library # try: if not SysMgr.systemdObj: SysMgr.systemdObj = SysMgr.loadLib(SysMgr.libsystemdPath) if not SysMgr.systemdObj: raise Exception("no %s" % SysMgr.libsystemdPath) func = 'sd_journal_open' if not hasattr(SysMgr.systemdObj, func): raise Exception( 'no %s in %s' % (func, SysMgr.libsystemdPath)) except: SysMgr.printErr( "fail to print journal", True) sys.exit(0) # define shortcut for object # systemdObj = SysMgr.systemdObj # open journal # jrl = c_void_p(0) flag = LogMgr.SD_JOURNAL_LOCAL_ONLY res = systemdObj.sd_journal_open(byref(jrl), c_int(flag)) if res < 0: SysMgr.printErr( "fail to print journal because no journal") return SysMgr.printInfo( "start printing journal... [ STOP(Ctrl+c) ]") # set head # res = systemdObj.sd_journal_seek_head(jrl) if res < 0: SysMgr.printErr( "fail to print journal because no journal head") return # initialize variables # data = c_void_p(0) size = c_size_t(0) usec = c_uint64(0) timeout = c_uint64(10000) # set fields # if SysMgr.inputParam: fieldList = SysMgr.inputParam.split(',') else: fieldList = \ [b"_TIME", b"_HOSTNAME", b"_TRANSPORT", b"_COMM", b"_PID", b"MESSAGE"] # move to the end of journal # if not SysMgr.showAll: systemdObj.sd_journal_seek_tail(jrl) # define summary table # table = {} SysMgr.printPipe('\n') # start reading journal in loop # try: while 1: res = systemdObj.sd_journal_next(jrl) if res == 0: ret = systemdObj.sd_journal_wait(jrl, timeout) # SD_JOURNAL_NOP / SD_JOURNAL_APPEND / SD_JOURNAL_INVALID # if ret == 0 or ret == 1 or ret == 2: continue elif ret < 0: break elif res < 1: break # traverse specific fields # if SysMgr.inputParam: res = systemdObj.sd_journal_restart_data(jrl) while 1: res = systemdObj.sd_journal_enumerate_data( jrl, byref(data), byref(size)) if res < 1: break SysMgr.printPipe( cast(data, c_char_p).value.decode('latin-1'), flush=True) SysMgr.printPipe(flush=True) continue # traverse all fields # jrlStr = b'' for field in fieldList: if field == b'_TIME': # get time # ret = systemdObj.sd_journal_get_realtime_usec( jrl, byref(usec)) if ret < 0: realtime = 0 else: realtime = usec.value wtime = time.strftime( '%m %d %H:%M:%S ', time.localtime(realtime / float(1000000))) ''' ret = systemdObj.sd_journal_get_monotonic_usec( jrl, byref(usec), boottime) ''' # set time # jrlStr += wtime.encode() continue res = systemdObj.sd_journal_get_data( jrl, field, byref(data), byref(size)) if res < 0: continue val = cast(data, c_char_p).value[len(field)+1:] if field == b"_COMM": if SysMgr.outPath: comm = val.decode('latin-1').rstrip('\x01') table.setdefault(comm, 0) table[comm] += 1 elif field == b"_PID": val = b'[%s]: ' % val elif field == b"_TRANSPORT" and val == b"kernel": val += b': ' else: val += b' ' jrlStr += val # print journal # if jrlStr: try: decstr = jrlStr.decode('latin-1') if not UtilMgr.isValidStr(decstr): raise Exception() if SysMgr.outPath and console: print(decstr) SysMgr.printPipe(decstr, flush=True) except SystemExit: sys.exit(0) except: SysMgr.printPipe(jrlStr, flush=True) # close journal # systemdObj.sd_journal_close(jrl) except SystemExit: if not table: return SysMgr.printPipe( '\n[Journal Summary]\n%s\n' % twoLine) SysMgr.printPipe( '{0:>32} {1:>16}\n{2:1}'.format( 'COMM', 'COUNT', oneLine)) total = 0 for comm, count in sorted(table.items(), key=lambda x:x[1], reverse=True): SysMgr.printPipe( '{0:>32} {1:>16}'.format(comm, UtilMgr.convNum(count))) total += count SysMgr.printPipe( '\n{0:>32} {1:>16}\n{2:1}'.format( 'TOTAL', UtilMgr.convNum(total), oneLine)) @staticmethod def getKmsg(line=0): try: fd = os.open(SysMgr.kmsgPath, os.O_RDONLY | os.O_NONBLOCK) except: return None logs = list() while 1: try: data = os.read(fd, SysMgr.pageSize).decode() logs.append(data) except SystemExit: sys.exit(0) except: break # convert logs # retList = list() for log in logs[-line:]: # parse log # pos = log.find(';') meta = log[:pos].split(',') if len(meta) > 2: nrLevel = long(meta[0]) try: level = ConfigMgr.LOG_LEVEL[nrLevel] except: level = nrLevel # time # ltime = str(meta[2]) if len(ltime) < 7: ltime = '0.%s' % ltime else: ltime = '%s.%s' % (ltime[:-6], ltime[-6:]) # name & log # log = log[pos + 1:] npos = log.find(':') name = log[:npos] if log[-1] == '\n': log = log[npos + 1:-1] else: log = log[npos + 1:] retList.append('[%s] (%s) %s: %s' % (ltime, level, name, log)) return retList[-line:] @staticmethod def printKmsg(console=False): # open kmsg device node # try: if not SysMgr.kmsgFd: SysMgr.kmsgFd = open(SysMgr.kmsgPath, 'r') except: SysMgr.printOpenErr(SysMgr.kmsgPath) sys.exit(0) SysMgr.printInfo( "start printing kernel log... [ STOP(Ctrl+c) ]") # check device node # try: SysMgr.kmsgFd.readline() except SystemExit: sys.exit(0) except: SysMgr.kmsgFd = None # syslog # if not SysMgr.kmsgFd: # get ctypes object # SysMgr.importPkgItems('ctypes') # get kernel ring-buffer size # size = SysMgr.syscall( 'syslog', LogMgr.SYSLOG_ACTION_SIZE_BUFFER, 0, 0) # allocate buffer # buf = (c_char*size)() ret = SysMgr.syscall( 'syslog', LogMgr.SYSLOG_ACTION_READ_ALL, buf, size) if ret > 0: logBuf = memoryview(buf).tobytes().decode() for line in logBuf.split('\n'): if not UtilMgr.isValidStr(line): continue SysMgr.printPipe(line) while 1: memset(buf, 0, size) ret = SysMgr.syscall( 'syslog', LogMgr.SYSLOG_ACTION_READ, buf, size) if ret < 1: continue logBuf = memoryview(buf).tobytes().decode() if not UtilMgr.isValidStr(line): continue if SysMgr.outPath and console: print(logBuf) SysMgr.printPipe(logBuf) return # change file position # try: SysMgr.kmsgFd.seek(0) except: pass # kmsg node # while 1: jsonResult = dict() log = SysMgr.kmsgFd.readline() if not UtilMgr.isValidStr(log): continue # parse log # pos = log.find(';') meta = log[:pos].split(',') if len(meta) > 2: nrLevel = long(meta[0]) try: level = ConfigMgr.LOG_LEVEL[nrLevel] except: level = nrLevel # time # ltime = str(meta[2]) if len(ltime) < 7: ltime = '0.%s' % ltime else: ltime = '%s.%s' % (ltime[:-6], ltime[-6:]) # name & log # log = log[pos + 1:] npos = log.find(':') name = log[:npos] if log[-1] == '\n': log = log[npos + 1:-1] else: log = log[npos + 1:] if SysMgr.jsonEnable: jsonResult = \ dict(time=ltime, level=level, name=name, log=log) else: if not SysMgr.outPath: level = UtilMgr.convColor(level, 'BOLD') name = UtilMgr.convColor(name, 'SPECIAL') ltime = UtilMgr.convColor(ltime, 'GREEN') log = '[%s] (%s) %s: %s' % (ltime, level, name, log) # apply filter # if SysMgr.filterGroup: found = False for string in SysMgr.filterGroup: if string in log: found = True break if not found: continue if SysMgr.jsonEnable: jsonResult = UtilMgr.convDict2Str(jsonResult) SysMgr.printPipe(jsonResult) else: if SysMgr.outPath and console: print(log[:-1]) SysMgr.printPipe(log[:-1]) @staticmethod def doLogKmsg(msg=None, level=None): # open kmsg device node # try: if not SysMgr.kmsgFd: SysMgr.kmsgFd = open(SysMgr.kmsgPath, 'w') except: SysMgr.printOpenErr(SysMgr.kmsgPath) sys.exit(0) try: SysMgr.kmsgFd.write(msg) SysMgr.kmsgFd.flush() except: SysMgr.printWarn( "fail to write kmsg", reason=True) return 0 @staticmethod def doLogSyslog(msg=None, level=None): if not msg: return # load libc # SysMgr.loadLibcObj(exit=True) if level is None: level = LogMgr.LOG_NOTICE SysMgr.libcObj.syslog(level, msg.encode()) return 0 @staticmethod def doLogJournal(msg=None, level=None): # get ctypes object # SysMgr.importPkgItems('ctypes') if not msg: return if level is None: level = LogMgr.LOG_NOTICE # load libsystemd library # try: if not SysMgr.systemdObj: SysMgr.systemdObj = SysMgr.loadLib(SysMgr.libsystemdPath) if not SysMgr.systemdObj: raise Exception("no %s" % SysMgr.libsystemdPath) func = 'sd_journal_print' if not hasattr(SysMgr.systemdObj, func): raise Exception( 'no %s in %s' % (func, SysMgr.libsystemdPath)) except: SysMgr.printErr( "fail to log journal", True) sys.exit(0) return SysMgr.systemdObj.sd_journal_print(level, msg.encode()) class SysMgr(object): """ Manager for system """ arch = None origArgs = [] kernelVersion = None isLinux = True isAndroid = False drawMode = False archOption = None # page size # try: pageSize = os.sysconf("SC_PAGE_SIZE") except: pageSize = 4096 HZ = 250 # 4ms tick # try: if isLinux: TICK = os.sysconf(os.sysconf_names['SC_CLK_TCK']) else: TICK = long((1 / float(HZ)) * 1000) except: TICK = long((1 / float(HZ)) * 1000) startTime = long(0) startRunTime = long(0) blockSize = 512 bufferSize = -1 termGetId = None termSetId = None ttyRows = 43 ttyRowsMargin = 2 ttyCols = 156 encoding = None encodeEnable = True encodeB64Enable = False remoteRun = False magicStr = '@@@@@' launchBuffer = '' lineLength = 154 pid = long(0) comm = __module__ commLen = 16 masterPid = long(0) parentPid = long(0) prio = None funcDepth = long(0) maxPid = 32768 maxRdCnt = 1024 pidDigit = 5 stdlog = None stderr = sys.stderr packetSize = 32767 defaultPort = 5555 bgProcList = None waitDelay = 0.5 repeatInterval = long(0) repeatCount = long(0) progressCnt = long(0) wordSize = 4 maxInterval = 0 # threshold # cpuPerHighThreshold = 80 cpuPerLowThreshold = 10 memAvailPerThreshold = 10 memHighThreshold = 1024 memLowThreshold = 100 swapPerThreshold = 90 diskPerHighThreshold = 90 # path # procPath = '/proc' imagePath = None mountPath = None mountCmd = None cgroupPath = None drawFormat = 'svg' debugfsPath = '/sys/kernel/debug' cacheDirPath = '/var/log/guider' outFilePath = 'guider.out' confFileName = 'guider.conf' cmdFileName = 'guider.cmd' tmpPath = '/tmp' kmsgPath = '/dev/kmsg' nullPath = '/dev/null' syslogPath = '/var/log/syslog' lmkPath = '/sys/module/lowmemorykiller/parameters/minfree' pythonPath = sys.executable pyLibPath = None objdumpPath = [] rootPath = '' fontPath = None libdltPath = 'libdlt' libcPath = 'libc' libgobjPath = 'libgobject-2.0' libgioPath = 'libgio-2.0' libdbusPath = 'libdbus-1' libcppPath = 'libstdc++' libsystemdPath = 'libsystemd' libglesPath = 'libGLESv2' ldCachePath = '/etc/ld.so.cache' libdemanglePath = libcppPath environList = {} environ = {} eventLogPath = None inputFile = None outputFile = None inputParam = None outPath = None signalCmd = "trap 'kill $$' INT\nsleep 1d\n" saveCmd = None boundaryLine = None demangleEnable = True compressEnable = False generalInfoEnable = True nrTop = None pipeForPager = None printFd = None fileSuffix = None parsedAnalOption = False optionList = [] customCmd = [] userCmd = [] kernelCmd = [] udpListCache = None tcpListCache = None customEventList = [] userEventList = [] kernelEventList = [] perfEventChannel = {} perfTargetEvent = [] ignoreItemList = [] idList = [] perfEventData = {} commCache = {} commFdCache = {} fdCache = {} libCache = {} netAddrCache = {} cmdFileCache = {} cmdAttachCache = {} thresholdData = {} thresholdEventList = {} thresholdEventHistory = {} impPkg = {} impGlbPkg = {} skipImpPkg = {} exitFuncList = [] dltObj = None dltCtx = None shmObj = None systemdObj = None libcObj = None libgioObj = None libdbusObj = None libgObj = None libglesObj = None statvfsObj = None guiderObj = None libcppObj = None libdemangleObj = None matplotlibVersion = long(0) matplotlibDpi = 500 sigsetObj = None sigsetOldObj = None localServObj = None remoteServObj = None netlinkObj = None geAttr = [0] * 9 addrListForPrint = {} addrListForReport = {} maxCore = long(0) nrCore = long(0) utilProc = long(0) logSize = long(0) kmsgLine = long(100) curLine = long(0) totalLine = long(0) dbgEventLine = long(0) uptime = long(0) prevUptime = long(0) uptimeDiff = long(0) diskStats = [] prevDiskStats = [] netstat = '' prevNetstat = '' loadavg = '' netInIndex = -1 # log # printStreamEnable = False loggingEnable = False dltEnable = False kmsgEnable = False syslogEnable = False journalEnable = False terminalOver = False logoEnable = True colorEnable = True cpuAvgEnable = True reportEnable = False truncEnable = True countEnable = False reportObject = None reportFileEnable = False graphEnable = False procBuffer = [] fixedProcList = {} topInstance = None procInstance = {} fileInstance = {} sysInstance = None procBufferSize = long(0) bufferOverflowed = False bufferString = '' bufferList = [] bufferRows = long(0) systemInfoBuffer = '' kerSymTable = {} jsonData = {} nrTopRank = 10 layout = None avgEnable = False showAll = False optStrace = False disableAll = False intervalNow = long(0) recordStatus = False bgStatus = False condExit = False sort = None sortCond = None # file descriptor # maxFd = 512 maxKeepFd = maxFd - 16 statFd = None memFd = None zoneFd = None lmkFd = None irqFd = None softirqFd = None vmstatFd = None swapFd = None uptimeFd = None netstatFd = None netdevFd = None shmFd = None msgqFd = None semFd = None loadavgFd = None cmdFd = None diskStatsFd = None mountFd = None nullFd = None eventLogFd = None kmsgFd = None syslogFd = None # flags # fixTargetEnable = False irqEnable = False cpuEnable = True cloneEnable = True execEnable = None latEnable = cpuEnable gpuEnable = True memEnable = False rssEnable = False pssEnable = False ussEnable = False vssEnable = False oomEnable = False leakEnable = False wssEnable = False diskEnable = False heapEnable = False floatEnable = False fileTopEnable = False dltTopEnable = False dbusTopEnable = False ueventEnable = False keventEnable = False networkEnable = False schedEnable = False delayEnable = False stackEnable = False wchanEnable = False sigHandlerEnable = False wfcEnable = False affinityEnable = False freeMemEnable = False blockEnable = False lockEnable = False userEnable = True userRecordEnable = True userEnableWarn = True printEnable = True bufferLossEnable = False jsonEnable = False powerEnable = False binderEnable = False wqEnable = False i2cEnable = False pipeEnable = False depEnable = False sysEnable = False waitEnable = False inWaitStatus = False cmdEnable = False perfEnable = False perfGroupEnable = False resetEnable = False warnEnable = False logEnable = True ttyEnable = False selectEnable = True cgroupEnable = False cgTopEnable = False cmdlineEnable = False schedstatEnable = True intervalEnable = long(0) forceEnable = False functionEnable = False systemEnable = False fileEnable = False threadEnable = False nsEnable = False termFlag = True exitFlag = False tgidEnable = True taskEnable = True exceptCommFilter = False processEnable = True totalEnable = False groupProcEnable = False rankProcEnable = True inotifyEnable = False dwarfEnable = False barGraphEnable = False # Elastic Stack # elasticEnable = False cmdList = {} rcmdList = {} savedProcTree = {} savedProcComm = {} savedMountTree = {} preemptGroup = [] filterGroup = [] schedFilter = [] affinityFilter = [] killFilter = [] syscallList = [] perCoreList = [] perCoreDrawList = [] childList = {} pidFilter = None def __init__(self): if not SysMgr.isLinux: return SysMgr.sysInstance = self self.cpuInfo = {} self.cpuCacheInfo = {} self.memInfo = {} self.devInfo = {} self.diskInfo = {} self.mountInfo = {} self.networkInfo = {} self.systemInfo = {} self.partitionInfo = {} self.cpuData = None self.gpuData = {} self.memData = {} self.diskData = {} self.storageData = {} self.prevStorageData = {} self.ipcData = {} self.prevIpcData = {} self.userData = {} self.mountData = None self.loadData = None self.nrMaxThread = 0 self.cmdlineData = None self.osData = None self.devData = None self.procData = None self.macAddr = None self.uname = [] self.openFileData = {} self.limitData = [] # update starttime # SysMgr.updateUptime() if SysMgr.startTime == 0: SysMgr.startTime = \ SysMgr.startRunTime = \ SysMgr.uptime # resource update time # self.netUpdate = None self.storageUpdate = None self.ipcUpdate = None # save system info first # self.saveSysStat(False) def __del__(self): pass @staticmethod def writeErr(fd, log): LogMgr.lock(fd) try: fd.write(log) except SystemExit: sys.exit(0) except: return LogMgr.unlock(fd) @staticmethod def setErrorLogger(): if SysMgr.isLinux: sys.stderr = LogMgr() @staticmethod def getMaxPid(): path = '%s/sys/kernel/pid_max' % SysMgr.procPath try: with open(path, 'r') as fd: maxPid = fd.readline()[:-1] # update pid length # if len(maxPid) > SysMgr.pidDigit: SysMgr.pidDigit = len(maxPid) SysMgr.maxPid = long(maxPid) except SystemExit: sys.exit(0) except: pass @staticmethod def loadLibcObj(exit=False): if SysMgr.libcObj: return True try: ret = SysMgr.loadLib(SysMgr.libcPath) if ret: SysMgr.libcObj = ret return True else: SysMgr.printErr('fail to load libc') if exit: sys.exit(0) else: return False except SystemExit: sys.exit(0) except: return False @staticmethod def shrinkHeap(): if not SysMgr.isLinux: return # load libc # if not SysMgr.loadLibcObj(): return if not hasattr(SysMgr.libcObj, 'malloc_trim'): SysMgr.printWarn( 'no malloc_trim in %s' % SysMgr.libcPath) return # int malloc_trim (size_t pad) # SysMgr.libcObj.malloc_trim(0) @staticmethod def doLogMode(mode): if mode.upper() == 'KMSG': func = LogMgr.doLogKmsg mtype = 'kernel' elif mode.upper() == 'DLT': func = DltAnalyzer.doLogDlt mtype = 'DLT' elif mode.upper() == 'JOURNAL': func = LogMgr.doLogJournal mtype = 'journal' elif mode.upper() == 'SYSLOG': func = LogMgr.doLogSyslog mtype = 'syslog' SysMgr.printLogo(big=True, onlyFile=True) # get message # if SysMgr.hasMainArg(): msg = SysMgr.getMainArg() elif SysMgr.inputParam: msg = SysMgr.inputParam else: SysMgr.printErr("no input message for %s" % mtype) sys.exit(0) # set alarm # if SysMgr.intervalEnable: signal.signal(signal.SIGALRM, SysMgr.onAlarm) signal.alarm(SysMgr.intervalEnable) while 1: ret = func(msg=msg) if ret == 0: SysMgr.printInfo( "logged a %s message '%s' successfully" % (mtype, msg)) else: SysMgr.printErr( "fail to log a %s message" % mtype) break if SysMgr.intervalEnable: SysMgr.waitEvent(forceExit=True) else: os._exit(0) @staticmethod def setMaxFd(): if not SysMgr.isLinux: return ''' maxFdPath = '%s/sys/fs/file-max' % SysMgr.procPath try: with open(maxFdPath, 'r') as fd: availMaxFd = long(fd.read()) except: availMaxFd = SysMgr.maxFd if availMaxFd == SysMgr.maxFd: return ''' # try to set maxFd with hard limit # try: resource = SysMgr.getPkg('resource', False, True) if resource: resource.setrlimit(resource.RLIMIT_NOFILE, (1048576, 1048576)) soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE) SysMgr.maxFd = hard SysMgr.maxKeepFd = SysMgr.maxFd - 16 return except SystemExit: sys.exit(0) except: pass # try to get maxFd by native call # try: func = SysMgr.guiderObj.getrlimit # pylint: disable=no-member SysMgr.maxFd = \ func(ConfigMgr.RLIMIT_TYPE.index('RLIMIT_NOFILE')) SysMgr.maxKeepFd = SysMgr.maxFd - 16 return except SystemExit: sys.exit(0) except: pass # get ctypes object # if not SysMgr.importPkgItems('ctypes', False): return class rlimit(Structure): _fields_ = ( ("rlim_cur", c_ulong), ("rlim_max", c_ulong), ) # try to get maxFd by standard library call # try: # load libc # SysMgr.loadLibcObj() SysMgr.libcObj.getrlimit.argtypes = (c_int, POINTER(rlimit)) SysMgr.libcObj.getrlimit.restype = c_int rlim = rlimit() rlim.rlim_cur = c_ulong(1048576) rlim.rlim_max = c_ulong(1048576) ret = SysMgr.libcObj.setrlimit( ConfigMgr.RLIMIT_TYPE.index('RLIMIT_NOFILE'), byref(rlim)) ret = SysMgr.libcObj.getrlimit( ConfigMgr.RLIMIT_TYPE.index('RLIMIT_NOFILE'), byref(rlim)) SysMgr.maxFd = rlim.rlim_cur SysMgr.maxKeepFd = SysMgr.maxFd - 16 except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to get the maximum file descriptor", reason=True) @staticmethod def setReportAttr(): # get argument # if SysMgr.hasMainArg(): SysMgr.inputFile = SysMgr.getMainArg() elif SysMgr.inputParam: SysMgr.inputFile = SysMgr.inputParam else: SysMgr.inputFile = 'guider.dat' if not SysMgr.outPath: SysMgr.outPath = \ '%s.out' % os.path.splitext(SysMgr.inputFile)[0] @staticmethod def execSystemView(): # parse all options and make output file path # SysMgr.parseAnalOption() SysMgr.printStat( r'start recording... [ STOP(Ctrl+c), MARK(Ctrl+\) ]') # wait for user input # SysMgr.waitEvent() # save system info # SysMgr.sysInstance.saveSysStat() # get and remove process tree from data file # SysMgr.getProcTreeInfo() SysMgr.printLogo(big=True) # print system information # SysMgr.printPipe(SysMgr.systemInfoBuffer) @staticmethod def setRecordAttr(): # function # if SysMgr.checkMode('funcrec'): SysMgr.functionEnable = True # file # elif SysMgr.checkMode('filerec'): SysMgr.fileEnable = True # syscall # elif SysMgr.checkMode('sysrec'): SysMgr.sysEnable = True SysMgr.cpuEnable = False # general # elif SysMgr.checkMode('genrec'): SysMgr.systemEnable = True # update record status # SysMgr.recordStatus = True SysMgr.inputFile = '/sys/kernel/debug/tracing/trace' # change priority for process # if not SysMgr.prio: SysMgr.setPriority(SysMgr.pid, 'C', -20) SysMgr.parseRecordOption() SysMgr.printProfileOption() SysMgr.printProfileCmd() @staticmethod def getFd(fname, perm='rb'): if fname in SysMgr.fdCache and \ SysMgr.fdCache[fname]['perm'] == perm: return SysMgr.fdCache[fname]['fd'] try: SysMgr.fdCache[fname] = { 'fd': open(fname, perm), 'perm': perm, } return SysMgr.fdCache[fname]['fd'] except SystemExit: sys.exit(0) except: SysMgr.printOpenErr(fname) return None @staticmethod def setVisualAttr(): # set default input path # if len(sys.argv) <= 2: sys.argv.insert(2, SysMgr.outFilePath) SysMgr.graphEnable = True # ignore user warning # SysMgr.ignoreWarn() # apply regular expression for first path # flist = UtilMgr.convPath(sys.argv[2]) if type(flist) is list and len(flist) > 0: sys.argv = sys.argv[:2] + flist + sys.argv[3:] # thread draw mode # if TaskAnalyzer.getInitTime(sys.argv[2]) > 0: # apply launch option # SysMgr.applyLaunchOption() # check data type # if SysMgr.isThreadMode(): pass elif SysMgr.isFuncMode(): SysMgr.printErr( "fail to draw because this data is for function") sys.exit(0) else: SysMgr.printErr( "fail to draw because this data is not supported") sys.exit(0) SysMgr.inputFile = sys.argv[1] = sys.argv[2] SysMgr.intervalEnable = 1 if not SysMgr.outPath: SysMgr.outPath = \ '%s.out' % os.path.splitext(SysMgr.inputFile)[0] del sys.argv[2] # top draw mode # else: # CPU # if SysMgr.checkMode('drawcpu') or \ SysMgr.checkMode('drawcpuavg'): SysMgr.layout = 'CPU' # delay # elif SysMgr.checkMode('drawdelay'): SysMgr.layout = 'DELAY' # memory # elif SysMgr.checkMode('drawmem') or \ SysMgr.checkMode('drawmemavg'): SysMgr.layout = 'MEM' # VSS # elif SysMgr.checkMode('drawvss') or \ SysMgr.checkMode('drawvssavg'): SysMgr.layout = 'MEM' SysMgr.vssEnable = True # RSS # elif SysMgr.checkMode('drawrss') or \ SysMgr.checkMode('drawrssavg'): SysMgr.layout = 'MEM' SysMgr.rssEnable = True # leak # elif SysMgr.checkMode('drawleak'): SysMgr.layout = 'MEM' SysMgr.leakEnable = True # I/O # elif SysMgr.checkMode('drawio'): SysMgr.layout = 'IO' # average # if SysMgr.isDrawAvgMode(): SysMgr.avgEnable = True # modify args for drawing multiple input files # sys.argv[1] = 'top' args = sys.argv[2:] SysMgr.inputParam = UtilMgr.getFileList(args) @staticmethod def execFileAnalysis(): SysMgr.checkRootPerm() # parse analysis option # SysMgr.parseAnalOption() SysMgr.printStat( r'start analyzing... [ STOP(Ctrl+c), MARK(Ctrl+\) ]') # start analyzing files # try: pi = FileAnalyzer() except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to analyze memory-mapped files", reason=True) sys.exit(0) # save system info # SysMgr.sysInstance.saveSysStat() # get and remove process tree from data file # SysMgr.getProcTreeInfo() if SysMgr.intervalEnable == 0: # print total file usage per process # pi.printUsage() else: # print file usage per process on timeline # pi.printIntervalInfo() @staticmethod def execRecordLoop(): while SysMgr.repeatInterval > 0: # set alarm # signal.alarm(SysMgr.repeatInterval) # get init time in buffer for verification # initTime = TaskAnalyzer.getInitTime(SysMgr.inputFile) # wait for timer # try: for cnt in range(0, SysMgr.repeatInterval): UtilMgr.printProgress(cnt, SysMgr.repeatInterval) time.sleep(1) except SystemExit: sys.exit(0) except: pass # real-time copy from pipe to file # if SysMgr.pipeEnable: if SysMgr.outputFile: SysMgr.copyPipeToFile( '%s%s' % (SysMgr.inputFile, '_pipe'), SysMgr.outputFile) else: SysMgr.printErr( "wrong option used, " "use also -s option to save data") sys.exit(0) # check counter # if SysMgr.repeatCount <= SysMgr.progressCnt and \ SysMgr.termFlag: sys.exit(0) # compare init time with now time for buffer verification # if initTime < TaskAnalyzer.getInitTime(SysMgr.inputFile): SysMgr.printErr( "buffer size is not enough (%sKB)" % \ SysMgr.getBufferSize()) sys.exit(0) else: SysMgr.clearTraceBuffer() # start writing logs to file through pipe # if SysMgr.pipeEnable: if SysMgr.outputFile: pipePath = '%s%s' % (SysMgr.inputFile, '_pipe') SysMgr.copyPipeToFile(pipePath, SysMgr.outputFile) else: SysMgr.printErr( "wrong option used, use also -s option to save data") sys.exit(0) if not SysMgr.graphEnable: # get init time from buffer for verification # initTime = TaskAnalyzer.getInitTime(SysMgr.inputFile) # wait for user input # while 1: if SysMgr.recordStatus: SysMgr.condExit = True SysMgr.waitEvent() if SysMgr.condExit: break else: break if not SysMgr.graphEnable: # compare init time with now time for buffer verification # if initTime < TaskAnalyzer.getInitTime(SysMgr.inputFile): SysMgr.printErr("buffer size %sKB is not enough" % \ SysMgr.getBufferSize()) sys.exit(0) # save system info # SysMgr.sysInstance.saveSysStat() @staticmethod def execTopCmd(): # check background processes # SysMgr.checkBgProcs() # set tty setting automatically # if not SysMgr.ttyEnable: SysMgr.setTTYAuto(True, False) # write user command # SysMgr.writeTraceCmd('BEFORE') # thread # if SysMgr.checkMode('ttop'): SysMgr.processEnable = False # file # elif SysMgr.checkMode('ftop'): SysMgr.fileTopEnable = True # cgroup # elif SysMgr.checkMode('cgtop'): SysMgr.cgTopEnable = True # stack # elif SysMgr.checkMode('stacktop'): if SysMgr.checkStackTopCond(): SysMgr.processEnable = False SysMgr.stackEnable = True else: sys.exit(0) # perf # elif SysMgr.checkMode('ptop'): if SysMgr.checkPerfTopCond(): SysMgr.perfEnable = True if SysMgr.findOption('g'): SysMgr.processEnable = False SysMgr.perfGroupEnable = True else: sys.exit(0) # mem # elif SysMgr.checkMode('mtop'): if SysMgr.checkMemTopCond(): SysMgr.memEnable = True SysMgr.sort = 'm' else: sys.exit(0) # WSS (working set size) # elif SysMgr.checkMode('wtop'): if SysMgr.checkWssTopCond(): SysMgr.memEnable = True SysMgr.wssEnable = True SysMgr.sort = 'm' else: sys.exit(0) # disk # elif SysMgr.checkMode('disktop'): if SysMgr.checkDiskTopCond(): SysMgr.diskEnable = True SysMgr.blockEnable = True SysMgr.sort = 'b' else: sys.exit(0) # all # elif SysMgr.checkMode('atop'): SysMgr.cpuEnable = True SysMgr.memEnable = True SysMgr.irqEnable = True SysMgr.diskEnable = True SysMgr.networkEnable = True if SysMgr.isRoot(): SysMgr.blockEnable = True SysMgr.perfEnable = True else: SysMgr.printWarn( 'block stat is disabled because of no root permission') # condition # elif SysMgr.checkMode('ctop'): # check path for config file # if not SysMgr.getOption('C'): if not SysMgr.loadConfig(SysMgr.confFileName): SysMgr.printErr( 'input effective file path for config') sys.exit(0) # ignore output # if not SysMgr.outPath: SysMgr.outPath = SysMgr.nullPath SysMgr.bufferSize = -1 # DLT # elif SysMgr.checkMode('dlttop'): SysMgr.dltTopEnable = True # D-Bus # elif SysMgr.checkMode('dbustop'): SysMgr.dbusTopEnable = True SysMgr.floatEnable = True # set default interval to 3 for performance # if not SysMgr.findOption('i') and \ not SysMgr.findOption('R'): SysMgr.intervalEnable = 3 # usercall # elif SysMgr.checkMode('utop'): SysMgr.doTrace('usercall') # pycall # elif SysMgr.checkMode('pytop'): SysMgr.doTrace('pycall') # breakcall # elif SysMgr.checkMode('btop'): SysMgr.doTrace('breakcall') # syscall # elif SysMgr.checkMode('systop'): SysMgr.doTrace('syscall') # network # elif SysMgr.checkMode('ntop'): SysMgr.networkEnable = True # background # elif SysMgr.checkMode('bgtop'): if not SysMgr.checkBgTopCond(): sys.exit(0) if SysMgr.isRoot(): SysMgr.blockEnable = True else: SysMgr.printWarn( 'block stat is disabled because of no root permission') SysMgr.diskEnable = True SysMgr.networkEnable = True SysMgr.runBackgroundMode() # report # elif SysMgr.checkMode('rtop'): SysMgr.jsonEnable = True if SysMgr.isRoot(): SysMgr.diskEnable = True SysMgr.networkEnable = True disableList = SysMgr.getOption('d') if disableList: if 'd' in disableList: SysMgr.diskEnable = False if 'n' in disableList: SysMgr.networkEnable = False else: SysMgr.printWarn( "fail to get stats for disk and network " "because of no root permission") if not SysMgr.checkRepTopCond(): sys.exit(0) # print profile option # if not SysMgr.isDrawMode(): SysMgr.printProfileOption() SysMgr.printProfileCmd() # set handler for exit # SysMgr.setNormalSignal() # run process / file monitoring # TaskAnalyzer() @staticmethod def loadLibCache(): try: if not os.path.exists(SysMgr.ldCachePath): raise Exception("no %s" % SysMgr.ldCachePath) libDict = {} libList = UtilMgr.convBin2Str(SysMgr.ldCachePath) for idx, item in enumerate(libList): try: if libList[idx+1].startswith('/'): value = libList[idx+1] libDict.setdefault(item, list()) libDict[item].append(value) except SystemExit: sys.exit(0) except: pass SysMgr.libCache = libDict except SystemExit: sys.exit(0) except: SysMgr.printWarn('fail to load library cache', reason=True) return False @staticmethod def findLib(lib, inc=False): if not SysMgr.libCache: SysMgr.loadLibCache() for key, val in SysMgr.libCache.items(): if not key.startswith(lib): continue if inc and key.startswith(lib): return val if (key[len(lib)] == '.' or key[len(lib)] == '-'): if len(val) > 1: SysMgr.printWarn( 'multiple libraries [ %s ] exist for %s' % \ (', '.join(val), key)) return val return None @staticmethod def getPrintFlag(): if 'QUIET' in SysMgr.environList: return False else: return True @staticmethod def loadLib(lib, path=False): if not SysMgr.importPkgItems('ctypes', False): return # absolute path # if path: return CDLL(lib) target = SysMgr.findLib(lib) if not target: target = ['%s.so' % lib] ret = FileAnalyzer.getMapFilePath(SysMgr.pid, lib) if ret: target.append(ret) for item in target: try: res = cdll.LoadLibrary(item) if res: return res except SystemExit: sys.exit(0) except: pass @staticmethod def importNative(): try: # do not use native library to improve initialization time # raise Exception import guider guider.check() # pylint: disable=no-member SysMgr.guiderObj = guider except: pass @staticmethod def applyKillVal(value): if not value: SysMgr.printErr("no value to send signal") sys.exit(0) SysMgr.checkRootPerm() jobs = value.split(',') for job in jobs: try: value = job.split(':') if len(value) > 3: raise Exception("wrong input") # set task # tid = value[0] # set signal # if len(value) == 1: sig = signal.SIGKILL else: sig = SysMgr.getSigNum(value[1]) if not sig: raise Exception("wrong signal %s" % value[1]) if len(value) > 2 and value[2].upper() == 'CONT': flag = 'CONT' else: flag = 'ONCE' SysMgr.killFilter.append([tid, sig, flag]) except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to set signal", True) sys.exit(0) @staticmethod def parseAffinityOption(jobs, launch=False): if not jobs: SysMgr.printErr("wrong option value") sys.exit(0) for origVal in jobs: try: value = origVal.split(':') if len(value) < 2 or len(value) > 3: raise Exception("wrong input") # set task # tid = value[0] if tid == '': tid = str(SysMgr.pid) # set mask # mask = value[1] if not mask: raise Exception('wrong input') if launch: sibling = SysMgr.groupProcEnable targetList = SysMgr.getPids(tid, sibling=sibling) targetList = list(map(long, targetList)) if targetList: SysMgr.setAffinity(mask, targetList) else: SysMgr.printWarn( "no thread related to '%s'" % tid) if len(value) == 3 and value[2].upper() == 'CONT': flag = 'CONT' else: flag = 'ONCE' SysMgr.affinityFilter.append([tid, mask, flag]) except SystemExit: sys.exit(0) except: SysMgr.printErr( "wrong option value '%s'" % origVal, True) sys.exit(0) @staticmethod def doDump(): # get argument # if SysMgr.hasMainArg(): inputParam = SysMgr.getMainArg() elif SysMgr.inputParam: inputParam = SysMgr.inputParam else: SysMgr.printErr("no input for COMM or PID") sys.exit(0) if not inputParam: SysMgr.printErr("no input for memory info") sys.exit(0) elif not SysMgr.outPath: SysMgr.printErr("no input for path") sys.exit(0) # convert comm to pid # targetList = [] for item in inputParam: targetList += SysMgr.getPids(item, isThread=False) targetList = list(set(targetList)) # check target # if not targetList: SysMgr.printErr("no target process") sys.exit(0) elif len(targetList) > 1: SysMgr.printErr( "found multiple tasks [%s]" % \ SysMgr.getCommList(targetList)) sys.exit(0) pid = targetList[0] meminfo = SysMgr.inputParam output = SysMgr.outPath # dump memory # Debugger.dumpTaskMemory(pid, meminfo, output) @staticmethod def doStrings(): # get argument # if SysMgr.hasMainArg(): inputParam = SysMgr.getMainArg() elif SysMgr.inputParam: inputParam = SysMgr.inputParam SysMgr.printErr("no input for path") sys.exit(0) SysMgr.setStream() SysMgr.printStat('start reading %s...' % inputParam) # convert binary file to string # clist = UtilMgr.convBin2Str(inputParam, pos=True) if not clist: SysMgr.printErr("no available string") return lastPos = sorted(clist.values())[-1] maxDigit = len(hex(lastPos)) # print strings # for string, pos in sorted(clist.items(), key=lambda e:e[1]): SysMgr.printPipe( '{0:>{digit}} {1}'.format(hex(pos), string, digit=maxDigit)) @staticmethod def doSetAffinity(): SysMgr.warnEnable = True # get argument # if SysMgr.hasMainArg(): value = SysMgr.getMainArg().split(',') elif SysMgr.filterGroup: value = SysMgr.filterGroup else: SysMgr.printErr( "fail to set CPU affinity of task because of no target") sys.exit(0) while 1: SysMgr.parseAffinityOption(value, launch=True) if SysMgr.intervalEnable: time.sleep(SysMgr.intervalEnable) else: break sys.exit(0) @staticmethod def importPkgItems(pkg, isExit=True): if pkg in SysMgr.impGlbPkg: return True module = SysMgr.getPkg(pkg, isExit) if not module: return False moduleDict = module.__dict__ try: importList = module.__all__ except SystemExit: sys.exit(0) except AttributeError: importList = \ [name for name in moduleDict if not name.startswith('_')] newDict = {} for name in importList: newDict[name] = moduleDict[name] globals().update(newDict) SysMgr.impGlbPkg[pkg] = True return True @staticmethod def applyThreshold(): def _getMaxInterval(node, maxVal=0): for key, item in node.items(): if type(item) is list: for subitem in item: if type(subitem) is not dict: continue val = _getMaxInterval(subitem, maxVal) if maxVal < val: maxVal = val elif type(item) is dict: val = _getMaxInterval(item, maxVal) if maxVal < val: maxVal = val elif key == 'interval' and UtilMgr.isNumber(item): item = long(item) if maxVal < item: maxVal = item return maxVal def _checkResource(item): try: if item['apply'] == 'true': return True except: pass if type(item) is list: for value in item: if _checkResource(value): return True elif type(item) is dict: for key, value in item.items(): if _checkResource(value): return True return False def _checkPerm(item): try: if item['apply'] == 'true' and \ item['perm'] == 'root': SysMgr.checkRootPerm(msg=item) except SystemExit: sys.exit(0) except: pass if type(item) is list: for value in item: _checkPerm(value) elif type(item) is dict: for key, value in item.items(): _checkPerm(value) if not 'threshold' in ConfigMgr.confData: return confData = SysMgr.getConfigDict('threshold') if not confData: return if type(confData) is not dict: return SysMgr.reportEnable = True SysMgr.rankProcEnable = False SysMgr.thresholdData = confData # check permission # _checkPerm(SysMgr.thresholdData) # check storage option # try: if _checkResource(SysMgr.thresholdData['storage']): SysMgr.diskEnable = True except SystemExit: sys.exit(0) except: pass # check network option # try: if _checkResource(SysMgr.thresholdData['net']): SysMgr.networkEnable = True except SystemExit: sys.exit(0) except: pass # update maximum interval # maxInterval = _getMaxInterval(confData) if maxInterval > SysMgr.maxInterval: SysMgr.maxInterval = maxInterval SysMgr.printInfo( "applied for thresholds from %s" % SysMgr.confFileName) SysMgr.printWarn(UtilMgr.convDict2Str(confData)) @staticmethod def doGetAffinity(): SysMgr.warnEnable = True # get argument # if SysMgr.hasMainArg(): value = SysMgr.getMainArg().split(',') elif SysMgr.filterGroup: value = SysMgr.filterGroup else: SysMgr.printErr( "fail to get CPU affinity of task because of no target") sys.exit(0) SysMgr.checkRootPerm() sibling = SysMgr.groupProcEnable targetList = [] try: for item in value: targetList += SysMgr.getPids(item, sibling=sibling) if not targetList: SysMgr.printErr( "no thread related to '%s'" % item) sys.exit(0) targetList = list(set(targetList)) targetList = list(map(long, targetList)) for tid in targetList: mask = SysMgr.getAffinity(tid) if not mask: SysMgr.printErr( "fail to get CPU affinity of %s(%s)" % \ (SysMgr.getComm(tid), tid)) else: SysMgr.printInfo( 'affinity of %s(%s) is %s' % \ (SysMgr.getComm(tid), tid, mask)) except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to get CPU affinity of task", True) sys.exit(0) @staticmethod def setStream(cut=True): if not cut: SysMgr.ttyCols = long(0) SysMgr.printStreamEnable = True SysMgr.encodeEnable = False @staticmethod def setAffinity(mask, pids, isProcess=False): # check root permission # if len(pids) == 1 and \ str(pids[0]).isdigit() and \ SysMgr.pid == long(pids[0]): pass elif not SysMgr.isRoot(): SysMgr.printWarn( "no root permission to set affinity") # check pid list # if UtilMgr.isNumber(pids): pids = [long(pids)] elif type(pids) is list: for pid in pids: if not str(pid).isdigit(): SysMgr.printErr('fail to recognize pid %s' % pid) return else: SysMgr.printErr('fail to recognize pid type') return # check mask type # try: mask = long(mask, 16) if mask == 0: SysMgr.printErr( 'fail to set mask to 0, use bit mask bigger than 0') return except: SysMgr.printErr('fail to recognize mask type') return # load libc # SysMgr.loadLibcObj(exit=True) # get the number of core # nrCore = SysMgr.getNrCore() for pid in pids: if isProcess: threadList = SysMgr.getThreadList(pid) else: threadList = [pid] for pid in threadList: try: if SysMgr.guiderObj: guiderObj = SysMgr.guiderObj ret = guiderObj.sched_setaffinity(long(pid), mask) # pylint: disable=no-member except SystemExit: sys.exit(0) except: pass try: SysMgr.libcObj.sched_setaffinity.argtypes = \ [c_int, c_ulong, POINTER(c_ulong)] ret = SysMgr.libcObj.sched_setaffinity( long(pid), nrCore, byref(c_ulong(((0x1 << nrCore) - 1) & mask))) except SystemExit: sys.exit(0) except: ret = -1 SysMgr.printWarn( "fail to set CPU affinity of tasks " "because of sched_setaffinity fail") if ret >= 0: SysMgr.printInfo( 'affinity of %s(%s) is changed to 0x%X' % \ (SysMgr.getComm(pid), pid, mask)) else: SysMgr.printErr( 'fail to set affinity of %s(%s) as 0x%X' % \ (SysMgr.getComm(pid), pid, mask)) @staticmethod def getAffinity(pid): try: return '0x%X' % \ SysMgr.guiderObj.sched_getaffinity(pid) # pylint: disable=no-member except SystemExit: sys.exit(0) except: pass # get ctypes object # if not SysMgr.importPkgItems('ctypes', False): return try: # load libc # if not SysMgr.loadLibcObj(): raise Exception('no libc') SysMgr.libcObj.sched_getaffinity.argtypes = \ [c_int, c_ulong, POINTER(c_ulong)] cpuset = c_ulong(0) size = long(1024 / (sizeof(c_ulong) * 8)) ret = SysMgr.libcObj.sched_getaffinity( long(pid), size, pointer(cpuset)) if ret >= 0: return hex(cpuset.value).rstrip('L') else: raise Exception('wrong affinity') except SystemExit: sys.exit(0) except: SysMgr.printWarn(( "fail to get CPU affinity of tasks " "because of sched_getaffinity fail")) @staticmethod def getMaxThread(): maxThdPath = '/proc/sys/kernel/threads-max' try: with open(maxThdPath, 'r') as fd: return long(fd.readline()[:-1]) except SystemExit: sys.exit(0) except: SysMgr.printErr( "fail to read %s" % maxThdPath, reason=True) return None @staticmethod def setOOMAdj(pid='self', pri='-17'): if not SysMgr.isLinux: return if not SysMgr.isRoot(): return # set path # oomPath = '%s/%s/oom_score_adj' % (SysMgr.procPath, pid) if not os.path.isfile(oomPath): # use deprecated path # oomPath = '%s/%s/oom_adj' % (SysMgr.procPath, pid) try: with open(oomPath, 'w') as fd: fd.write(pri) except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to write %s" % oomPath, reason=True) @staticmethod def ping(url=[], timeout=None, count=None): ICMP_ECHO_REQUEST = 8 def _checksum(source): sum = 0 countTo = (len(source)/2)*2 count = 0 while count < countTo: if type(source[count+1]) is long: data1 = source[count+1] else: data1 = ord(source[count+1]) if type(source[count]) is long: data2 = source[count] else: data2 = ord(source[count]) thisVal = data1*256 + data2 sum = sum + thisVal sum = sum & 0xffffffff # Necessary? count = count + 2 if countTo < len(source): sum = sum + ord(source[len(source) - 1]) sum = sum & 0xffffffff # Necessary? sum = (sum >> 16) + (sum & 0xffff) sum = sum + (sum >> 16) answer = ~sum answer = answer & 0xffff # Swap bytes. Bugger me if I know why # answer = answer >> 8 | (answer << 8 & 0xff00) return answer def _receivePing(sockList, timeout, sockInfo): select = SysMgr.getPkg('select') timeLeft = timeout while True: startedSelect = time.time() # wait for event # whatReady = select.select(sockList, [], [], timeLeft) # check timeout # if not whatReady[0]: return # get current time # timeReceived = time.time() howLongInSelect = (timeReceived - startedSelect) # check received packets # for sock in whatReady[0]: recPacket, addr = sock.recvfrom(1024) icmpHeader = recPacket[20:28] ptype, code, checksum, packetID, sequence = \ struct.unpack("bbHHh", icmpHeader) # get sent ID # ID = sockInfo[sock.fileno()][2] # check sent ID # if packetID != ID: continue # decode packet # bytesInDouble = struct.calcsize("d") timeSent = struct.unpack( "d", recPacket[28:28 + bytesInDouble])[0] # save times # delay = timeReceived - timeSent sockInfo[sock.fileno()].append(delay) sockList.pop(sockList.index(sock)) # finished # if not sockList: return # timeout # timeLeft = timeLeft - howLongInSelect if timeLeft <= 0: return def _sendPing(sock, destAddr, ID): socket = SysMgr.getPkg('socket') # Header: type(8), code(8), checksum(16), id(16), sequence(16) # checksumData = 0 # Make a dummy heder with a 0 checksum # header = struct.pack( "bbHHh", ICMP_ECHO_REQUEST, 0, checksumData, ID, 1) bytesInDouble = struct.calcsize("d") data = (192 - bytesInDouble) * "Q".encode() data = struct.pack("d", time.time()) + data # Calculate the checksum on the data and the dummy header. # checksumData = _checksum(header + data) ''' Now that we have the right checksum, we put that in. It's just easier to make up a new header than to stuff it into the dummy. ''' header = struct.pack( "bbHHh", ICMP_ECHO_REQUEST, 0, socket.htons(checksumData), ID, 1) packet = header + data sock.sendto(packet, (destAddr, 0)) def _convAddrs(addrList): def __expandAddrs(addrs, item): newAddrs = [] if item.isdigit(): if not addrs: newAddrs.append(item) else: for word in addrs: newAddrs.append('%s.%s' % (word, item)) elif item.count('-') == 1: start, end = item.split('-') if start.strip().isdigit() and end.strip().isdigit(): for idx in range(long(start), long(end)+1): if not addrs: newAddrs.append(idx) continue for word in addrs: newAddrs.append('%s.%s' % (word, idx)) else: if not addrs: newAddrs.append(item) else: for word in addrs: newAddrs.append('%s.%s' % (word, idx)) elif item == '*': for idx in range(1, 255): if not addrs: newAddrs.append(idx) else: for word in addrs: newAddrs.append('%s.%s' % (word, idx)) else: if not addrs: newAddrs.append(item) else: for word in addrs: newAddrs.append('%s.%s' % (word, item)) return newAddrs if not addrList: return addrList newAddrList = [] for addr in addrList: # digit address # checkAddr = addr.replace('.', '') if checkAddr.isdigit(): newAddrList.append(addr) continue # name address # checkAddr = checkAddr.replace('-', '').replace('*', '') if not checkAddr.isdigit(): newAddrList.append(addr) continue # convert addresses # addrs = [] fields = addr.split('.') for item in fields: addrs = __expandAddrs(addrs, item) # add addresses # newAddrList += addrs return newAddrList def _doPing(addrList, timeout, seq=None, verb=True): socket = SysMgr.getPkg('socket') # set attributes # try: ttl = 64 icmp = socket.getprotobyname("icmp") except: SysMgr.printErr('fail to ping', True) return 0 # define socket list # sockList = list() sockInfo = dict() # send packets # for idx, destAddr in enumerate(addrList): destIPAddr = socket.gethostbyname(destAddr) # create a socket # try: sock = socket.socket( socket.AF_INET, socket.SOCK_RAW, icmp) sock.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, ttl) except: SysMgr.printErr('fail to ping', True) return 0 # create an unique ID # ICMP_ID = (os.getpid()+idx) & 0xFFFF # send packet # _sendPing(sock, destIPAddr, ICMP_ID) # get address details # if destAddr == destIPAddr: addrInfo = destAddr else: addrInfo = '%s(%s)' % (destAddr, destIPAddr) # save sock info # sockList.append(sock) sockInfo[sock.fileno()] = [sock, addrInfo, ICMP_ID] # receive packet # _receivePing(sockList, timeout, sockInfo) # add timed out info and close all sockets # for name, attr in sockInfo.items(): if len(attr) <= 3: sockInfo[name].append(timeout) try: attr[0].close() except: pass # check return condition # if not verb: return # set sequence string # if seq is not None: seqstr = '[%s] ' % seq else: seqstr = '' # define json variable # if SysMgr.jsonEnable: jsonData = {'seq': seq, 'success': dict(), 'fail': dict()} timeoutstr = '' timeoutlinestr = '' # print results # for attr in sorted(sockInfo.values(), key=lambda x:x[3]): name = attr[1] elapsed = attr[3] # success # if elapsed < timeout: delay = attr[3] * 1000 if SysMgr.jsonEnable: jsonData['success'].setdefault(name, dict()) jsonData['success'][name]['time'] = delay continue name = UtilMgr.convColor(name, 'GREEN', 15, 'left') delaystr = UtilMgr.convColor('%.3f' % delay, 'YELLOW') SysMgr.printPipe( '%s%s: %s ms' % (seqstr, name, delaystr)) # timeout # else: if SysMgr.jsonEnable: jsonData['fail'].setdefault(name, dict()) jsonData['fail'][name]['time'] = timeout continue name = UtilMgr.convColor(name, 'RED', 15, 'left') if len(timeoutlinestr) + len(name) >= SysMgr.ttyCols: timeoutstr = '%s %s\n' % \ (timeoutstr, timeoutlinestr.lstrip()) timeoutlinestr = name else: timeoutlinestr = '%s %s' % (timeoutlinestr, name) # print results in JSON format # if SysMgr.jsonEnable: SysMgr.printPipe(UtilMgr.convDict2Str(jsonData)) elif timeoutlinestr: timeoutstr = '%s %s\n' % \ (timeoutstr, timeoutlinestr.lstrip()) # print timeout info # if timeoutstr: SysMgr.printPipe( '%stimeout:\n%s' % (seqstr, timeoutstr)) # check root permission for Linux # if SysMgr.isLinux and not SysMgr.isRoot(): SysMgr.printErr( 'fail to ping because of no root permission') return # get address list # urlList = [] if url: urlList = url elif SysMgr.hasMainArg(): urlList = SysMgr.getMainArg().split(',') urlList = UtilMgr.cleanItem(urlList) elif SysMgr.inputParam: try: files = SysMgr.inputParam.split(',') files = UtilMgr.cleanItem(files) for fname in files: with open(fname, 'r') as fd: urlList += fd.readlines() urlList = UtilMgr.cleanItem(urlList) except: SysMgr.printErr( "fail to read addresses from '%s'" % \ ','.join(files), True) sys.exit(0) # check input # if not urlList: SysMgr.printErr('no input for address') sys.exit(0) # convert addresses # urlList = _convAddrs(urlList) # set repeat count # if not count: if SysMgr.repeatInterval == 0: count = 1 else: count = SysMgr.repeatInterval SysMgr.printInfo( 'set repeat count to %s' % UtilMgr.convNum(count)) # set timeout # if not timeout: timeout = SysMgr.getOption('T') if timeout: try: timeout = float(timeout) except: SysMgr.printErr( "fail to set timeout '%s'" % timeout, True) sys.exit(0) else: timeout = 3 # set interval # interval = SysMgr.getOption('i') try: interval = float(interval) except: interval = 1 # print timeout info # timeoutstr = '%f' % timeout timeoutstr = timeoutstr.rstrip('0') if timeoutstr.endswith('.'): timeoutstr = timeoutstr[:-1] SysMgr.printInfo( 'set timeout to %s sec\n' % timeoutstr) # ping # for seq in xrange(0, count): try: _doPing(urlList, timeout, seq=seq) time.sleep(interval) except SystemExit: sys.exit(0) except: SysMgr.printErr( 'fail to send ping to %s', True) @staticmethod def getExeCmd(pid): cmd = SysMgr.getCmdline(pid, retList=True)[:2] if cmd[1][0] != '/': pwd = SysMgr.getCwd(pid) cmd[1] = '%s/%s' % (pwd, cmd[1]) return cmd @staticmethod def getConfigDict(name): confData = ConfigMgr.confData[name] if type(confData) is list: confData = UtilMgr.convStr2Dict('\n'.join(confData), True) if type(confData) is dict: return confData else: return None @staticmethod def getConfigList(name): confData = ConfigMgr.confData[name] if type(confData) is list: return confData else: return None @staticmethod def loadConfig(fname, verb=True): try: targetList = [] fd = None skip = False fd = open(fname, 'r') for line in fd.readlines(): if not line: continue line = line.strip() if not line or line == '\n': continue elif line.startswith('#') or line.startswith('//'): continue elif skip: if line.startswith("'''") or line.startswith('*/'): skip = False continue elif line.startswith("'''") or line.startswith('/*'): skip = True continue elif line.startswith('<') and line.endswith('>'): entry = line[1:-1] ConfigMgr.confData.setdefault(entry, list()) targetList = ConfigMgr.confData[entry] continue else: targetList.append(line) return ConfigMgr.confData except SystemExit: sys.exit(0) except: if verb: SysMgr.printErr( "fail to load config from '%s'" % fname, reason=True) return None finally: if fd: fd.close() @staticmethod def getCwd(pid): cwdPath = '%s/%s/cwd' % (SysMgr.procPath, pid) return os.readlink(cwdPath) @staticmethod def getPyLibPath(load=True): if SysMgr.pyLibPath: return SysMgr.pyLibPath try: # set library name # exePath = SysMgr.getExeName(SysMgr.pid) exeName = os.path.basename(exePath) libName = 'lib%s' % exeName if not load: return libName # search ld.so.cache # if not SysMgr.pyLibPath: SysMgr.pyLibPath = SysMgr.findLib(libName, inc=True)[0] # search standard path # else: libName = SysMgr.loadLib(libName)._name if libName: SysMgr.pyLibPath = \ FileAnalyzer.getMapFilePath(SysMgr.pid, libName) return SysMgr.pyLibPath except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to get path for python library", reason=True) @staticmethod def getExeName(pid): exePath = '%s/%s/exe' % (SysMgr.procPath, pid) try: return os.readlink(exePath) except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to get binary path for %s process" % pid, reason=True) return None @staticmethod def getCmdline(pid, retList=False): cmdlinePath = \ '%s/%s/cmdline' % (SysMgr.procPath, pid) try: with open(cmdlinePath, 'r') as fd: res = fd.readline() if retList: return res.split("\x00") else: return res.replace("\x00", " ").strip() except SystemExit: sys.exit(0) except: SysMgr.printOpenWarn(cmdlinePath) if retList: return [] else: return '' @staticmethod def getTracerId(pid): statusPath = \ '%s/%s/status' % (SysMgr.procPath, pid) try: with open(statusPath, 'r') as fd: for line in fd.readlines(): if line.startswith('TracerPid'): return long(line.split(':')[1].split()[0]) except SystemExit: sys.exit(0) except: return 0 @staticmethod def getUid(pid, itype='real'): try: path = '%s/status' % pid data = SysMgr.procReadlines(path) for line in data: if line.startswith('Uid'): if itype == 'real': idx = 0 elif itype == 'effective': idx = 1 elif itype == 'saved': idx = 2 elif itype == 'filesystem': idx = 3 return long(line.split(':')[1].split()[idx]) except SystemExit: sys.exit(0) except: comm = SysMgr.getComm(pid) SysMgr.printErr( 'fail to get UID for %s(%s)' % (comm, pid), reason=True) return 0 @staticmethod def getTgid(pid): statusPath = \ '%s/%s/status' % (SysMgr.procPath, pid) try: with open(statusPath, 'r') as fd: for line in fd.readlines(): if line.startswith('Tgid'): return line.split(':')[1].split()[0] except SystemExit: sys.exit(0) except: return None @staticmethod def resizeShm(shm, size): mmap = SysMgr.getPkg('mmap', False) if not mmap: return mmap.resize(size) @staticmethod def createShm(path=None, size=pageSize): if not SysMgr.isLinux: return mmap = SysMgr.getPkg('mmap', False) if not mmap: return return mmap.mmap(-1, size) @staticmethod def getCommList(pidList): try: commList = ['%s(%s)' % \ (SysMgr.getComm(pid), pid) for pid in pidList] return ', '.join(commList) except: return ', '.join(pidList) @staticmethod def getPwd(pid): pwdPath = \ '%s/%s/cwd' % (SysMgr.procPath, pid) pwd = None try: pwd = os.readlink(pwdPath) except SystemExit: sys.exit(0) except: return None return pwd @staticmethod def getComm(pid, cache=False, save=False): if pid in SysMgr.commCache: return SysMgr.commCache[pid] try: if pid in SysMgr.commFdCache: fd = SysMgr.commFdCache[pid] fd.seek(0) comm = fd.readline()[:-1] if save: SysMgr.commCache[pid] = comm return comm except SystemExit: sys.exit(0) except: pass # use psutil # if not SysMgr.isLinux: try: psutil = SysMgr.getPkg('psutil') return psutil.Process(pid).name() except: pass comm = None commPath = \ '%s/%s/comm' % (SysMgr.procPath, pid) try: fd = open(commPath, 'r') comm = fd.readline()[:-1] # cache comm # if save: SysMgr.commCache[pid] = comm # flush fd cache # if SysMgr.maxKeepFd < fd.fileno(): SysMgr.commFdCache = {} # cache fd # elif cache: SysMgr.commFdCache[pid] = fd else: fd.close() except SystemExit: sys.exit(0) except: return None return comm @staticmethod def getPyConfig(item='all', var=None): try: SysMgr.importPkgItems('sysconfig') if item == 'path': varDict = get_paths() else: varDict = get_config_vars() if var: return varDict[var] else: return varDict except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to get python config", True, True) return None @staticmethod def getMyBacktrace(): # load libc # SysMgr.loadLibcObj(exit=True) # define functions # libcObj = SysMgr.libcObj libcObj.backtrace.argtypes = [c_void_p, c_int] libcObj.backtrace.restype = c_int libcObj.backtrace_symbols.argtypes = [c_void_p, c_int] libcObj.backtrace_symbols.restype = POINTER(c_char_p) # define buffers # buf = (c_void_p*1024)() # call backtrace # ret = libcObj.backtrace(byref(buf), c_int(1024)) syms = libcObj.backtrace_symbols(byref(buf), c_int(ret)) sys.exit(0) @staticmethod def isBlkDev(path): stat = SysMgr.getPkg('stat') try: return stat.S_ISBLK(os.stat(path).st_mode) except: return False @staticmethod def dlopen(path): # load libc # if not SysMgr.loadLibcObj(): return try: path = path.encode() except: pass try: func = '__libc_dlopen_mode' funcp = getattr(SysMgr.libcObj, func) funcp.argtypes = [c_void_p, c_int] funcp.restype = c_ulong return funcp(path, 1) except: SysMgr.printErr("fail to call dlopen", reason=True) return None @staticmethod def setComm(comm): if not SysMgr.isLinux: return # try to set comm using native lib # try: SysMgr.guiderObj.prctl(15, comm, 0, 0, 0) # pylint: disable=no-member return except SystemExit: sys.exit(0) except: pass # load libc # if not SysMgr.loadLibcObj(): return try: SysMgr.libcObj.prctl( 15, c_char_p(comm.encode('utf-8')), 0, 0, 0) except SystemExit: sys.exit(0) except: SysMgr.printWarn( 'fail to set comm', True, reason=True) @staticmethod def getPicklePkg(isExit=True): pickle = SysMgr.getPkg('cPickle', isExit) if not pickle: pickle = SysMgr.getPkg('pickle', isExit) if not pickle: return None return pickle @staticmethod def isAlive(tid): try: statPath = "%s/%s/stat" % (SysMgr.procPath, tid) with open(statPath, 'r') as fd: stat = fd.read() # convert string to list # statList = stat.split(')')[1].split() if statList[0] == 'Z': return False else: return True except SystemExit: sys.exit(0) except: return False @staticmethod def getPkg(name, isExit=True, isTemp=False, isRoot=True): # check cache # try: return SysMgr.impPkg[name] except SystemExit: sys.exit(0) except: pass # check blacklist # if not isExit and name in SysMgr.skipImpPkg: return None # import package # try: obj = __import__(name, fromlist = [name] if isRoot else [None]) except SystemExit: sys.exit(0) except: SysMgr.printWarn( "fail to import python package: %s " % name, isExit) # register to blacklist # SysMgr.skipImpPkg[name] = True # check return condition # if isExit: sys.exit(0) return None # save package object # if not isTemp: SysMgr.impPkg[name] = obj return obj @staticmethod def getIowaitTime(dev=None): if not SysMgr.diskStats or \ not SysMgr.prevDiskStats: return '0/0' flist = {} dlist = {} curReadMsTotal = prevReadMsTotal = long(0) curWriteMsTotal = prevWriteMsTotal = long(0) curNrReadTotal = prevNrReadTotal = long(0) curNrWriteTotal = prevNrWriteTotal = long(0) curIoMsTotal = prevIoMsTotal = long(0) curWIoMsTotal = prevWIoMsTotal = long(0) # get total iowait time for read # for line in SysMgr.diskStats: items = line.split() dev = items[2] if not dev[-1].isdigit(): flist[dev] = None else: skip = False for item in flist: if item != dev and \ dev.startswith(item): skip = True if skip: continue dlist[dev] = dict() dlist[dev]['curNrRead'] = long(items[3]) dlist[dev]['curNrWrite'] = long(items[7]) dlist[dev]['curReadMs'] = long(items[6]) dlist[dev]['curWriteMs'] = long(items[10]) dlist[dev]['curIoMs'] = long(items[12]) dlist[dev]['curWIoMs'] = long(items[13]) curNrReadTotal += long(items[3]) curNrWriteTotal += long(items[7]) curReadMsTotal += long(items[6]) curWriteMsTotal += long(items[10]) curIoMsTotal += long(items[12]) curWIoMsTotal += long(items[13]) # get total iowait time for write # for line in SysMgr.prevDiskStats: items = line.split() dev = items[2] skip = False for item in flist: if item != dev and \ dev.startswith(item): skip = True if skip: continue dlist[dev]['prevNrRead'] = long(items[3]) dlist[dev]['prevNrWrite'] = long(items[7]) dlist[dev]['prevReadMs'] = long(items[6]) dlist[dev]['prevWriteMs'] = long(items[10]) dlist[dev]['prevIoMs'] = long(items[12]) dlist[dev]['prevWIoMs'] = long(items[13]) prevNrReadTotal += long(items[3]) prevNrWriteTotal += long(items[7]) prevReadMsTotal += long(items[6]) prevWriteMsTotal += long(items[10]) prevIoMsTotal += long(items[12]) prevWIoMsTotal += long(items[13]) for dev, stat in dlist.items(): read = stat['curNrRead'] - stat['prevNrRead'] write = stat['curNrWrite'] - stat['prevNrWrite'] io = read + write readMsTotal = curReadMsTotal - prevReadMsTotal writeMsTotal = curWriteMsTotal - prevWriteMsTotal ''' nrReadTotal = curNrReadTotal - prevNrReadTotal nrWriteTotal = curNrWriteTotal - prevNrWriteTotal ioMsTotal = curIoMsTotal - prevIoMsTotal wIoMsTotal = curWIoMsTotal - prevWIoMsTotal ''' retstr = '%s/%s' % ( UtilMgr.convSize2Unit(readMsTotal), UtilMgr.convSize2Unit(writeMsTotal)) return retstr @staticmethod def updateDiskStats(): try: SysMgr.diskStatsFd.seek(0) SysMgr.prevDiskStats = SysMgr.diskStats SysMgr.diskStats = SysMgr.diskStatsFd.readlines() except SystemExit: sys.exit(0) except: try: diskstatPath = '%s/diskstats' % SysMgr.procPath SysMgr.diskStatsFd = open(diskstatPath, 'r') SysMgr.diskStats = SysMgr.diskStatsFd.readlines() except SystemExit: sys.exit(0) except: SysMgr.printOpenWarn(diskstatPath) @staticmethod def getMountData(pid='self'): try: if pid != 'self': raise Exception() SysMgr.mountFd.seek(0) return SysMgr.mountFd.readlines() except SystemExit: sys.exit(0) except: try: mountPath = '%s/%s/mountinfo' % (SysMgr.procPath, pid) mountFd = open(mountPath, 'r') if pid == 'self': SysMgr.mountFd = mountFd return mountFd.readlines() except SystemExit: sys.exit(0) except: SysMgr.printOpenWarn(mountPath) @staticmethod def getMemStat(pid): try: statmPath = "%s/%s/statm" % (SysMgr.procPath, pid) with open(statmPath, 'r') as fd: return fd.readlines()[0].split() except SystemExit: sys.exit(0) except: SysMgr.printOpenWarn(statmPath) return @staticmethod def getPidFilter(): if not SysMgr.pidFilter: cmd = "" for cond in list(SysMgr.filterGroup): try: cmd += "common_pid == %s || " % long(cond) except: try: ldir = cond.find('>') if ldir == 0: cmd += "common_pid >= %s || " % long(cond[1:]) elif ldir == len(cond) - 1: cmd += "common_pid <= %s || " % long(cond[:-1]) rdir = cond.find('<') if rdir == 0: cmd += "common_pid <= %s || " % long(cond[1:]) elif rdir == len(cond) - 1: cmd += "common_pid >= %s || " % long(cond[:-1]) except SystemExit: sys.exit(0) except: pass if cmd != "": cmd = "(" + cmd[:cmd.rfind('||')] + ")" SysMgr.pidFilter = cmd return SysMgr.pidFilter @staticmethod def isExceptTarget(tid, tdata, comm=None, plist=[]): tlist = SysMgr.filterGroup # check filter # if tlist == []: return False # get comm # if not comm: comm = tdata[tid]['comm'] # check a thread # for item in tlist: if item == tid or \ item in comm or \ item == '' or \ SysMgr.isValidTid(tid, item): return False # check all threads in a same process # if SysMgr.groupProcEnable: tgid = tdata[tid]['tgid'] # check tgid in process list by tid # if str(tgid) in plist: return False # check tgid in filter list by tid # for item in tlist: try: if item == tgid or \ SysMgr.isValidTid(tgid, item): return False elif tgid == tdata[item]['tgid'] or \ tgid == SysMgr.savedProcTree[item]: return False except SystemExit: sys.exit(0) except: pass return True @staticmethod def getTraceItem(string): if SysMgr.tgidEnable: # record-tgid option # m = re.match(( r'^\s*(?P\S+)-(?P[0-9]+)\s+' r'\[(?P[0-9]+)\]\s+\(\s*(?P.+)\)\s+' r'(?P