#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = "Peace Lee"
__copyright__ = "Copyright 2015-2020, Guider"
__module__ = "guider"
__credits__ = "Peace Lee"
__license__ = "GPLv2"
__version__ = "3.9.7"
__revision__ = "200609"
__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 ctypes import *
    from copy import deepcopy
except ImportError:
    err = sys.exc_info()[1]
    print("[Error] Fail to import python default packages: %s" % err.args[0])
    sys.exit(0)

# convert types not supported #
try:
    range
except:
    range = range
try:
    long
except:
    long = int





class ConfigMgr(object):
    """ Manager for configuration """

    # 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 configuration 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',
        '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',
        'WARNING': '\033[95m',
        'OKBLUE': '\033[94m',
        'OKGREEN': '\033[92m',
        'SPECIAL': '\033[93m',
    }

    # 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 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",
        0x4: "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 = {
        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",
    }

    # 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 #
    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_getres": ("long", (
            ("clockid_t", "which_clock"),
            ("struct timespec *", "tp"),
        )),
        "clock_gettime": ("long", (
            ("clockid_t", "which_clock"),
            ("struct timespec *", "tp"),
        )),
        "clock_nanosleep": ("long", (
            ("clockid_t", "which_clock"),
            ("int", "flags"),
            ("const struct timespec *", "rqtp"),
            ("struct timespec *", "rmtp"),
        )),
        "clock_settime": ("long", (
            ("clockid_t", "which_clock"),
            ("const struct timespec *", "tp"),
        )),
        "clone": ("long", (
            ("unsigned long", "flags"),
            ("unsigned long", "child_stack"),
            ("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"),
        )),
        "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"),
        )),
        "futimesat": ("long", (
            ("int", "dfd"),
            ("const char *", "filename"),
            ("struct timeval *", "utimes"),
        )),
        "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"),
        )),
        "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_pgetevents": ("long", (
            ("aio_context_t", "ctx_id"),
            ("long", "min_nr"),
            ("long", "nr"),
            ("struct io_event *", "events"),
            ("struct _kernel_timespec *", "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_timedsend": ("long", (
            ("mqd_t", "mqdes"),
            ("const char *", "msg_ptr"),
            ("size_t", "msg_len"),
            ("unsigned int", "msg_prio"),
            ("const struct timespec *", "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"),
        )),
        "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_readdir": ("long", (
            ("unsigned int", "fd"),
            ("struct old_linux_dirent *", "dirp"),
            ("unsigned int", "count"),
        )),
        "old_select": ("long", (
            ("struct sel_arg_struct *", "arg"),
        )),
        "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"),
        )),
        "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_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"),
            ("size_t", ""),
        )),
        "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"),
        )),
        "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"),
        )),
        "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"),
        )),
        "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_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_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"),
        )),
        "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 *", "dest_addr"),
            ("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"),
        )),
        "stime": ("long", (
            ("time_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", (
            ("time_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_settime": ("long", (
            ("timer_t", "timer_id"),
            ("int", "flags"),
            ("const struct itimerspec *", "new_setting"),
            ("struct itimerspec *", "old_setting"),
        )),
        "timerfd_create": ("long", (
            ("int", "clockid"),
            ("int", "flags"),
        )),
        "timerfd_gettime": ("long", (
            ("int", "ufd"),
            ("struct itimerspec *", "otmr"),
        )),
        "timerfd_settime": ("long", (
            ("int", "ufd"),
            ("int", "flags"),
            ("const struct itimerspec *", "utmr"),
            ("struct itimerspec *", "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"),
        )),
        "utimensat": ("long", (
            ("int", "dfd"),
            ("const char *", "filename"),
            ("struct timespec *", "utimes"),
            ("int", "flags"),
        )),
        "utimes": ("long", (
            ("char *", "filename"),
            ("struct timeval *", "utimes"),
        )),
        "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, 424, 1)] + SYSCALL_COMMON

    # 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, 424, 1)] + SYSCALL_COMMON

    # Define default syscall list #
    sysList = []

    # Define systemcall register #
    SYSREG_LIST = {
        "powerpc": "gpr0",
        "arm": "r7",
        "aarch64": "r8",
        "x64": "orig_rax",
        "x86": "orig_eax"
        }

    # Define return register #
    RET_LIST = {
        "powerpc": "result",
        "arm": "r0",
        "aarch64": "r0",
        "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', 'NRTTY', 'TPGID', 'FLAGS', 'MINFLT', 'CMINFLT', #10#
        'MAJFLT', 'CMAJFLT', 'UTIME', 'STIME', 'CUTIME', 'CSTIME', 'PRIORITY', 'NICE', 'NRTHREAD', 'ITERALVAL', #20#
        'STARTTIME', 'VSIZE', 'RSS', 'RSSLIM', 'STARTCODE', 'ENDCODE', 'STARTSTACK', 'SP', 'PC', 'SIGNAL', #30#
        'BLOCKED', 'SIGIGNORE', 'SIGCATCH', 'WCHEN', 'NSWAP', 'CNSWAP', 'EXITSIGNAL', 'PROCESSOR', 'RTPRIORITY', #39#
        'POLICY', 'DELAYBLKTICK', 'GUESTTIME', 'CGUESTTIME' # 43 #
        ]

    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_ATTACH',            #16#
        'PTRACE_DETACH',            #17#
        '', '', '', '', '', '',
        '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 readProcData(tid, path, num):
        path = '%s/%s/%s' % (SysMgr.procPath, tid, path)

        try:
            f = open(path, 'r')
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printOpenErr(path)
            return None

        if num == 0:
            return f.readline().replace('\n', '')
        else:
            return f.readline().replace('\n', '').split(' ')[num - 1]



    @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 """

    progressCnt = 0
    progressChar = {
        0: '|',
        1: '/',
        2: '-',
        3: '\\',
    }



    @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',
        ])

        superset = {}
        superset.update({i:0 for i in ConfigMgr.SYSCALL_COMMON})
        superset.update({i:0 for i in ConfigMgr.SYSCALL_COMMON32})
        superset.update({i:0 for i in ConfigMgr.SYSCALL_X86})
        superset.update({i:0 for i in ConfigMgr.SYSCALL_X64})
        superset.update({i:0 for i in ConfigMgr.SYSCALL_ARM})
        superset.update({i:0 for i in ConfigMgr.SYSCALL_AARCH64})
        supersetlist = set(superset.keys())
        protolist = \
            set(['sys_%s' % name for name in ConfigMgr.SYSCALL_PROTOTYPES.keys()])

        # print final diff list #
        print("--- no prototype ---")
        print(list(supersetlist - protolist - ignorelist))

        print("\n--- no define ---")
        print(list(protolist - supersetlist))



    @staticmethod
    def parseInputString(string):
        string = string.replace('\,', '$%')
        clist = string.split(',')
        for idx, item in enumerate(list(clist)):
            clist[idx] = item.replace('$%', ',')
        return clist



    @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 isEffectiveStr(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 == string:
                    return True

        return False



    @staticmethod
    def drawGraph(inFile, outFile=None):
        instance = ThreadAnalyzer(onlyInstance=True)
        instance.drawStats(inFile, outFile=outFile, onlyGraph=True)



    @staticmethod
    def drawChart(inFile, outFile=None):
        instance = ThreadAnalyzer(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 getFileList(flist, sort=False):
        if not flist or \
            type(flist) is not list:
            return []

        rlist = list()
        for item in flist:
            # apply regular expression for path #
            ilist = UtilMgr.convertPath(item, retStr=False)
            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:
            text = value

        # define start index by encoding type #
        if type(text) is bytes:
            start = 2
        else:
            start = 1

        return text[start:]



    @staticmethod
    def getFlagString(value, flist):
        string = ''
        numVal = long(value)
        for bit in list(flist.keys()):
            try:
                if numVal & bit:
                    string = '%s%s|' % (string, flist[bit])
                elif bit == 1 and 0 in flist:
                    string = '%s%s|' % (string, flist[0])
            except:
                SysMgr.printWarn(\
                    "Fail to get flag info for %s" % value, reason=True)
        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:
            return value



    @staticmethod
    def decodeBase64(value):
        base64 = SysMgr.getPkg('base64', False)

        try:
            return base64.b64decode(value)
        except:
            return value



    @staticmethod
    def encodeStr(value):
        try:
            return value.encode()
        except:
            try:
                return value.encode('utf8', 'surrogateescape')
            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:
                long(value, 16)
                return True
            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)

        # open a file #
        try:
            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:
            totalSize = long(0)

        # read data from a file #
        while 1:
            try:
                data = fd.readline()
                curSize = fd.tell()
                if len(data) == 0:
                    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 convertPath(value, retStr=True, isExit=False, separator=' '):
        glob = SysMgr.getPkg('glob', False)
        if glob:
            res = glob.glob(value)
            if len(res) == 0 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 convNum(number):
        try:
            return format(long(number), ",")
        except SystemExit:
            sys.exit(0)
        except:
            return number



    @staticmethod
    def convertColor(string, color='LIGHT'):
        if 'REMOTERUN' in os.environ:
            return string

        return '%s%s%s' % \
            (ConfigMgr.COLOR_LIST[color], string, ConfigMgr.ENDC)



    @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:
            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:
                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:
                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 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)

            raise Exception()
        except SystemExit:
            sys.exit(0)
        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):
        pickle = SysMgr.getPicklePkg(False)
        if not pickle:
            return

        # 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 ELF cache to %s" % 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)

            if div != percent:
                return

            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 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 len(pathList) == 0:
            return None
        else:
            return pathList



    @staticmethod
    def convDict2Str(dictObj, pretty=True, indent=2):
        try:
            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):
        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], 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):
        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, TCP_NODELAY, 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 #
            self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)

            # set SENDTIMEOUT #
            '''
            sec = 1
            usec = long(0)
            timeval = struct.pack('ll', sec, usec)
            self.socket.setsockopt(SOL_SOCKET, SO_SNDTIMEO, timeval)
            '''

            # set NODELAY #
            '''
            self.socket.setsockopt(SOL_TCP, TCP_NODELAY, 1)
            '''

            # 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 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 = ''

            SysMgr.printErr(\
                "Fail to create socket with %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):
        ret = self.socket.close()
        self.socket = None
        return ret



    def flush(self):
        pass



    def timeout(self, time=3):
        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 = plist.split(',')
            origPath = path[0].strip()
            targetPath = path[1].strip()
            receiver = self
            targetIp = self.ip
            targetPort = self.port

            # 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(\
                    "%s [%s] is downloaded from %s:%s:%s successfully\n" % \
                    (targetPath, \
                    UtilMgr.convSize2Unit(os.path.getsize(targetPath)), \
                    targetIp, targetPort, origPath))
            except:
                SysMgr.printErr(\
                    'Fail to download %s from %s:%s:%s' % \
                        (origPath, targetIp, targetPort, targetPath), True)
            finally:
                receiver.close()

        def onUpload(req):
            # parse path #
            plist = req.split('|', 1)[1]
            path = plist.split(',')

            origPath = path[0].strip()
            targetPath = path[1].strip()
            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

            convert = UtilMgr.convSize2Unit

            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)

                        ret = sender.send(buf)
                        if not ret:
                            raise Exception()
                        else:
                            curSize = len(buf)

                        buf = fd.read(sender.sendSize)

                UtilMgr.deleteProgress()

                SysMgr.printInfo(\
                    "%s [%s] is uploaded to %s:%s successfully\n" % \
                        (origPath, convert(os.path.getsize(origPath)), \
                            addr, targetPath))
            except:
                SysMgr.printErr(\
                    "Fail to upload %s to %s:%s" % \
                        (origPath, addr, targetPath), True)
            finally:
                sender.close()

        def onRun(req, onlySocket):
            # parse command #
            origReq = req
            command = req.split('|', 1)[1]

            # parse addr #
            addr = '%s:%s' % (self.ip, self.port)

            if not onlySocket:
                SysMgr.printInfo(\
                    "'%s' is executed from %s\n" % (command, addr))

            # return just the connected socket #
            if onlySocket:
                return self

            # get select object #
            selectObj = SysMgr.getPkg('select')

            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

                    print(output[:-1])
                    isPrint = True
                except:
                    break

            # print output from server #
            if not isPrint:
                print('No response')

            print(oneLine)

            # close connection #
            try:
                self.close()
            except:
                pass



        # get select object to check #
        SysMgr.getPkg('select')

        # unmarshalling #
        if type(req) is tuple:
            try:
                req = req[0].decode()
            except:
                req = req[0]

            # handle request #
            if not req:
                return

            elif req.upper().startswith('DOWNLOAD'):
                return onDownload(req)

            elif req.upper().startswith('UPLOAD'):
                return onUpload(req)

            elif req.upper().startswith('RUN'):
                return onRun(req, onlySocket)

            elif req.startswith('ERROR'):
                err = req.split('|', 1)[1]
                errMsg = err.split(':', 1)[0]
                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()

            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):
        try:
            data = b''

            # receive and composite packets #
            while 1:
                output = self.recvfrom(noTimeout=True)

                # handle timeout #
                if not output:
                    continue

                # get only data #
                output = output[0]

                # composite packets #
                data = data + output

                if len(output) == 0:
                    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 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)

        # 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 or len(data) == 0:
            return 'None'

        data = data.lstrip()

        if data.startswith('{'):
            return 'JSON'
        elif '[Info' in data[:10] or \
            '[Error' in data[:10] or \
            '[Warning' 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():
        return NetworkMgr.execRemoteCmd("PING:PING")



    @staticmethod
    def getCmdPipe(connObj, cmd):
        if not cmd:
            return None

        # add command prefix #
        if cmd.upper().startswith('PING'):
            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 reply and reply[0].decode() == 'PONG':
                return True
        except:
            pass

        # handle reply from server #
        try:
            return connObj.handleServerRequest(reply, onlySocket=True)
        except:
            return None



    @staticmethod
    def execRemoteCmd(command):
        # get new connection #
        connObj = NetworkMgr.getServerConn()
        if not connObj:
            return None

        # launch remote command #
        pipe = NetworkMgr.getCmdPipe(connObj, command)
        return pipe



    @staticmethod
    def getServerConn():
        def printErr():
            SysMgr.printErr(\
                "No running server or wrong server address")

        # set server address in local #
        if SysMgr.isLinux and not SysMgr.remoteServObj:
            try:
                addr = SysMgr.getProcAddrs(__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

            connObj.timeout()

            # connect with handling CLOSE_WAIT #
            while 1:
                try:
                    connObj.connect()
                    break
                except:
                    SysMgr.printWarn(\
                        "Fail to connect to %s:%s" % (ip, port), reason=True)
                    et, err, to = sys.exc_info()
                    if err.args and err.args[0] == 99:
                        time.sleep(0.1)
                        continue
                    break

            return connObj
        except:
            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 value and len(value) == 0:
            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 option value with -X, "
                "local address and remote address are same "
                "with %s:%s") % (ip, port))
            sys.exit(0)

        if not ip or not port or \
            not SysMgr.isEffectiveRequest(service):
            reqList = ''
            for req in ThreadAnalyzer.requestType:
                reqList += req + '|'

            SysMgr.printErr(\
                ("wrong option value with -X, "
                 "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

        if tcp:
            proto = 'TCP'
        else:
            proto = 'UDP'

        SysMgr.printInfo(\
            "use %s:%d(%s) as remote address" % (ip, port, proto))



    @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(ThreadAnalyzer.requestType)

        if not ip or not SysMgr.isEffectiveRequest(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):
        if SysMgr.localServObj and not force:
            SysMgr.printWarn(\
                "Fail 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 len(iplist) > 0:
                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)
        if not networkObject.ip:
            SysMgr.printWarn(\
                "Fail to set server IP", True)
            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 len(ipList) == 0:
            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 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):
        SysMgr.checkPerm()

        try:
            if type(pid) is not list or len(pid) != 1:
                raise Exception()

            pid = SysMgr.getPids(pid[0], isThread=False)
            if len(pid) == 0:
                raise Exception()
            elif len(pid) > 1:
                SysMgr.printErr(\
                    "Found multiple pids [ %s ]" % ', '.join(pid))
                raise Exception()
            else:
                pid = pid[0]
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Fail to recognize pid, input only one PID with -g option")
            sys.exit(0)

        if not vaddr:
            PageAnalyzer.printMemoryArea(pid)
            SysMgr.printPipe(oneLine)
            sys.exit(0)

        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"):
                    addrType = 'hex'
                    addrs = long(vrange[0], base=16)
                    addre = addrs
                else:
                    addrType = 'dec'
                    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"):
                        addrType = 'hex'
                        addre = long(vrange[1], base=16)
                    else:
                        addrType = 'dec'
                        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[ PID: %s ] [ AREA: %s ] [ HELP: %s ]\n" % \
            (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):
        count = long(0)
        switch = long(0)
        fpath = '%s/%s/maps' % (SysMgr.procPath, pid)

        try:
            with open(fpath, 'r') as fd:
                buf = fd.readlines()
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printOpenErr(fpath)
            sys.exit(0)

        start = hex(start)
        end = hex(end)
        all = hex(-1)

        # print menu #
        menuStr = ''
        menuList = ['AREA', 'PERM', 'INODE', 'DEV', 'OFFSET']
        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, 'PROPERTY')
        SysMgr.printPipe('%s\n%s\n%s' % (twoLine, menuStr, oneLine))

        # set text position #
        tstr = menuStr.split()
        pstr = tstr[1]
        pidx = menuStr.find(pstr)

        # print maps 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()

                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')



    @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': bool(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 = ThreadAnalyzer.readTraceData(logFile)

        # save trace data and stop analysis #
        if SysMgr.outputFile:
            SysMgr.saveTraceData(lines)
            sys.exit(0)

        # Check target thread setting #
        if len(SysMgr.filterGroup) == 0:
            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 len(self.userCallData) == 0 and \
            len(self.kernelCallData) == 0 and \
            len(self.target) > 0:
            if self.target == []:
                SysMgr.printErr("No collected stack data")
            else:
                SysMgr.printErr(\
                    "No collected stack data related to %s" % self.target)
            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:
                SysMgr.printWarn(\
                    "No collected user stack data related to %s" % \
                    self.target, 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

        # Set user stack list #
        if self.sort == 'sym':
            targetStack = self.userSymData[sym]['symStack']
        elif self.sort == 'pos':
            targetStack = self.userSymData[sym]['stack']



    def handleHeapReduce(self, size, arg):
        addr = arg[0]
        time = arg[1]
        core = arg[2]
        tid = arg[3]

        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 len(targetStack) == 0:
                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 len(list(stackSet - subStackSet)) == 0 and \
                        len(list(subStackSet - stackSet)) == 0:
                        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 len(kernelTargetStack) == 0:
                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 len(list(kerStackSet - kerSubStackSet)) == 0 and \
                        len(list(kerSubStackSet - kerStackSet)) == 0:
                        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 with -X, "
                "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.getSymbolInfo(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.getSymbolInfo(binPath, offsetList) == -1:
                nrNoFile += 1

        UtilMgr.deleteProgress()

        if nrNoFile > 0:
            SysMgr.printWarn(\
                "Fail to find total %s binaries to analyze functions" % \
                    nrNoFile, True)



    def getSymbolInfo(self, binPath, offsetList):
        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:]
            else:
                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 SysMgr.addr2linePath:
            try:
                symbolList = list()
                binObj = ElfAnalyzer.getObject(binPath)
                if not binObj:
                    return None

                for offset in offsetList:
                    symbol = binObj.getSymbolByOffset(offset)

                    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 -l option to set custom path"))
                sys.exit(0)

            SysMgr.printInfo(\
                "use %s as addr2line path" % ', '.join(addr2linePath))
            SysMgr.addr2linePath = addr2linePath
        else:
            for path in SysMgr.addr2linePath:
                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.addr2linePath:
            # 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:
                        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 len(nowCtx['userStack']) == 0 and \
                len(nowCtx['kerStack']) > 0:
                    # Set userLastPos to None #
                self.nowCtx['userLastPos'] = '0'
                self.nowCtx['userStack'].append('0')
            if len(nowCtx['kerStack']) == 0 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 <kernel>
                CORE/0 <user>

                CORE/0 EVENT1
                CORE/0 <kernel>
                    CORE/0 EVENT2
                    CORE/0 <kernel>
                    CORE/0 <user>
                CORE/0 <user>
                '''
                # 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 <kernel>
                CORE/0 <user>

                CORE/0 EVENT1
                    CORE/0 EVENT2
                    CORE/0 <kernel>
                    CORE/0 <user>
                CORE/0 <kernel>
                CORE/0 <user>
                '''
                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 len(self.nowCtx['userStack']) == 0:
                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 len(self.nowCtx['kerStack']) == 0:
                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<value>\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 len(SysMgr.perCoreList) > 0 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<page>\S+)\s+pfn=(?P<pfn>[0-9]+)\s+'
                r'order=(?P<order>[0-9]+)\s+migratetype=(?P<mt>[0-9]+)\s+'
                r'gfp_flags=(?P<flags>\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<page>\S+)\s+pfn=(?P<pfn>[0-9]+)\s+'
                          r'order=(?P<order>[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<nr>[0-9]+) (?P<args>.+)', 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 len(syscallList) == 0 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<uaddr>\S+), (?P<op>\S+), '
                        r'(?P<val>\S+), (?P<timer>\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:
                            op = flist[maskedOp]
                        except:
                            op = l['op']

                        # 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<nr>\S+) = (?P<ret>.+)', 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 == '-----':
                            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<major>[0-9]+),(?P<minor>[0-9]+)\s*(?P<operation>\S+)\s*'
                r'(?P<address>\S+)\s+\+\s+(?P<size>[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<major>[0-9]+):(?P<minor>[0-9]+):\s*'
                r'ino=(?P<ino>\S+)\s+index=(?P<index>\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<major>[0-9]+):(?P<minor>[0-9]+):\s*'
                          r'towrt=(?P<towrt>\S+)\s+skip=(?P<skip>\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<sig>[0-9]+) errno=(?P<err>[0-9]+) '
                          r'code=(?P<code>.*) comm=(?P<comm>.*) '
                          r'pid=(?P<pid>[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<sig>[0-9]+) errno=(?P<err>[0-9]+) code=(?P<code>.*) '
                r'sa_handler=(?P<handler>.*) sa_flags=(?P<flags>.*)'), 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<dev>.+)\s+ino=(?P<ino>.+)'\
                r'\s+type=(?P<type>.+)\s+ctx=(?P<ctx>.+)'), 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 == "<user":
            self.nowCtx['prevMode'] = self.nowCtx['curMode']
            self.nowCtx['curMode'] = 'user'

            return True

        # Start to record kernel stack #
        elif func == "<stack":
            self.nowCtx['prevMode'] = self.nowCtx['curMode']
            self.nowCtx['curMode'] = 'kernel'
            self.nowCtx['nested'] -= 1

            if self.nowCtx['nested'] < 0:
                #self.printDbgInfo()
                SysMgr.printWarn((\
                    "Fail to analyze stack data "
                    "because of corruption (underflow) at %s line\n"\
                    "\tso report results may differ from actual") % \
                    SysMgr.dbgEventLine, True)

            return True

        # custom event #
        elif not isFixedEvent:
            try:
                if len([event for event in self.customEventTable \
                    if event.endswith(func[:-1])]) == 0:
                    cond = self.customEventTable[func[:-1]] = None
                else:
                    cond = self.customEventTable[func[:-1]]

                # set event filter #
                customCnt = self.getCustomEventValue(func, args, cond)

                if customCnt > 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:
                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 len(SysMgr.perCoreList) > 0 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<comm>.*)\s+pid=(?P<pid>[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<comm>.*)\s+pid=(?P<pid>[0-9]+)\s+'\
                    r'child_comm=(?P<child_comm>.*)\s+'\
                    r'child_pid=(?P<child_pid>[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<pid>[0-9]+)\s+comm=(?P<comm>\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<event>\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<path>.+)\[\+0x(?P<offset>.\S*)\] '\
                r'\<(?P<pos>.\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<symbol>.+) \<(?P<pos>.\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", "ID", "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 = ''
            dieMark = ''
            newMark = ''

            # 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 = '-'

            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(value['comm'], 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 len(self.target) == 0:
            SysMgr.printWarn(\
                "No specific thread targeted, input TID with -g option")

        # 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 len(subStack) == 0:
            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 len(symbolStack) == 0:
            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

        # Make syscall event list #
        sysList = ConfigMgr.sysList

        # 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 len(subStack) == 0:
                    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 len(self.sysCallData) == 0:
            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]
            userstack = call[2]
            kernelstack = call[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 len(subStack) == 0:
                        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 len(subStack) == 0:
                    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 len(self.customCallData) == 0:
            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]
            userstack = call[2]
            kernelstack = call[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 len(subStack) == 0:
                        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()

            # 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()

            # 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()

        # 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 len(subStack) == 0:
                    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

        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 len(subStack) == 0:
                        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()

        # 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)

        # Make exception list to remove a redundant part of stack #
        exceptList = self.getExceptionList()

        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 len(subStack) == 0:
                    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()

        # 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)

        # Make exception list to remove a redundant part of stack #
        exceptList = self.getExceptionList()

        # 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 len(subStack) == 0:
                        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()

        # 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)

        # Make exception list to remove a redundant part of stack #
        exceptList = self.getExceptionList()

        # 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 len(subStack) == 0:
                    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()

        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 len(subStack) == 0:
                    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 len(self.heapTable) == 0:
            SysMgr.printPipe('\tNone\n%s' % oneLine)

        SysMgr.printPipe()

        # Print remaining heap history #
        if not SysMgr.showAll or len(self.heapTable) == 0:
            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 len(subStack) == 0:
                    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()

        # 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()

        # 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 len(subStack) == 0:
                    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()

        # 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()

        # Print lock history #
        if not SysMgr.showAll or len(self.lockCallData) == 0:
            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]
            kernelstack = call[3]

            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 len(subStack) == 0:
                        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()

        # 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)

        # Make exception list to remove a redundant part of stack #
        exceptList = self.getExceptionList()

        # 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 len(subStack) == 0:
                    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 len(subStack) == 0:
                        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()

        # 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)

        # Make exception list to remove a redundant part of stack #
        exceptList = self.getExceptionList()

        # 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 len(subStack) == 0:
                    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 leaktracer """

    def __init__(self, file=None, pid=None):

        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):
        convert = UtilMgr.convSize2Unit

        # function leakage info #
        title = 'Function Leakage Info'
        SysMgr.printPipe(\
            '\n[%s] [TotalSize: %s] [CallCount: %s] [FuncCount: %s]' % \
                (title, convert(self.totalLeakSize), \
                convert(len(self.callData)), \
                convert(len(self.symData))))

        SysMgr.printPipe(twoLine)
        SysMgr.printPipe(\
                "{0:^7} | {1:^7} | {2:^7} |{3:^46} | {4:^74} |".\
                format("Size", "Count", "Avg", "Function", "Path"))
        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:^46} | {4:<74} |".\
                    format(convert(val['lastPosSize']), convert(val['count']), \
                    convert(long(val['lastPosSize'] / val['count'])), \
                    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] [TotalSize: %s] [CallCount: %s] [FileCount: %s]' % \
                (title, convert(self.totalLeakSize), \
                convert(len(self.callData)), \
                convert(len(self.fileData))))

        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 len(self.callData) == 0:
            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)
        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 = ' <- '.join(callinfo['symstack'][1:])

                    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']):
                symstack[idx] = self.posData[offset]['sym']

            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:
            line = fd.readline()
            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, \
        '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.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 len(SysMgr.filterGroup) == 0:
            SysMgr.filterGroup.insert(0, '')

        if not SysMgr.guiderObj:
            # get ctypes object #
            SysMgr.importPkgItems('ctypes')

            if not SysMgr.loadLibcObj():
                sys.exit(0)

            # 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 len(self.procList) == 0:
            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 len(self.fileList) == 0:
            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

        # 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:_^5})|{2:_^12}|{3:_^16}({4:_^5}) |".\
            format("Process", "Pid", "MaxRAM", "ThreadName", "Tid"))
        SysMgr.printPipe(twoLine)

        procInfo = "{0:_^16}({1:^5})|{2:11} |".format('', '', '')
        threadInfo = " {0:^16}({1:^5}) |".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):
            printMsg = "{0:>16}({1:>5})|{2:>11} |".\
                format(val['comm'], pid, \
                convert(val['pageCnt'] * pageSize))
            linePos = len(printMsg)

            for tid, threadVal in sorted(val['tids'].items(), reverse=True):
                threadInfo = \
                    "{0:>16}({1:>5}) |".format(threadVal['comm'][:16], tid)

                linePos += threadLength

                if linePos > lineLength:
                    linePos = procLength + threadLength
                    printMsg += "\n" + (' ' * (procLength - 1)) + '|'

                printMsg += threadInfo

            SysMgr.printPipe(printMsg)

        SysMgr.printPipe("%s\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)
            else:
                per = long(0)

            # 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(\
                            convert(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

                    diffNew = convert(diffNew * pageSize)
                    diffDel = convert(diffDel * pageSize)
                    printMsg += "+%6s/-%6s|" % (diffNew, diffDel)

            finalData = self.intervalFileData[-1][fileName]
            totalMemSize = finalData['pageCnt'] * pageSize

            if fileSize != 0:
                per = long(long(totalMemSize) / float(fileSize) * 100)
            else:
                per = long(0)

            printMsg += \
                "{0:11}|{1:3}| {2:1}".format(\
                    convert(totalMemSize), per, fileName)

            SysMgr.printPipe(printMsg)

        SysMgr.printPipe("%s\n\n\n" % oneLine)



    def makeReadaheadList(self):
        pass



    @staticmethod
    def getMapFilePath(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 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):
        # open maps #
        try:
            path = '%s/%s/maps' % (SysMgr.procPath, pid)
            return open(path, 'r')
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printOpenWarn(path)
            return None



    @staticmethod
    def getProcMapInfo(pid, fd=None, onlyExec=False):
        if not fd:
            fd = FileAnalyzer.getMapFd(pid)
            if not fd:
                return None

        # 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)

        # remove non-executable files #
        if onlyExec:
            for fname in list(fileMap.keys()):
                if 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

            # bigger start address 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
            # lesser start address 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<startAddr>.\S+)-(?P<endAddr>.\S+) (?P<perm>.\S+) '
            r'(?P<offset>.\S+) (?P<devid>.\S+) (?P<inode>0|.\S+).\s*'
            r'(?P<binName>.+)'), string)
        if not m:
            return None

        return m.groupdict()



    @staticmethod
    def mergeMapLine(string, procMap, onlyExec=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
        newEnd = newOffset + newSize

        # merge map line #
        FileAnalyzer.addMapLine(procMap, fileName, newOffset, newSize)

        # set mapped addr #
        if newOffset == 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 len(self.procData) == 0:
            SysMgr.printErr('No process profiled')
            sys.exit(0)
        if len(self.fileData) == 0:
            SysMgr.printErr('No file profiled')
            sys.exit(0)

        SysMgr.printLogo(big=True)

        # print system information #
        SysMgr.printInfoBuffer()

        # define alias #
        convert = UtilMgr.convSize2Unit
        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:_^5})|{2:_^13}|{3:_^16}({4:_^5}) |".\
            format("Process", "Pid", "RAM", "Thread", "Tid"))
        SysMgr.printPipe(twoLine)

        procInfo = "{0:^16}({0:^5})|{0:12} |".format('')
        threadInfo = " {0:^16}({0:^5}) |".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:
                pass

            printMsg = "{0:>16}({1:>5})|{2:>12} |".\
                format(val['comm'][:16], pid, convert(rsize))
            linePos = len(printMsg)

            for tid, threadVal in sorted(val['tids'].items(), reverse=True):
                threadInfo = \
                    "{0:^16}({1:^5}) |".format(threadVal['comm'][:16], tid)

                linePos += threadLength

                if linePos > lineLength:
                    linePos = procLength + threadLength
                    printMsg += "\n" + (' ' * (procLength - 1)) + '|'

                printMsg += threadInfo

            SysMgr.printPipe(printMsg)

        SysMgr.printPipe("%s\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)
            else:
                per = long(0)

            if not val['isRep']:
                continue
            else:
                SysMgr.printPipe((\
                    "{0:>11} |{1:>9} |{2:>5} | {3:1} "
                    "[Proc: {4:1}] [Link: {5:1}]").\
                    format(convert(memSize), convert(fileSize), per, \
                    fileName, len(val['pids']), val['hardLink']))

            # prepare for printing process list #
            pidInfo = ''
            lineLength = SysMgr.lineLength
            pidLength = len(" %16s (%5s) |" % ('', ''))
            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 (%5s) |" % (comm[:16], 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 SysMgr.filterGroup #
        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 SysMgr.filterGroup:
                    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 to analyze %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 systemcall #
            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 systemcall 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 systemcall 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):
        self.terminal = sys.stderr
        self.notified = False
        self.error = False



    def write(self, message):
        self.terminal.write(message)

        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:
                fd.write(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 printSyslog():
        # 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.isEffectiveStr(log):
                continue

            SysMgr.printPipe(log, newline=False)


    @staticmethod
    def printJournal():
       # 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 log... [ 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)

        # start reading loop #
        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 all fields #
            if SysMgr.inputParam is not None:
                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, flush=True)
                SysMgr.printPipe(flush=True)
                continue

            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":
                    pass
                elif field == b"_PID":
                    val = b'[%s]: ' % val
                elif field == b"_TRANSPORT" and val == b"kernel":
                    val += b': '
                else:
                    val += b' '

                jrlStr += val

            if jrlStr and UtilMgr.isEffectiveStr(jrlStr):
                try:
                    SysMgr.printPipe(jrlStr.decode(), flush=True)
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printPipe(jrlStr, flush=True)

        # close journal #
        systemdObj.sd_journal_close(jrl)



    @staticmethod
    def printKmsg():
        # 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.isEffectiveStr(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.isEffectiveStr(line):
                    continue

                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.isEffectiveStr(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.jsonOutputEnable:
                    jsonResult = \
                        dict(time=ltime, level=level, name=name, log=log)
                else:
                    if not SysMgr.printFile:
                        level = UtilMgr.convertColor(level, 'BOLD')
                        name = UtilMgr.convertColor(name, 'SPECIAL')
                        ltime = UtilMgr.convertColor(ltime, 'GREEN')
                    log = '[%s] (%s) %s: %s' % (ltime, level, name, log)

            # apply filter #
            if len(SysMgr.filterGroup) > 0:
                found = False
                for string in SysMgr.filterGroup:
                    if string in log:
                        found = True
                        break

                if not found:
                    continue

            if SysMgr.jsonOutputEnable:
                jsonResult = UtilMgr.convDict2Str(jsonResult)
                SysMgr.printPipe(jsonResult)
            else:
                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

        if not SysMgr.loadLibcObj():
            sys.exit(0)

        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 = None
    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
    magicString = '@@@@@'
    launchBuffer = ''
    lineLength = 154
    pid = long(0)
    masterPid = long(0)
    prio = None
    funcDepth = long(0)
    maxPid = 32768
    pidDigit = 5
    stderr = sys.stderr
    packetSize = 32767
    defaultPort = 5555
    bgProcList = None
    waitDelay = 0.5
    repeatInterval = long(0)
    repeatCount = long(0)
    progressCnt = long(0)
    wordSize = 4

    # path #
    procPath = '/proc'
    imagePath = None
    mountPath = None
    mountCmd = None
    debugfsPath = '/sys/kernel/debug'
    cacheDirPath = '/var/log/guider'
    outFileName = 'guider.out'
    confFileName = 'guider.conf'
    cmdFileName = 'guider.cmd'
    tmpPath = '/tmp'
    kmsgPath = '/dev/kmsg'
    syslogPath = '/var/log/syslog'
    lmkPath = '/sys/module/lowmemorykiller/parameters/minfree'
    pythonPath = sys.executable
    addr2linePath = []
    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'
    libdemanglePath = libcppPath
    eventLogPath = None
    inputFile = None
    outputFile = None
    inputParam = None
    printFile = None

    signalCmd = "trap 'kill $$' INT\nsleep 1d\n"
    saveCmd = None
    boundaryLine = None
    demangleEnable = True
    compressEnable = True
    nrTop = None
    pipeForPrint = None
    fileForPrint = None
    fileSuffix = None
    parsedAnalOption = False
    optionList = []
    customCmd = []
    userCmd = []
    kernelCmd = []
    udpListCache = None
    tcpListCache = None
    customEventList = []
    userEventList = []
    kernelEventList = []
    perfEventChannel = {}
    perfTargetEvent = []
    perfEventData = {}
    commFdCache = {}
    libCache = {}
    cmdFileCache = {}
    cmdAttachCache = {}

    impPkg = {}
    impGlbPkg = {}
    skipImpPkg = {}
    exitFuncList = []
    dltObj = None
    dltCtx = None
    shmObj = None
    systemdObj = None
    libcObj = None
    libgioObj = None
    libdbusObj = None
    libgObj = None
    libglesObj = 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)
    logSize = long(0)
    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

    printStreamEnable = False
    loggingEnable = False
    dltEnable = False
    kmsgEnable = False
    syslogEnable = False
    journalEnable = False
    terminalOver = False

    cpuAvrEnable = True
    reportEnable = False
    truncEnable = True
    countEnable = False
    reportObject = None
    reportFileEnable = False
    graphEnable = False
    procBuffer = []
    topInstance = None
    procInstance = {}
    fileInstance = {}
    sysInstance = None
    procBufferSize = long(0)
    bufferOverflowed = False
    bufferString = ''
    bufferList = []
    bufferRows = long(0)
    systemInfoBuffer = ''
    kerSymTable = {}
    reportData = {}
    jsonData = {}
    layout = None

    showAll = False
    optStrace = False
    disableAll = False
    intervalNow = long(0)
    recordStatus = False
    bgStatus = False
    condExit = False
    sort = 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 #
    irqEnable = False
    cpuEnable = True
    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
    jsonOutputEnable = False
    powerEnable = 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
    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
    groupProcEnable = False

    # Elastic Stack #
    elasticEnable = False

    cmdList = {}
    rcmdList = {}
    savedProcTree = {}
    savedProcComm = {}
    savedMountTree = {}
    preemptGroup = []
    filterGroup = []
    schedFilter = []
    affinityFilter = []
    killFilter = []
    syscallList = []
    perCoreList = []
    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.cmdlineData = None
        self.osData = None
        self.devData = None
        self.procData = None
        self.macAddr = None

        # 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 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]
                SysMgr.pidDigit = len(maxPid)
                SysMgr.maxPid = long(maxPid)
        except SystemExit:
            sys.exit(0)
        except:
            pass



    @staticmethod
    def loadLibcObj():
        if SysMgr.libcObj:
            return True

        try:
            ret = SysMgr.loadLib(SysMgr.libcPath)
            if ret:
                SysMgr.libcObj = ret
                return True
            else:
                return False
        except SystemExit:
            sys.exit(0)
        except:
            return False



    @staticmethod
    def shrinkHeap():
        if not SysMgr.isLinux:
            return

        # get ctypes object #
        if not SysMgr.importPkgItems('ctypes', False):
            return

        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) #
        ret = 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)

        if not SysMgr.inputParam:
            SysMgr.printErr((\
                "wrong option value with -I option, "
                "input a %s message") % mtype)
            sys.exit(0)

        # set alarm #
        if SysMgr.intervalEnable:
            signal.signal(signal.SIGALRM, SysMgr.onAlarm)
            signal.alarm(SysMgr.intervalEnable)

        while 1:
            msg = SysMgr.inputParam
            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 #
        resource = SysMgr.getPkg('resource', False, True)
        if resource:
            soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
            resource.setrlimit(resource.RLIMIT_NOFILE, (hard, hard))
            SysMgr.maxFd = hard
            SysMgr.maxKeepFd = SysMgr.maxFd - 16
            return

        # 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_uint),
                ("rlim_max", c_uint),
            )

        # try to get maxFd by standard library call #
        try:
            SysMgr.loadLibcObj()

            SysMgr.libcObj.getrlimit.argtypes = (c_int, POINTER(rlimit))
            SysMgr.libcObj.getrlimit.restype = c_int

            rlim = rlimit()
            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():
        if not SysMgr.inputParam:
            SysMgr.inputFile = 'guider.dat'
        else:
            SysMgr.inputFile = SysMgr.inputParam

        if not SysMgr.printFile:
            SysMgr.printFile = \
                '%s.out' % os.path.splitext(SysMgr.inputFile)[0]



    @staticmethod
    def execSystemView():
        # parse all options and make output file path #
        SysMgr.parseAnalOption()

        # wait for user input #
        SysMgr.waitEvent()

        SysMgr.printStat(\
            r'start recording... [ STOP(Ctrl+c), MARK(Ctrl+\) ]')

        # 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.isFuncRecordMode():
            SysMgr.functionEnable = True

        # file #
        elif SysMgr.isFileRecordMode():
            SysMgr.fileEnable = True

        # syscall #
        elif SysMgr.isSyscallRecordMode():
            SysMgr.sysEnable = True
            SysMgr.cpuEnable = False

        # general #
        elif SysMgr.isGeneralRecordMode():
            SysMgr.systemEnable = True

        # update record status #
        SysMgr.recordStatus = True
        SysMgr.inputFile = '/sys/kernel/debug/tracing/trace'

        # change priority of process #
        if not SysMgr.prio:
            SysMgr.setPriority(SysMgr.pid, 'C', -20)

        SysMgr.parseRecordOption()
        SysMgr.printProfileOption()
        SysMgr.printProfileCmd()



    @staticmethod
    def setVisualAttr():
        if len(sys.argv) <= 2:
            sys.argv.append(SysMgr.outFileName)

        SysMgr.graphEnable = True

        # apply regular expression for first path #
        flist = UtilMgr.convertPath(sys.argv[2], retStr=False)
        if type(flist) is list and \
            len(flist) > 0:
            sys.argv = sys.argv[:2] + flist + sys.argv[3:]

        # thread draw mode #
        if float(ThreadAnalyzer.getInitTime(sys.argv[2])) > 0:
            # apply launch option #
            SysMgr.applyLaunchOption()

            if not SysMgr.isThreadMode():
                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.printFile:
                SysMgr.printFile = \
                    '%s.out' % os.path.splitext(SysMgr.inputFile)[0]
            del sys.argv[2]
        # top draw mode #
        else:
            # CPU graph #
            if SysMgr.isCpuDrawMode():
                SysMgr.layout = 'CPU'
            # memory graph #
            elif SysMgr.isMemDrawMode():
                SysMgr.layout = 'MEM'
            # vss graph #
            elif SysMgr.isVssDrawMode():
                SysMgr.layout = 'MEM'
                SysMgr.vssEnable = True
            # rss graph #
            elif SysMgr.isRssDrawMode():
                SysMgr.layout = 'MEM'
                SysMgr.rssEnable = True
            # leak graph #
            elif SysMgr.isLeakDrawMode():
                SysMgr.layout = 'MEM'
                SysMgr.leakEnable = True
            # io graph #
            elif SysMgr.isIoDrawMode():
                SysMgr.layout = 'IO'

            # modify args for drawing multiple input files #
            sys.argv[1] = 'top'
            args = sys.argv[2:]
            SysMgr.inputParam = UtilMgr.getFileList(args)



    @staticmethod
    def execFileAnalysis():
        SysMgr.checkPerm()

        # parse analysis option #
        SysMgr.parseAnalOption()

        SysMgr.printStat(\
            r'start recording... [ STOP(Ctrl+c), MARK(Ctrl+\) ]')

        # start analyzing files #
        pi = FileAnalyzer()

        # 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:
            signal.alarm(SysMgr.repeatInterval)

            # get init time in buffer for verification #
            initTime = ThreadAnalyzer.getInitTime(SysMgr.inputFile)

            # wait for timer #
            try:
                time.sleep(SysMgr.repeatInterval)
            except SystemExit:
                sys.exit(0)
            except:
                pass

            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 < ThreadAnalyzer.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 = ThreadAnalyzer.getInitTime(SysMgr.inputFile)

            # wait for user input #
            while 1:
                if SysMgr.recordStatus:
                    SysMgr.condExit = True

                    SysMgr.waitEvent()
                    if SysMgr.condExit:
                        break
                else:
                    break

            # compare init time with now time for buffer verification #
            if initTime < ThreadAnalyzer.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.isThreadTopMode():
            SysMgr.processEnable = False

        # file #
        elif SysMgr.isFileTopMode():
            SysMgr.fileTopEnable = True

        # stack #
        elif SysMgr.isStackTopMode():
            if SysMgr.checkStackTopCond():
                SysMgr.processEnable = False
                SysMgr.stackEnable = True
            else:
                sys.exit(0)

        # perf #
        elif SysMgr.isPerfTopMode():
            if SysMgr.checkPerfTopCond():
                SysMgr.perfEnable = True
                if SysMgr.findOption('g'):
                    SysMgr.processEnable = False
                    SysMgr.perfGroupEnable = True
            else:
                sys.exit(0)

        # mem #
        elif SysMgr.isMemTopMode():
            if SysMgr.checkMemTopCond():
                SysMgr.memEnable = True
                SysMgr.sort = 'm'
            else:
                sys.exit(0)

        # WSS (working set size) #
        elif SysMgr.isWssTopMode():
            if SysMgr.checkWssTopCond():
                SysMgr.memEnable = True
                SysMgr.wssEnable = True
                SysMgr.sort = 'm'
            else:
                sys.exit(0)

        # disk #
        elif SysMgr.isDiskTopMode():
            if SysMgr.checkDiskTopCond():
                SysMgr.diskEnable = True
                SysMgr.blockEnable = True
                SysMgr.sort = 'b'
            else:
                sys.exit(0)

        # system #
        elif SysMgr.isSystemTopMode():
            SysMgr.irqEnable = True
            SysMgr.diskEnable = True
            SysMgr.networkEnable = True

        # DLT #
        elif SysMgr.isDltTopMode():
            SysMgr.dltTopEnable = True

        # D-Bus #
        elif SysMgr.isDbusTopMode():
            SysMgr.dbusTopEnable = True
            SysMgr.floatEnable = True

            # set default interval to 3 for accuracy #
            if not SysMgr.findOption('i') and \
                not SysMgr.findOption('R'):
                SysMgr.intervalEnable = 3

        # usercall #
        elif SysMgr.isUserTopMode():
            SysMgr.doTrace('usercall')

        # breakcall #
        elif SysMgr.isBrkTopMode():
            SysMgr.doTrace('breakcall')

        # syscall #
        elif SysMgr.isSysTopMode():
            SysMgr.doTrace('syscall')

        # network #
        elif SysMgr.isNetTopMode():
            SysMgr.networkEnable = True

        # background #
        elif SysMgr.isBgTopMode():
            if SysMgr.checkBgTopCond():
                SysMgr.runBackgroundMode()
            else:
                sys.exit(0)

        # report #
        elif SysMgr.isReportTopMode():
            SysMgr.jsonOutputEnable = True

            if SysMgr.isRoot():
                SysMgr.diskEnable = True
                SysMgr.networkEnable = True
            else:
                SysMgr.printWarn(\
                    "Fail to get disk and network start "
                    "because no root permission")

            if SysMgr.checkReportTopCond():
                SysMgr.printEnable = False
            else:
                sys.exit(0)

        # print profile option #
        if not SysMgr.isDrawMode():
            SysMgr.printProfileOption()
            SysMgr.printProfileCmd()

        # set handler for exit #
        SysMgr.setNormalSignal()

        # run process / file monitoring #
        ThreadAnalyzer()



    @staticmethod
    def loadLibCache():
        try:
            path = '/etc/ld.so.cache'
            if sys.version_info < (3, 0):
                fd = open(path, 'rb')
            else:
                fd = open(path, errors='ignore')

            content = fd.read()
            libList = list(re.findall("[^\x00-\x1F\x7F-\xFF]{4,}", content))

            libDict = {}
            for idx, item in enumerate(libList):
                try:
                    if libList[idx+1][0] == '/':
                        value = libList[idx+1]
                        if item in libDict:
                            libDict[item].append(value)
                        else:
                            libDict[item] = [value]
                except:
                    pass

            SysMgr.libCache = libDict
        except:
            SysMgr.printWarn('Fail to load library cache', reason=True)
            return False



    @staticmethod
    def findLib(lib):
        if len(SysMgr.libCache) == 0:
            SysMgr.loadLibCache()

        for key, val in SysMgr.libCache.items():
            if key.startswith(lib):
                if len(val) > 1:
                    SysMgr.printWarn(\
                        'Multiple libraries [ %s ] exist for %s' % \
                            (', '.join(val), key))

                return val

        return None



    @staticmethod
    def loadLib(lib):
        if not SysMgr.importPkgItems('ctypes', False):
            return

        target = SysMgr.findLib(lib)
        if not target:
            target = ['%s.so' % lib]

        for item in target:
            try:
                res = cdll.LoadLibrary(item)
                if res:
                    return res
            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 parseKillOption(value):
        if len(value) == 0:
            SysMgr.printErr("wrong option value %s with -k")
            sys.exit(0)

        SysMgr.checkPerm()

        sigList = ConfigMgr.SIG_LIST

        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 len(jobs) == 0:
            SysMgr.printErr("wrong option value")
            sys.exit(0)

        SysMgr.checkPerm()

        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:
                    withSibling = SysMgr.groupProcEnable
                    targetList = SysMgr.getPids(tid, withSibling=withSibling)
                    targetList = list(map(long, targetList))
                    if not targetList:
                        SysMgr.printErr(\
                            "No threads related to %s" % tid)
                        sys.exit(0)
                    SysMgr.setAffinity(mask, targetList)

                if len(value) == 3 and value[2].upper() == 'CONT':
                    flag = 'CONT'
                else:
                    flag = 'ONCE'

                SysMgr.affinityFilter.append([mask, tid, flag])
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "wrong option value '%s'" % origVal, True)
                sys.exit(0)



    @staticmethod
    def doSetAffinity():
        isProcess = False
        SysMgr.warnEnable = True

        # parse options #
        value = SysMgr.filterGroup
        if len(value) == 0:
            SysMgr.printErr(\
                "Fail to set CPU affinity of task "
                "because of no target")
            sys.exit(0)

        SysMgr.checkPerm()

        SysMgr.parseAffinityOption(value, launch=True)

        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('_')]

        globals().update({name: moduleDict[name] for name in importList})

        SysMgr.impGlbPkg[pkg] = True

        return True



    @staticmethod
    def doGetAffinity():
        SysMgr.warnEnable = True

        # parse options #
        value = SysMgr.filterGroup
        if len(value) == 0:
            SysMgr.printErr(\
                "Fail to get CPU affinity of task "
                "because of no target")
            sys.exit(0)

        SysMgr.checkPerm()

        withSibling = SysMgr.groupProcEnable
        targetList = []

        try:
            for item in value:
                targetList += SysMgr.getPids(item, withSibling=withSibling)

            if not targetList:
                SysMgr.printErr(\
                    "No threads 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 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.printErr(\
                "Fail to get root permission to set affinity")
            return

        # 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

        # get ctypes object #
        if not SysMgr.importPkgItems('ctypes', False):
            return

        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.loadLibcObj()

                    nrCore = SysMgr.getNrCore()

                    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:
            if not SysMgr.loadLibcObj():
                raise Exception()

            nrCore = SysMgr.getNrCore()

            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()
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printWarn((\
                "Fail to get CPU affinity of tasks "
                "because of sched_getaffinity fail"))



    @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 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 loadConfig(fname, verb=True):
        try:
            targetList = []
            with open(fname, 'r') as fd:
                for line in fd.readlines():
                    if not line:
                        continue

                    line = line.strip()
                    if line.startswith('<') and line.endswith('>'):
                        entry = line[1:-1]
                        ConfigMgr.confData[entry] = list()
                        targetList = ConfigMgr.confData[entry]
                    elif line and line != '\n' and not line.startswith('#'):
                        targetList.append(line)

            return ConfigMgr.confData
        except SystemExit:
            sys.exit(0)
        except:
            if verb:
                SysMgr.printErr(\
                    "Fail to load configuration from %s" % fname, reason=True)
            return None



    @staticmethod
    def getCwd(pid):
        cwdPath = \
            '%s/%s/cwd' % (SysMgr.procPath, pid)
        return os.readlink(cwdPath)



    @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 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 getComm(pid, cache=False):
        try:
            if pid in SysMgr.commFdCache:
                fd = SysMgr.commFdCache[pid]
                fd.seek(0)
                comm = fd.readline()[:-1]
        except SystemExit:
            sys.exit(0)
        except:
            pass

        commPath = \
            '%s/%s/comm' % (SysMgr.procPath, pid)
        comm = None

        try:
            fd = open(commPath, 'r')

            comm = fd.readline()[:-1]

            # flush fd cache #
            if SysMgr.maxKeepFd < fd.fileno():
                SysMgr.commFdCache = {}
            # cache a fd #
            elif cache:
                SysMgr.commFdCache[pid] = fd
            else:
                fd.close()
        except SystemExit:
            sys.exit(0)
        except:
            return None

        return comm



    @staticmethod
    def getBacktrace():
        # get ctypes object #
        SysMgr.importPkgItems('ctypes')

        if not SysMgr.loadLibcObj():
            sys.exit(0)

        # 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 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

        # get cyptes object #
        if not SysMgr.importPkgItems('ctypes', False):
            return

        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.readlines()[0]

            # 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

            if io > 0:
                wio = stat['curWIoMs'] - stat['prevWIoMs']

        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():
        try:
            SysMgr.mountFd.seek(0)
            return SysMgr.mountFd.readlines()
        except SystemExit:
            sys.exit(0)
        except:
            try:
                mountPath = '%s/self/mountinfo' % SysMgr.procPath
                SysMgr.mountFd = open(mountPath, 'r')
                return SysMgr.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:
                STATM_TYPE = fd.readlines()[0].split()
                return STATM_TYPE
        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.isEffectiveTid(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.isEffectiveTid(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<comm>\S+)-(?P<thread>[0-9]+)\s+'
                r'\[(?P<core>[0-9]+)\]\s+\(\s*(?P<tgid>.+)\)\s+'
                r'(?P<time>\S+):\s+(?P<func>\S+)(?P<etc>.+)'), string)
            if not m:
                # print-tgid option #
                m = re.match((\
                    r'^\s*(?P<comm>.+)-(?P<thread>[0-9]+)\s+'
                    r'\(\s*(?P<tgid>\S+)\)\s+\[(?P<core>[0-9]+)\]\s+'
                    r'(?P<time>\S+):\s+(?P<func>\S+)(?P<etc>.+)'), string)

            return m

        m = re.match((\
            r'^\s*(?P<comm>.+)-(?P<thread>[0-9]+)\s+\[(?P<core>[0-9]+)\]\s+'
            r'(?P<time>\S+):\s+(?P<func>\S+)(?P<etc>.+)'), string)

        return m



    @staticmethod
    def isEffectiveEnableOption(options):
        if not options:
            return False

        if 'i' in options or 'm' in options or \
            'n' in options or 'h' in options or \
            'b' in options or 'p' in options or \
            'P' in options or 'r' in options or \
            'g' in options or 'L' in options or \
            'N' in options or 't' in options or \
            'v' in options or 'H' in options or \
            'l' in options or 'G' in options or \
            'c' in options or 's' in options or \
            'S' in options or 'u' in options or \
            'a' in options or 'I' in options or \
            'f' in options or 'F' in options or \
            'w' in options or 'W' in options or \
            'r' in options or 'R' in options or \
            'd' in options or 'o' in options or \
            'C' in options or 'E' in options or \
            'D' in options or 'k' in options or \
            'j' in options or 'y' in options or \
            'Y' in options or 'q' in options:
            return True
        else:
            return False



    @staticmethod
    def isEffectiveOption(option):
        if option == 'a' or option == 'A' or option == 'b' or \
            option == 'c' or option == 'C' or option == 'd' or \
            option == 'D' or option == 'e' or option == 'E' or \
            option == 'f' or option == 'F' or option == 'g' or \
            option == 'H' or option == 'i' or option == 'I' or \
            option == 'j' or option == 'k' or option == 'K' or \
            option == 'L' or option == 'l' or option == 'm' or \
            option == 'M' or option == 'n' or option == 'N' or \
            option == 'o' or option == 'O' or option == 'P' or \
            option == 'p' or option == 'Q' or option == 'r' or \
            option == 'R' or option == 'S' or option == 's' or \
            option == 'T' or option == 't' or option == 'u' or \
            option == 'U' or option == 'v' or option == 'w' or \
            option == 'W' or option == 'x' or option == 'X' or \
            option == 'Y' or option == 'y' or option == 'Z' or \
            option == 'B' or option.isdigit():
            return True
        else:
            return False



    @staticmethod
    def isEffectiveTid(tid, cond):
        try:
            tid = long(tid)

            ldir = cond.find('>')
            if ldir == 0 and tid >= long(cond[1:]):
                return True
            elif ldir == len(cond) - 1 and tid <= long(cond[:-1]):
                return True

            rdir = cond.find('<')
            if rdir == 0 and tid <= long(cond[1:]):
                return True
            elif rdir == len(cond) - 1 and tid >= long(cond[:-1]):
                return True

            if tid == cond or tid == long(cond):
                return True

            return False
        except SystemExit:
            sys.exit(0)
        except:
            return False



    @staticmethod
    def printBacktrace():
        traceback = SysMgr.getPkg('traceback')
        traceback.print_stack(file=SysMgr.stderr)



    @staticmethod
    def waitEvent(ignChldSig=True, exit=False, forceExit=False):
        # ignore SIGCHLD #
        if ignChldSig:
            signal.signal(signal.SIGCHLD, signal.SIG_IGN)

        # pause task #
        try:
            signal.pause()
        except SystemExit:
            if exit:
                sys.exit(0)
            elif forceExit:
                os._exit(0)
            else:
                pass
        except:
            pass



    @staticmethod
    def getProcTree():
        procTree = {}

        # get process list in proc filesystem #
        try:
            pids = os.listdir(SysMgr.procPath)
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printOpenErr(SysMgr.procPath)
            return None

        for pid in pids:
            try:
                long(pid)
            except:
                continue

            # make path of tid #
            procPath = "%s/%s" % (SysMgr.procPath, pid)
            taskPath = "%s/%s" % (procPath, 'task')

            # update comm of main thread #
            comm = SysMgr.getComm(pid)

            try:
                tids = os.listdir(taskPath)
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printOpenWarn(taskPath)
                continue

            for tid in tids:
                try:
                    long(tid)
                    if tid == pid:
                        procTree[tid] = '%s(%s)' % (pid, comm)
                    else:
                        procTree[tid] = pid
                except:
                    continue

        return procTree



    @staticmethod
    def setSortValue(value):
        if value == 'c':
            SysMgr.printInfo("sorted by COMM")
        elif value == 'm':
            SysMgr.printInfo("sorted by MEMORY")
        elif value == 'b':
            SysMgr.printInfo("sorted by BLOCK")
        elif value == 'w':
            SysMgr.printInfo("sorted by CHILD")
            SysMgr.wfcEnable = True
        elif value == 'p':
            SysMgr.printInfo("sorted by PID")
        elif value == 'n':
            SysMgr.printInfo("sorted by NEW")
        elif value == 'e':
            SysMgr.printInfo("sorted by EXECTIME")
            SysMgr.schedEnable = True
        elif value == 'r':
            SysMgr.printInfo("sorted by RUNTIME")
        elif value == 'o':
            SysMgr.printInfo("sorted by OOMSCORE")
            ThreadAnalyzer.setLastField('oom')
        elif value == 'P':
            SysMgr.printInfo("sorted by PRIORITY")
        elif value == 'f':
            SysMgr.printInfo("sorted by FILE")
            SysMgr.fileTopEnable = True
        elif value == 'C':
            if not SysMgr.isThreadTopMode():
                SysMgr.printErr(\
                   "Fail to sort by CONTEXTSWITCH because "
                    "it is supported on thread mode")
                sys.exit(0)
            SysMgr.printInfo("sorted by CONTEXTSWITCH")
            SysMgr.showAll = True
        elif not value:
            value = None
        else:
            SysMgr.printErr(\
                "wrong option value '%s' for sort" % value)
            return False

        SysMgr.sort = value
        return True



    @staticmethod
    def checkEnv():
        # check os #
        if sys.platform.startswith('linux'):
            SysMgr.isLinux = True

            # environment variables #
            try:
                # set default terminal to xterm #
                os.environ['TERM'] = 'xterm'

                # set run type #
                if "REMOTERUN" in os.environ:
                    SysMgr.encodeEnable = False
                    SysMgr.remoteRun = True

                # check encode condition #
                if not "LANG" in os.environ or \
                    'tty' in os.ttyname(sys.stdout.fileno()):
                    SysMgr.encodeEnable = False
            except SystemExit:
                sys.exit(0)
            except:
                pass

            # android #
            if 'ANDROID_ROOT' in os.environ:
                SysMgr.isAndroid = True
                SysMgr.libcPath = 'libc'
                SysMgr.libcppPath = 'libstdc++'
                SysMgr.libdemanglePath = 'libgccdemangle'
                SysMgr.cacheDirPath = '/data/log/guider'
        elif sys.platform.startswith('win') or \
            sys.platform.startswith('darwin'):
            SysMgr.isLinux = False
            if len(sys.argv) > 1 and \
                not SysMgr.isClientMode() and \
                not SysMgr.isDrawMode() and \
                not SysMgr.isConvertMode() and \
                not SysMgr.isReadelfMode() and \
                not SysMgr.isAddr2symMode() and \
                not SysMgr.isSym2addrMode() and \
                not SysMgr.isTopDiffMode() and \
                not SysMgr.isTopSumMode() and \
                not SysMgr.isPrintDirMode() and \
                not SysMgr.isReportMode() and \
                not SysMgr.isHelpMode():
                if len(sys.argv) == 1:
                    arg = sys.argv[0]
                else:
                    arg = sys.argv[1]

                SysMgr.printErr(\
                    '%s command is not supported on %s platform now' % \
                        (arg, sys.platform))
                sys.exit(0)
        else:
            SysMgr.printErr(\
                '%s platform is not supported now' % sys.platform)
            sys.exit(0)

        # check python #
        if sys.version_info < (2, 6):
            SysMgr.printWarn(\
                'python version is %d.%d so that some features may not work'
                % (sys.version_info[0], sys.version_info[1]))



    @staticmethod
    def onAlarm(signum, frame):
        SysMgr.progressCnt += 1
        if SysMgr.repeatCount <= SysMgr.progressCnt:
            sys.exit(0)

        SysMgr.updateTimer()



    @staticmethod
    def checkProgress():
        if not SysMgr.countEnable:
            return

        if SysMgr.progressCnt >= SysMgr.repeatCount:
            # remove progress #
            UtilMgr.deleteProgress()

            try:
                os.kill(SysMgr.pid, signal.SIGINT)
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printSigError(SysMgr.pid, 'SIGINT')

        if SysMgr.repeatCount > 1:
            UtilMgr.printProgress(\
                SysMgr.progressCnt, SysMgr.repeatCount)

        SysMgr.progressCnt += 1



    @staticmethod
    def getCmdString():
        cmdList = SysMgr.getCmdList()

        cmdbuf = ''
        for ctype, tvalue in sorted(cmdList.items()):
            prefix = ctype
            for cmd, cvalue in sorted(tvalue.items()):
                if len(prefix) > 0:
                    types = '[%s]' % prefix.upper()
                else:
                    types = ' '

                cmdbuf = '%s%4s%-12s%4s%-12s%4s<%-s>\n' % \
                    (cmdbuf, ' ', types, ' ', cmd, ' ', cvalue)
                prefix = ''
            cmdbuf = '%s\n' % cmdbuf

        return cmdbuf[:-1]



    @staticmethod
    def getCmdList():
        return {
            'monitor': {
                'top': 'Process',
                'ttop': 'Thread',
                'smtop': 'System',
                'bgtop': 'Background',
                'stacktop': 'Stack',
                'perftop': 'PMU',
                'memtop': 'Memory',
                'disktop': 'Storage',
                'nettop': 'Network',
                'wsstop': 'Memory',
                'reptop': 'JSON',
                'ftop': 'File',
                'systop': 'Syscall',
                'utop': 'Function',
                'btop': 'Breakpoint',
                'dlttop': 'DLT',
                'dbustop': 'D-Bus',
                },
            'trace': {
                'strace': 'Syscall',
                'utrace': 'Function',
                'btrace': 'Breakpoint',
                'sigtrace': 'Signal',
                },
            'profile': {
                'rec': 'Thread',
                'funcrec': 'Function',
                'filerec': 'File',
                'sysrec': 'Syscall',
                'genrec': 'System',
                'report': 'Report',
                'mem': 'Page',
                },
            'visual': {
                'draw': 'System',
                'cpudraw': 'CPU',
                'memdraw': 'Memory',
                'vssdraw': 'VSS',
                'rssdraw': 'RSS',
                'leakdraw': 'Leak',
                'iodraw': 'I/O',
                'convert': 'Text',
                },
            'util': {
                'topdiff': 'Diff',
                'topsum': 'Summary',
                'kill/tkill': 'Signal',
                'pause': 'Thread',
                'remote': 'Command',
                'limitcpu': 'CPU',
                'setcpu': 'Clock',
                'setsched': 'Priority',
                'getafnt': 'Affinity',
                'setafnt': 'Affinity',
                'pstree': 'Process',
                'systat': 'Status',
                'printenv': 'Env',
                'printinfo': 'System',
                'readelf': 'File',
                'addr2sym': 'Symbol',
                'sym2addr': 'Address',
                'leaktrace': 'Leak',
                'printcrp': 'Cgroup',
                'printdir': 'Dir',
                'printdbus': 'D-Bus',
                'printsig': 'D-Bus',
                'printns': 'Namespace',
                'printsvc': 'systemd',
                },
            'log': {
                'printkmsg': 'Kernel',
                'printdlt': 'DLT',
                'printsys': 'Syslog',
                'logkmsg': 'Kernel',
                'logdlt': 'DLT',
                'logjrl': 'Journal',
                'logsys': 'Syslog',
                },
            'control': {
                'list': 'List',
                'start': 'Signal',
                'send': 'Signal',
                'event': 'Event',
                'server': 'Server',
                'client': 'Client',
                },
            'test': {
                'cputest': 'CPU',
                'memtest': 'Memory',
                'iotest ': 'Storage',
                'nettest ': 'Network',
                },
            }



    @staticmethod
    def printHelp():
        printPipe = SysMgr.printPipe

        # help #
        if len(sys.argv) <= 1 or \
            SysMgr.isHelpMode():
            # get environment variable from launcher #
            if 'CMDLINE' in os.environ:
                cmd = os.environ['CMDLINE']
            else:
                cmd = sys.argv[0]

            # remove pyc file extention #
            if '.pyc' in cmd:
                cmd = cmd[:cmd.find('.pyc')]

            # disable extended ascii code support #
            SysMgr.encodeEnable = False

            defStr = '''
Usage:
    $ {0:1} COMMAND|FILE [OPTIONS] [--help]
                '''.format(cmd)

            # command help #
            if len(sys.argv) > 1 and \
                SysMgr.isHelpMode():
                # get command #
                mode = sys.argv[1]

                topCommonStr = '''
    -o  <DIR|FILE>              save output data
    -u                          run in the background
    -W                          wait for signal
    -b  <SIZE:KB>               set buffer size
    -T  <FILE>                  set font path
    -j  <DIR|FILE>              set report path
    -w  <TIME:FILE{:VALUE}>     set additional command
    -x  <IP:PORT>               set local address
    -X  <REQ@IP:PORT>           set request address
    -N  <REQ@IP:PORT>           set report address
    -S  <comm/memory/pid        sort by key
         block/wfc/new/file
         runtime/exectime
         Priority/oomscore
         Contextswitch>
    -P                          group threads in a same process
    -I  <DIR|FILE>              set input path
    -m  <ROWS:COLS>             set terminal size
    -a                          show all stats and events
    -g  <COMM|TID{:FILE}>       set filter
    -i  <SEC>                   set interval
    -R  <INTERVAL:TIME:TERM>    set repeat count
    -C  <PATH>                  set configuration path
    -Q                          print all rows in a stream
    -J                          print in JSON format
    -E  <DIR>                   set cache dir path
    -H  <LEVEL>                 set function depth level
    -k  <COMM|TID:SIG{:CONT}>   set signal list
    -z  <MASK:TID|ALL{:CONT}>   set CPU affinity list
    -Y  <POLICY:PRIO|TIME       set sched
         {:TID|COMM:CONT}>
    -v                          verbose
                '''

                topSubStr = '''
Options:
    -e  <CHARACTER>             enable options
            a:affinity | b:block | c:cpu | C:cgroup
            d:disk | D:DLT | e:encode | E:Elastic
            f:float | F:wfc | h:sigHandler | H:sched
            i:irq | j:journal | k:kmsg | L:cmdline
            m:memory | n:net | N:namespace | o:oomScore
            p:pipe | P:perf | q:quit | r:report
            R:fileReport | s:stack | S:pss | t:thread
            u:uss | w:wss | W:wchan | y:syslog | Y:delay
    -d  <CHARACTER>             disable options
            a:memAvailable | A:cpuAverage
            c:cpu | e:encode | G:gpu | L:log
            p:print | t:truncate | T:task
                                    '''

                drawSubStr = '''
Options:
    -g  <COMM|TID{:FILE}>       set filter
    -o  <DIR>                   save output data
    -a                          show all stats and events
    -T  <NUM>                   set top number
    -t  <START:END>             set range
    -L  <RES:PER>               set graph Layout
    -l  <BOUNDARY>              set boundary lines
    -E  <DIR>                   set cache dir path
    -v                          verbose
                    '''

                topExamStr = '''
Examples:
    - Monitor status of processes used CPU resource more than 1%
        # {0:1} {1:1}

    - Monitor status of all processes sorted by memory(RSS)
        # {0:1} {1:1} -S m

    - Report analysis results of processes to ./guider.out when SIGINT signal arrives
        # {0:1} {1:1} -o .

    - Report analysis results of processes to ./guider.out with unlimited memory buffer
        # {0:1} {1:1} -o . -b 0

    - Report analysis results of processes to ./guider.out in real-time until SIGINT signal arrives
        # {0:1} {1:1} -o . -e p

    - Report analysis results of processes collected every 3 seconds for 5 minutes to ./guider.out
        # {0:1} {1:1} -R 3s:5m -o .

    - Report analysis results of processes collected every 10 seconds for 60 minutes to ./guider.out
        # {0:1} {1:1} -i 10 -R 60m -o .

    - Report analysis results of processes collected every 3 seconds for 5 minutes to ./guider.out continuously
        # {0:1} {1:1} -R 3s:5m: -o .

    - Monitor status of processes including memory(USS)
        # {0:1} {1:1} -e u

    - Monitor status of processes including memory(PSS)
        # {0:1} {1:1} -e S

    - Monitor status of all processes including block usage every 2 seconds
        # {0:1} {1:1} -e b -i 2 -a

    - Monitor status of processes involved in a same process group with specific processes having name including system
        # {0:1} {1:1} -g system -P

    - Monitor status of processes on the minimum-size terminal
        # {0:1} {1:1} -m

    - Monitor status of processes on the optimized-size terminal
        # {0:1} {1:1} -m:

    - Report analysis results of processes to ./guider.out and console
        # {0:1} {1:1} -o . -Q

    - Monitor status of processes and execute special commands
        # {0:1} {1:1} -w AFTER:/tmp/touched:1, AFTER:ls

    - Monitor status of processes and report to 192.168.0.5:5555 in real-time
        # {0:1} {1:1} -e r -N REPORT_ALWAYS@192.168.0.5:5555

    - Monitor status of processes after setting configuration from guider.conf
        # {0:1} {1:1} -I guider.conf

                '''.format(cmd, mode)

                drawExamStr = '''
Examples:
    - Draw graphs of resource usage and memory chart
        # {0:1} {1:1} guider.out

    - Draw graphs of resource usage excluding chrome process and memory chart
        # {0:1} {1:1} guider.out -g ^chrome

    - Draw graphs of resource usage with some boundary lines
        # {0:1} {1:1} guider.out worstcase.out -l 80, 100, 120

    - Draw graphs of resource usage after cutting range
        # {0:1} {1:1} guider.out -t 1234:1239

    - Draw graphs of resource usage of top 5 processes
        # {0:1} {1:1} guider.out worstcase.out -T 5

    - Draw graphs of resource usage with ylimit 100
        # {0:1} {1:1} guider.out worstcase.out -H 100

    - Draw graphs of resource usage with multiple files for comparison
        # {0:1} {1:1} guider*.out worstcase.out
                '''.format(cmd, mode)

                brkExamStr = '''
Commands:
    start
    stop
    print
    exit
    kill
    ret:VAL
    exec:CMD
    sleep:SEC
    getarg:REGS
    setarg:REG#VAL
    load:PATH
    save:NAME
    jump:FUNC#ARGS
    usercall:FUNC#ARGS
    syscall:FUNC#ARGS
    rdmem:ADDR|REG:SIZE
    wrmem:ADDR|REG:VAL:SIZE
    filter:ADDR|REG:OP(EQ/DF/INC/BT/LT):VAL:SIZE

Examples:
    - Print all function calls for a specific thread
        # {0:1} {1:1} -g 1234

    - Print all function calls for a specific binary execution
        # {0:1} {1:1} -I "ls"

    - Print all function calls with backtrace for a specific thread
        # {0:1} {1:1} -g a.out -H

    - Print printPeace function calls for a specific thread
        # {0:1} {1:1} -g 1234 -c printPeace

    - Print a specific function call for a specific binary execution
        # {0:1} {1:1} -g 1234 -I ~/test/mutex -c "std::_Vector_base<unsigned long\, std::allocator<unsigned long> >::~_Vector_base()"

    - Print printPeace function calls only for 2 seconds
        # {0:1} {1:1} -g a.out -c printPeace -R 2s

    - Print and save printPeace function calls to ./guider.out
        # {0:1} {1:1} -g a.out -c printPeace -o . -a

    - Print specific function calls including specific word
        # {0:1} {1:1} -g 1234 -c \\*printPeace
        # {0:1} {1:1} -g 1234 -c printPeace\\*
        # {0:1} {1:1} -g 1234 -c \\*printPeace\\*

    - Print all function calls in specific files
        # {0:1} {1:1} -g a.out -c -T /usr/bin/yes

    - Handle specific function calls including specific word as a stop point
        # {0:1} {1:1} -g a.out -c \\*printPeace|stop
        # {0:1} {1:1} -g a.out -c printPeace\\*|stop
        # {0:1} {1:1} -g a.out -c \\*printPeace\\*|stop

    - Handle all function calls as a 0.1 second sleep point
        # {0:1} {1:1} -g a.out -c \\|sleep:0.1

    - Handle write function calls as a 0.1 second sleep point only one time
        # {0:1} {1:1} -g a.out -c write\\|oneshot:sleep:0.1

    - Handle write function calls as a kill point
        # {0:1} {1:1} -g a.out -c write\\|kill

    - Handle write function calls as a memory modification point
        # {0:1} {1:1} -g a.out -c write\\|wrmem:0x1234:aaaa:4

    - Handle write function calls as a modification point for memory pointed by 1st argument
        # {0:1} {1:1} -g a.out -c write\\|wrmem:0:aaaa:4

    - Handle printf function calls as a print point for 10-length string that 1st argument point to
        # {0:1} {1:1} -g a.out -c printf\\|rdmem:0:10

    - Handle printf function calls as a print point for 10-length string from the specific address
        # {0:1} {1:1} -g a.out -c printf\\|rdmem:0x1234:10

    - Handle write function calls as a return point for a specific value
        # {0:1} {1:1} -g a.out -c write\\|ret:3

    - Handle write function calls as a argument modification point for 1st and 2nd arguments
        # {0:1} {1:1} -g a.out -c write\\|setarg:0#2:1#5

    - Handle write function calls as a context print point
        # {0:1} {1:1} -g a.out -c write\\|print

    - Handle write function calls as a variable print point
        # {0:1} {1:1} -g a.out -c write\\|\\|save:VAR1\\|print:VAR1\\|save:VAR2:123:

    - Print value of PATH environment variable
        # {0:1} {1:1} -g a.out -c usercall:getenv#PATH, usercall:write#1#@getenv#1024

    - Print write function calls if the call meets specific conditions
        # {0:1} {1:1} -g a.out -c write\\|filter:2:EQ:4096
        # {0:1} {1:1} -g a.out -c write\\|filter:2:BT:0x1000
        # {0:1} {1:1} -g a.out -c write\\|filter:*1:EQ:HELLO
        # {0:1} {1:1} -g a.out -c write\\|filter:*1:INC:HE

    - Handle write function calls as a print point for 1st and 2nd arguments
        # {0:1} {1:1} -g a.out -c write\\|getarg:0:1

    - Handle write function calls as a print point for 1st and 2nd arguments and save its return value
        # {0:1} {1:1} -g a.out -c write\\|getarg:0:1\\|save:writeRet

    - Handle a write function call as a starting trace point for all functions
        # {0:1} {1:1} -g a.out -c write\\|start

    - Handle a write function call as a call point for sleep
        # {0:1} {1:1} -g a.out -c write\\|usercall:sleep#3
        # {0:1} {1:1} -g a.out -c write\\|usercall:printf#PEACE
        # {0:1} {1:1} -g a.out -c write\\|usercall:printf#\\"12345\\"

    - Handle a write function call as a syscall point for getpid
        # {0:1} {1:1} -g a.out -c write\\|syscall:getpid
        # {0:1} {1:1} -g a.out -c write\\|syscall:open#test.out#1

    - Handle a write function call as a load point for /usr/lib/preload.so
        # {0:1} {1:1} -g a.out -c write\\|load:/usr/lib/preload.so

    - Handle a write function call as a exit point
        # {0:1} {1:1} -g a.out -c write\\|exit

    - Handle write function calls as a jump point to the specific address with register values
        # {0:1} {1:1} -g a.out -c write\\|jump:sleep#5

    - Handle all function calls as a command execution point
        # {0:1} {1:1} -g a.out -c \\|exec:"ls -lha":"sleep 1"
        # {0:1} {1:1} -g a.out -c \\|exec:"ls -lha &"
                '''.format(cmd, mode)

                logCommonStr = '''
Usage:
    # {0:1} {1:1} -I <MESSAGE>

Description:
    Log a message

Options:
    -v                          verbose
    -R  <INTERVAL:TIME>         set repeat count
    -I  <LOG>                   set log message

Examples:
    - Log a message
        # {0:1} {1:1} -I "Hello World!"
                    '''.format(cmd, mode)

                printCommonStr = '''
Usage:
    # {0:1} {1:1}

Description:
    Print messages in real-time

Options:
    -v                          verbose
    -g  <WORD|TID>              set filter
    -c  <WORD>                  set filter
    -I  <FILE|FIELD>            set path / field
    -o  <DIR|FILE>              save output data

Examples:
    - Print messages in real-time
        # {0:1} {1:1}

    - Print messages including specific words in real-time
        # {0:1} {1:1} -g test

    - Print messages to the sepcific file
        # {0:1} {1:1} -o log.out
                    '''.format(cmd, mode)

                # function record #
                if SysMgr.isFuncRecordMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Record function events
                        '''.format(cmd, mode)

                    helpStr += '''
Options:
  [collect]
    -e  <CHARACTER>             enable options
          b:block | c:cgroup | e:encode | g:graph
          h:heap | L:lock | m:memory | p:pipe
    -d  <CHARACTER>             disable options
          a:all | c:cpu | C:compress | e:encode
          l:latency | L:log | u:user
    -s  <DIR|FILE>              save trace data
    -f                          force execution
    -u                          run in the background
    -b  <SIZE:KB>               set buffer size
    -t  <SYSCALL>               trace syscall
    -B  <DIR|FILE>              set command script path
    -W                          wait for signal
    -w  <TIME:FILE{:VALUE}>     set additional command
    -M  <FILE>                  set objdump path
    -U  <NAME:FUNC|ADDR:FILE>   set user event
    -K  <NAME:FUNC|ADDR:ARGS>   set kernel event

  [report]
    -o  <DIR|FILE>              save output data
    -S  <cpu/memory/pid         sort by key
         block/wfc/new
         runtime/file>
    -P                          group threads in a same process
    -O  <CORE>                  set core filter
    -l  <FILE>                  set addr2line path
    -r  <DIR>                   set root path
    -m  <ROWS:COLS>             set terminal size

  [common]
    -a                          show all stats and events
    -C  <PATH>                  set configuration path
    -g  <COMM|TID{:FILE}>       set filter
    -R  <INTERVAL:TIME:TERM>    set repeat count
    -Q                          print all rows in a stream
    -A  <ARCH>                  set CPU type
    -c  <EVENT:COND>            set custom event
    -E  <DIR>                   set cache dir path
    -H  <LEVEL>                 set function depth level
    -k  <COMM|TID:SIG{:CONT}>   set signal list
    -z  <MASK:TID|ALL{:CONT}>   set CPU affinity list
    -Y  <POLICY:PRIO|TIME       set sched
         {:TID|COMM:CONT}>
    -v                          verbose
                    '''

                    helpStr += '''
Examples:
    - record default function events of all threads to ./guider.dat
        # {0:1} {1:1} -s .

    - report function analysis result of all threads to ./guider.out
        # {0:1} guider.dat -o .

    - convert function event data compressed to original one
        # {0:1} guider.dat -s .

    - report all function analysis result with maximum 3-depth of a specific thread having TID 1234 to ./guider.out
        # {0:1} guider.dat -o . -g 1234 -H 3

    - report all function analysis result of specific threads including other threads involved in the same process to ./guider.out
        # {0:1} guider.dat -o . -P -g 1234, 4567 -a

    - record default function events of all threads to ./guider.dat for only 3 minutes
        # {0:1} guider.dat -o . -R 3m

    - record default function events of all threads to ./guider.dat every 3 minutes continuously
        # {0:1} guider.dat -o . -R 3m:1:

    - record default function events of specific threads having TID bigger than 1024 to ./guider.dat in the background
        # {0:1} {1:1} -s . -g 1024\< -u

    - record specific function events including memory, block, heap of all threads to ./guider.dat
        # {0:1} {1:1} -s . -e m, b, h

    - record specific function events including all systemcalls of all threads to ./guider.dat
        # {0:1} {1:1} -s . -t

    - record specific function events including softirq_entry event of all threads to ./guider.dat
        # {0:1} {1:1} -s . -c softirq_entry:vec==1

    - record specific function events including segmentation fault of all threads to ./guider.dat in real-time
        # {0:1} {1:1} -s . -d c -K segflt:bad_area -e p

    - record specific function events including blocking of all threads to ./guider.dat
        # {0:1} {1:1} -s . -d c -K block:schedule

    - record default function events of all threads to ./guider.dat and execute user commands
        # {0:1} {1:1} -s . -w BEFORE:/tmp/started:1, BEFORE:ls

    - record all kernel function calls of all threads to ./guider.dat
        # {0:1} {1:1} -s . -e g
                    '''.format(cmd, mode)

                # file record #
                elif SysMgr.isFileRecordMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Record on-memory file status
                        '''.format(cmd, mode)

                    helpStr += '''
Options:
    -e  <CHARACTER>             enable options
          p:pipe | e:encode
    -d  <CHARACTER>             disable options
          e:encode
    -s  <DIR|FILE>              save trace data
    -u                          run in the background
    -W                          wait for signal
    -w  <TIME:FILE{:VALUE}>     set additional command
    -o  <DIR|FILE>              save output data
    -m  <ROWS:COLS>             set terminal size
    -a                          show all stats and events
    -g  <COMM|TID{:FILE}>       set filter
    -Q                          print all rows in a stream
    -E  <DIR>                   set cache dir path
    -v                          verbose
                    '''

                    helpStr += '''
Examples:
    - report all analysis results of files mapped to all processes to ./guider.out
        # {0:1} {1:1} -o . -a

    - report analysis result on each intervals of files mapped to all processes to ./guider.out
        # {0:1} {1:1} -o . -i
                    '''.format(cmd, mode)

                # syscall record #
                elif SysMgr.isSyscallRecordMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Record syscall events
                        '''.format(cmd, mode)

                    helpStr += '''
Options:
    -e  <CHARACTER>             enable options
          p:pipe | e:encode
    -d  <CHARACTER>             disable options
          e:encode
    -s  <DIR|FILE>              save trace data
    -u                          run in the background
    -b  <SIZE:KB>               set buffer size
    -t  <SYSCALL>               trace syscall
    -W                          wait for signal
    -w  <TIME:FILE{:VALUE}>     set additional command
    -o  <DIR|FILE>              save output data
    -m  <ROWS:COLS>             set terminal size
    -a                          show all stats and events
    -g  <COMM|TID{:FILE}>       set filter
    -E  <DIR>                   set cache dir path
    -v                          verbose
                    '''

                    helpStr += '''
Examples:
    - record all syscall events of all threads to ./guider.dat
        # {0:1} {1:1} -s .

    - report analysis result of specific syscalls to ./guider.out
        # {0:1} guider.dat -o . -t read, write
                    '''.format(cmd, mode)

                # report #
                elif SysMgr.isReportMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Report analysis result based on guider.dat
                        '''.format(cmd, mode)

                    helpStr += '''
Options:
    -e  <CHARACTER>             enable options
          p:pipe | e:encode
    -d  <CHARACTER>             disable options
          e:encode
    -o  <DIR|FILE>              save output data
    -m  <ROWS:COLS>             set terminal size
    -a                          show all stats and events
    -g  <COMM|TID{:FILE}>       set filter
    -I  <DIR|FILE>              set input path
    -E  <DIR>                   set cache dir path
    -v                          verbose
                    '''

                    helpStr += '''
Examples:
    - report analysis result based on guider.dat to ./guider.out
        # {0:1} {1:1}

    - report all analysis result based on guider.dat for a specific thread to ./guider.out
        # {0:1} {1:1} -g 1234 -a
                    '''.format(cmd, mode)

                # general record #
                elif SysMgr.isGeneralRecordMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Record system status
                        '''.format(cmd, mode)

                    helpStr += '''
Options:
    -e  <CHARACTER>             enable options
          p:pipe | e:encode
    -d  <CHARACTER>             disable options
          e:encode
    -s  <DIR|FILE>              save trace data
    -u                          run in the background
    -W                          wait for signal
    -o  <DIR|FILE>              save output data
    -m  <ROWS:COLS>             set terminal size
    -Q                          print all rows in a stream
    -E  <DIR>                   set cache dir path
    -v                          verbose
                    '''

                    helpStr += '''
Examples:
    - report analysis results of system to ./guider.out
        # {0:1} {1:1} -o .
                    '''.format(cmd, mode)

                # thread record #
                elif SysMgr.isThreadRecordMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Record thread events
                        '''.format(cmd, mode)

                    helpStr += '''
Options:
  [collect]
    -e  <CHARACTER>             enable options
            b:block | c:cgroup | e:encode | g:graph
            i:irq | L:lock | m:memory | n:net
            p:pipe | r:reset | P:power
    -d  <CHARACTER>             disable options
            a:all | c:cpu | C:compress | e:encode
    -s  <DIR|FILE>              save trace data
    -f                          force execution
    -u                          run in the background
    -W                          wait for signal
    -b  <SIZE:KB>               set buffer size
    -D                          trace thread dependency
    -t  <SYSCALL>               trace syscall
    -B  <DIR|FILE>              set command script path
    -w  <TIME:FILE{:VALUE}>     set additional command
    -U  <NAME:FUNC|ADDR:FILE>   set user event
    -K  <NAME:FUNC|ADDR:ARGS>   set kernel event
    -R  <INTERVAL:TIME:TERM>    set repeat count

  [report]
    -a                          show all stats and events
    -o  <DIR|FILE>              save output data
    -S  <cpu/memory/pid         sort by key
         block/wfc/new
         runtime/file>
    -P                          group threads in a same process
    -p  <TID>                   show preemption info
    -O  <CORE>                  set core filter
    -L  <RES:PER>               set graph Layout
    -m  <ROWS:COLS>             set terminal size
    -i  <SEC>                   set interval
    -Q                          print all rows in a stream

  [common]
    -g  <COMM|TID{:FILE}>       set filter
    -C  <PATH>                  set configuration path
    -A  <ARCH>                  set CPU type
    -c  <EVENT:COND>            set custom event
    -E  <DIR>                   set cache dir path
    -k  <COMM|TID:SIG{:CONT}>   set signal list
    -z  <MASK:TID|ALL{:CONT}>   set CPU affinity list
    -Y  <POLICY:PRIO|TIME       set sched
         {:TID|COMM:CONT}>
    -v                          verbose
                    '''

                    helpStr += '''
Examples:
    - record default events of all threads to ./guider.dat
        # {0:1} {1:1} -s .

    - report analysis result of all threads to ./guider.out
        # {0:1} guider.dat -o .

    - convert event data compressed to original one
        # {0:1} guider.dat -s .

    - record default events of all threads and their commands
        # {0:1} {1:1} -s . -B

    - report all analysis results of a specific thread having TID 1234 to ./guider.out
        # {0:1} guider.dat -o . -g 1234 -a

    - report all analysis results including interval information of all threads to ./guider.out
        # {0:1} guider.dat -o . -a -i

    - record default events of all threads to ./guider.dat for only 3 seconds
        # {0:1} guider.dat -o . -R 3

    - record default events of all threads to ./guider.dat every 3 seconds continuously
        # {0:1} guider.dat -o . -R 3:1:

    - record specific events including memory, block, irq of all threads to ./guider.dat in the background
        # {0:1} {1:1} -s . -e m, b, i -u

    - record default events including specific systemcalls of all threads to ./guider.dat
        # {0:1} {1:1} -s . -t sys_read, write

    - record default events including lock of all threads to ./guider.dat
        # {0:1} {1:1} -s . -e L

    - record default events including specific user function of all threads to ./guider.dat
        # {0:1} {1:1} -s . -U evt1:func1:/tmp/a.out, evt2:0x1234:/tmp/b.out

    - record default events including specific kernel function of all threads to ./guider.dat
        # {0:1} {1:1} -s . -d c -K evt1:func1:u32, evt2:0x1234:s16, evt3:func2:x16

    - record default events including specific kernel function with args of all threads on x86 to ./guider.dat
        # {0:1} {1:1} -s . -d c -K open:do_sys_open:dfd=%ax\ filename=%bx\;u64\ flags=%cx\;s32\ mode=+4\(\$stack\):NONE

    - record default events including specific kernel function with register values of all threads on x86 to ./guider.dat
        # {0:1} {1:1} -s . -d c -K strace32:func1:%bp/u32.%sp/s64, strace:0x1234:$stack:NONE

    - record default events including specific kernel function with the return value of all threads to ./guider.dat
        # {0:1} {1:1} -s . -d c -K openfile:getname::*string, access:0x1234:NONE:*string
        # {0:1} {1:1} -s . -d c -K openfile:getname::**string, access:0x1234:NONE:*string

    - record default events of all threads to ./guider.dat and execute user commands
        # {0:1} {1:1} -s . -w BEFORE:/tmp/started:1, BEFORE:ls

    - report all analysis results including specific threads's preemption of all threads to ./guider.out
        # {0:1} guider.dat -o . -p 1234, 4567 -a

    - report all analysis results of specific threads including other threads involved in the same process to ./guider.out
        # {0:1} guider.dat -o . -P -g 1234, 4567 -a
                    '''.format(cmd, mode)

                # file top #
                elif SysMgr.isFileTopMode():
                    fileTopStr = topCommonStr

                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor the status of open files / sockets / pipes
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor open files including null of all processes
        # {0:1} {1:1} -g :null

    - Monitor open files of specific processes including system
        # {0:1} {1:1} -g system

    - Monitor all processes sorted by the number of file descriptors
        # {0:1} {1:1} -g system

    - Report analysis result of open files to ./guider.out
        # {0:1} {1:1} -o .

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += fileTopStr + examStr

                # thread top #
                elif SysMgr.isThreadTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor thread status
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor status of all threads
        # {0:1} {1:1} -a

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + examStr

                # syscall top #
                elif SysMgr.isSysTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor syscalls for a specific thread
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor syscalls for a specific thread
        # {0:1} {1:1} -g a.out

    - Monitor syscalls with backtrace for a specific thread
        # {0:1} {1:1} -g a.out -H

    - Monitor syscalls for a specific thread every 2 second
        # {0:1} {1:1} -g 1234 -R 2:

    - Monitor CPU usage on whole system of syscalls for a specific thread
        # {0:1} {1:1} -g a.out -e c

    - Monitor systemcalls with breakpoint for read including register info for a specific thread
        # {0:1} {1:1} -g 1234 -c read -a

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + examStr

                # usercall top #
                elif SysMgr.isUserTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor usercalls for a specific thread
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor usercalls for a specific thread
        # {0:1} {1:1} -g a.out

    - Monitor usercalls with backtrace for a specific thread
        # {0:1} {1:1} -g a.out -H

    - Monitor usercalls for a specific thread every 2 second for 1 minute with 1 ms sampling
        # {0:1} {1:1} -g 1234 -T 1000 -i 2 -R 1m

    - Monitor CPU usage on whole system of usercalls for a specific thread
        # {0:1} {1:1} -g a.out -e c

    - Monitor usercalls with breakpoint for peace including register info for a specific thread
        # {0:1} {1:1} -g 1234 -c peace -a

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topCommonStr + examStr

                # break top #
                elif SysMgr.isBrkTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor breakpoints for a specific thread
                        '''.format(cmd, mode)

                    examStr = '''
    {0:1}

    See the top COMMAND help for more examples.
                    '''.format(brkExamStr)

                    helpStr += topCommonStr + examStr

                # system top #
                elif SysMgr.isSystemTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor system status
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor status of system
        # {0:1} {1:1}

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topCommonStr + examStr

                # stack top #
                elif SysMgr.isStackTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor stack status
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor stacks of specific threads
        # {0:1} {1:1} -g chrome

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + examStr

                # perf top #
                elif SysMgr.isPerfTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor PMU(Performance Monitoring Unit) status
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor performance stats of specific threads
        # {0:1} {1:1} -g chrome

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + examStr

                # mem top #
                elif SysMgr.isMemTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor memory details
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor memory details of specific processes
        # {0:1} {1:1} -g chrome

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + examStr

                # wss top #
                elif SysMgr.isWssTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor WSS(Working Set Size) of processes after clearing page reference bits
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor WSS(Working Set Size) change of specific processes
        # {0:1} {1:1} -g chrome

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + examStr

                # report top #
                elif SysMgr.isReportTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Report system status in JSON format
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Report system status in JSON format to ./guider.report in the background every second
        # {0:1} {1:1} -j . -u

    - Stop reporting processes in the background
        # {0:1} stop

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + examStr

                # background top #
                elif SysMgr.isBgTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Collect system status in the background until get a stop signal
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Collect system status to ./guider.out in the background
        # {0:1} {1:1} -o .

    - Stop collecting processes in the background and let them report system analysis result
        # {0:1} stop

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + examStr

                # disk top #
                elif SysMgr.isDiskTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor storage status
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor status of all storages
        # {0:1} {1:1}

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + examStr

                # DLT top #
                elif SysMgr.isDltTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor DLT logs
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor DLT logs
        # {0:1} {1:1}

    - Change default log level to be printed
        # {0:1} {1:1} -c INFO

    - Monitor DLT logs including specific string
        # {0:1} {1:1} -g test

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + examStr

                # dbus top #
                elif SysMgr.isDbusTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor D-Bus messages
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor D-Bus messages
        # {0:1} {1:1}

    - Monitor D-Bus messages for dbus-client process
        # {0:1} {1:1} -g dbus-client

    - Monitor D-Bus messages including specific word
        # {0:1} {1:1} -c test

    - Monitor D-Bus messages for a specific session bus
        # DBUS_SESSION_BUS_ADDRESS=$(cat addr) {0:1} {1:1}

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + examStr

                # network top #
                elif SysMgr.isNetTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor network status
                        '''.format(cmd, mode)

                    examStr = '''
Examples:
    - Monitor status of all network devices
        # {0:1} {1:1}

    See the top COMMAND help for more examples.
                    '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + examStr

                # process top #
                elif SysMgr.isTopMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Monitor process status
                        '''.format(cmd, mode)

                    helpStr += topSubStr + topCommonStr + topExamStr

                # strace #
                elif SysMgr.isStraceMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Trace systemcalls
                        '''.format(cmd, mode)

                    helpStr +=  '''
Options:
    -e  <CHARACTER>             enable options
          p:pipe | e:encode
    -d  <CHARACTER>             disable options
          e:encode
    -u                          run in the background
    -a                          show all stats including registers
    -g  <COMM|TID{:FILE}>       set filter
    -I  <COMMAND>               set command
    -R  <TIME>                  set timer
    -c  <EVENT>                 set breakpoint
    -o  <DIR|FILE>              save output data
    -m  <ROWS:COLS>             set terminal size
    -E  <DIR>                   set cache dir path
    -v                          verbose
                    '''

                    helpStr +=  '''
Examples:
    - Trace all read systemcalls for a specific thread
        # {0:1} {1:1} -g 1234 -t read

    - Trace all write systemcalls with specific command
        # {0:1} {1:1} -I "ls -al" -t write

    - Trace all read systemcalls for a specific thread and save summary tables, call history to ./guider.out
        # {0:1} {1:1} -g 1234 -t read -o . -a

    - Trace all systemcalls with breakpoint for read including register info for a specific thread
        # {0:1} {1:1} -g 1234 -c read -a

    - Trace all systemcalls for a specific thread only for 1 minute
        # {0:1} {1:1} -g 1234 -R 1m

    - Trace all systemcalls and pause when catching open systemcall
        # {0:1} {1:1} -I "ls -al" -c open
                    '''.format(cmd, mode)

                # utrace #
                elif SysMgr.isUtraceMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Trace all usercalls
                        '''.format(cmd, mode)

                    helpStr +=  '''
Options:
    -e  <CHARACTER>             enable options
          p:pipe | e:encode
    -d  <CHARACTER>             disable options
          e:encode
    -u                          run in the background
    -a                          show all stats including registers
    -g  <COMM|TID{:FILE}>       set filter
    -I  <COMMAND>               set command
    -R  <TIME>                  set timer
    -c  <EVENT>                 set breakpoint
    -H  <SKIP>                  set instrunction sampling rate
    -o  <DIR|FILE>              save output data
    -m  <ROWS:COLS>             set terminal size
    -E  <DIR>                   set cache dir path
    -v                          verbose
                    '''

                    helpStr +=  '''
Examples:
    - Trace usercalls for a specific thread in 100us cycles
        # {0:1} {1:1} -g 1234

    - Trace usercalls for a specific thread in 10ms cycles
        # {0:1} {1:1} -g 1234 -i 10000

    - Trace usercalls with 1/10 instructions for a specific thread
        # {0:1} {1:1} -g 1234 -H 10

    - Trace usercalls for a specific thread and save summary tables, call history to ./guider.out
        # {0:1} {1:1} -g 1234 -o . -a

    - Trace usercalls with breakpoint for peace including register info for a specific thread
        # {0:1} {1:1} -g 1234 -c peace -a

    - Trace usercalls for a specific thread only for 2 seconds
        # {0:1} {1:1} -g 1234 -R 2s

    - Trace usercalls and pause when catching PLT function call
        # {0:1} {1:1} -I "ls -al" -c PLT
                    '''.format(cmd, mode)

                # btrace #
                elif SysMgr.isBtraceMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Trace specific usercalls
                        '''.format(cmd, mode)

                    helpStr +=  '''
Options:
    -e  <CHARACTER>             enable options
          p:pipe | e:encode
    -d  <CHARACTER>             disable options
          e:encode
    -u                          run in the background
    -a                          show all stats including registers
    -T  <FILE>                  set file
    -g  <COMM|TID{:FILE}>       set filter
    -I  <COMMAND>               set command
    -R  <TIME>                  set timer
    -c  <SYM|ADDR{:CMD}>        set breakpoint
    -H  <LEVEL>                 set function depth level
    -o  <DIR|FILE>              save output data
    -m  <ROWS:COLS>             set terminal size
    -E  <DIR>                   set cache dir path
    -v                          verbose
                    '''

                    helpStr +=  brkExamStr

                # remote #
                elif SysMgr.isRemoteMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -c <COMMAND> [OPTIONS] [--help]

Description:
    Execute commands remotely
                        '''.format(cmd, mode)

                    helpStr +=  '''
Options:
    -u                          run in the background
    -a                          show all stats including registers
    -g  <COMM|TID{:FILE}>       set filter
    -R  <TIME>                  set timer
    -c  <SYM|ADDR{:CMD}>        set command
    -H  <LEVEL>                 set function depth level
    -o  <DIR|FILE>              save output data
    -m  <ROWS:COLS>             set terminal size
    -E  <DIR>                   set cache dir path
    -v                          verbose
                    '''

                    helpStr +=  brkExamStr

                # sigtrace #
                elif SysMgr.isSigtraceMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Trace signals
                        '''.format(cmd, mode)

                    helpStr +=  '''
Options:
    -e  <CHARACTER>             enable options
          p:pipe | e:encode
    -d  <CHARACTER>             disable options
          e:encode
    -u                          run in the background
    -g  <COMM|TID{:FILE}>       set filter
    -I  <COMMAND>               set command
    -R  <TIME>                  set timer
    -H  <LEVEL>                 set function depth level
    -o  <DIR|FILE>              save output data
    -m  <ROWS:COLS>             set terminal size
    -E  <DIR>                   set cache dir path
    -v                          verbose
                    '''

                    helpStr +=  '''
Examples:
    - Trace all signals for a specific thread
        # {0:1} {1:1} -g 1234

    - Trace all signals for a specific command
        # {0:1} {1:1} -I "ls"

    - Trace the SIGINT signal for a specific thread
        # {0:1} {1:1} -g 1234 -c SIGINT
                    '''.format(cmd, mode)

                # mem #
                elif SysMgr.isMemMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Analyze page attributes
                        '''.format(cmd, mode)

                    helpStr += '''
Options:
    -e  <CHARACTER>             enable options
          e:encode
    -d  <CHARACTER>             disable options
          e:encode
    -g  <COMM|TID{:FILE}>       set filter
    -o  <DIR|FILE>              save output data
    -I  <ADDR>                  set address area
    -m  <ROWS:COLS>             set terminal size
    -v                          verbose
                    '''

                    helpStr +=  '''
Examples:
    - Analyze page attributes in specific area for a specific process
        # {0:1} {1:1} -g 1234 -I 0x0-0x4000
                    '''.format(cmd, mode)

                # CPU draw #
                elif SysMgr.isCpuDrawMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} FILE [OPTIONS] [--help]

Description:
    Draw CPU graphs and memory chart
                        '''.format(cmd, mode)

                    helpStr += drawSubStr + drawExamStr

                # memory draw #
                elif SysMgr.isMemDrawMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} FILE [OPTIONS] [--help]

Description:
    Draw system memory graphs and memory chart
                        '''.format(cmd, mode)

                    helpStr += drawSubStr + drawExamStr

                # vss draw #
                elif SysMgr.isVssDrawMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} FILE [OPTIONS] [--help]

Description:
    Draw process memory(VSS) graphs and memory chart
                        '''.format(cmd, mode)

                    helpStr += drawSubStr + drawExamStr

                # rss draw #
                elif SysMgr.isRssDrawMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} FILE [OPTIONS] [--help]

Description:
    Draw process memory(RSS) graphs and memory chart
                        '''.format(cmd, mode)

                    helpStr += drawSubStr + drawExamStr

                # leak draw #
                elif SysMgr.isLeakDrawMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} FILE [OPTIONS] [--help]

Description:
    Draw memory(VSS) graphs of processes suspected memory leak and memory chart
                        '''.format(cmd, mode)

                    helpStr += drawSubStr + drawExamStr

                # I/O draw #
                elif SysMgr.isIoDrawMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} FILE [OPTIONS] [--help]

Description:
    Draw system I/O graphs and memory chart
                        '''.format(cmd, mode)

                    helpStr += drawSubStr + drawExamStr

                # draw #
                elif SysMgr.isDrawMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} FILE [OPTIONS] [--help]

Description:
    Draw system resource graphs and memory chart
                        '''.format(cmd, mode)

                    helpStr += drawSubStr + drawExamStr

                # topdiff #
                elif SysMgr.isTopDiffMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} FILE [OPTIONS] [--help]

Description:
    Diff top report files
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Diff top report files
        # {0:1} {1:1} tc1.out tc2.out

    - Diff top report files
        # {0:1} {1:1} tc*.out
                    '''.format(cmd, mode)

                # topsum #
                elif SysMgr.isTopSumMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} FILE [OPTIONS] [--help]

Description:
    Summary a top output file
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Summary a top output file
        # {0:1} {1:1} output

    - Summary a top output file into summary.out
        # {0:1} {1:1} output -o guider.out
                    '''.format(cmd, mode)

                # kill / send #
                elif SysMgr.isKillMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -<SIGNUM|SIGNAME> <PID|COMM> [OPTIONS] [--help]

Description:
    Send specific signal to specific tasks or all running Guiders

Options:
    -g  <TID|COMM>              set filter
    -l                          print signal list
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Send the notification signal to all running Guiders
        # {0:1} {1:1}

    - Send SIGSTOP signal to a specific tasks
        # {0:1} {1:1} -stop 1234

    - Send SIGKILL signal to a specific tasks
        # {0:1} {1:1} -9 1234
                    '''.format(cmd, mode)

                # pause #
                elif SysMgr.isPauseMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -g <TID|COMM> [OPTIONS] [--help]

Description:
    Pause specific running threads

Options:
    -g  <TID|COMM>              set filter
    -R  <TIME>                  set timer
    -u                          run in the background
    -P                          group threads in a same process
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Pause specific running threads for 3 seconds
        # {0:1} {1:1} -g 1234 -R 3

    - Pause specific running threads including a same process group
        # {0:1} {1:1} -g 1234 -P
                    '''.format(cmd, mode)

                # readelf #
                elif SysMgr.isReadelfMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -I <FILE> [OPTIONS] [--help]

Description:
    Show information about ELF file

Options:
        -I  <FILE>                  set input path
        -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Print ELF infomation of specific file
        # {0:1} {1:1} -I /usr/bin/yes

    - Print vDSO infomation
        # {0:1} {1:1} -I vdso
                    '''.format(cmd, mode)

                # log #
                elif SysMgr.isLogDltMode() or \
                    SysMgr.isLogKmsgMode() or \
                    SysMgr.isLogSysMode() or \
                    SysMgr.isLogJournalMode():
                    helpStr = logCommonStr

                # printdlt #
                elif SysMgr.isPrintDltMode() or \
                    SysMgr.isPrintDbusMode() or \
                    SysMgr.isPrintKmsgMode() or \
                    SysMgr.isPrintJournalMode() or \
                    SysMgr.isPrintSyslogMode():
                    helpStr = printCommonStr

                    if SysMgr.isPrintDbusMode():
                        helpStr +=  '''
    - Print D-Bus messages with detailed information in real-time
        # {0:1} {1:1} -a

    - Print D-Bus messages including specific word in real-time
        # {0:1} {1:1} -c test

    - Print D-Bus messages with backtrace for a.out process in real-time
        # {0:1} {1:1} -g a.out -H

    - Print D-Bus messages for a specific session bus
        # DBUS_SESSION_BUS_ADDRESS=$(cat addr) {0:1} {1:1}
                    '''.format(cmd, mode)

                    if SysMgr.isPrintJournalMode():
                        helpStr +=  '''
    - Print journal messages with all fields in real-time
        # {0:1} {1:1} -I

    - Print journal messages with specific fields in real-time
        # {0:1} {1:1} -I _TIME, _COMM, _PID

    - Print all journal messages
        # {0:1} {1:1} -a
                    '''.format(cmd, mode)

                    if SysMgr.isPrintDltMode():
                        helpStr +=  '''
    - Print DLT messages from specific files
        # {0:1} {1:1} -I "./*.dlt"

    - Change default log level to be printed
        # {0:1} {1:1} -c INFO

    - Print DLT messages sorted by line from specific files
        # {0:1} {1:1} -I "./*.dlt" -S
                    '''.format(cmd, mode)

                # printsig #
                elif SysMgr.isPrintSigMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Show D-Bus signal subscription info

Options:
    -o  <DIR|FILE>              save output data
    -a                          show all stats
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Print D-Bus signal subscription info
        # {0:1} {1:1}

    - Print D-Bus signal subscription info with specific values
        # {0:1} {1:1} -a

    - Print D-Bus signal subscription info to a specific file
        # {0:1} {1:1} -o sig.out
                    '''.format(cmd, mode)

                # addr2sym #
                elif SysMgr.isAddr2symMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -I <FILE> -g <OFFSET> [OPTIONS] [--help]

Description:
    Show symbols of specific addresses in a file or a process memory map

Options:
    -I  <FILE|COMM|PID>         set input path or process
    -g  <OFFSET>                set offset
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Print symbol infomation of specific addresses in a file
        # {0:1} {1:1} -I /usr/bin/yes -g ab1cf

    - Print symbol infomation of specific addresses in a process memory map
        # {0:1} {1:1} -I yes -g ab1cf
                    '''.format(cmd, mode)

                # sym2addr#
                elif SysMgr.isSym2addrMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -I <FILE|COMM|PID> -g <SYMBOL> [OPTIONS] [--help]

Description:
    Show files and offset of specific symbols in a file or a process memory map

Options:
    -I  <FILE|COMM|PID>         set input path or process
    -g  <SYMBOL>                set offset
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Print infomation of specific symbols in a file
        # {0:1} {1:1} -I /usr/bin/yes -g testFunc

    - Print infomation of all symbols in a file
        # {0:1} {1:1} -I /usr/bin/yes -g

    - Print infomation of specific symbols including specific word in a file
        # {0:1} {1:1} -I /usr/bin/yes -g \\*testFunc
        # {0:1} {1:1} -I /usr/bin/yes -g testFunc\\*
        # {0:1} {1:1} -I /usr/bin/yes -g \\*testFunc\\*

    - Print infomation of specific symbols including specific word in a file
        # {0:1} {1:1} -I ~/test/mutex -g "std::_Vector_base<unsigned long\, std::allocator<unsigned long> >::~_Vector_base()"

    - Print infomation of specific symbols in a process memory map
        # {0:1} {1:1} -I yes -g testFunc
                    '''.format(cmd, mode)

                # printcgroup #
                elif SysMgr.isPrintCgroupMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Show system cgroup tree

Options:
    -v                          verbose
    -a                          show name of all processes
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Print system cgroup tree
        # {0:1} {1:1}

    - Print system cgroup tree with the name of processes
        # {0:1} {1:1} -a
                    '''.format(cmd, mode)

                # printdir #
                elif SysMgr.isPrintDirMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Show directory structure

Options:
    -v                          verbose
    -I  <DIR>                   set input path
    -a                          show all attributes
    -H  <LEVEL>                 set function depth level
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Print directory structure from current working directory
        # {0:1} {1:1}

    - Print directory structure from / dir
        # {0:1} {1:1} -I /

    - Print directory structure in 2-depth from / dir
        # {0:1} {1:1} -I / -H 2

    - Print directory structure with attributes from / dir
        # {0:1} {1:1} -I / -a
                    '''.format(cmd, mode)

                # leaktracer #
                elif SysMgr.isLeaktraceMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -I <FILE> -g <PID|COMM> [OPTIONS] [--help]

Description:
    Show functions caused memory leakage with leaktracer output

    Get libleaktracer.so from https://github.com/iipeace/portable/tree/master/leaktracer

    Run the target process with below specific environment variables
    $ LD_PRELOAD=./libleaktracer.so \\
        LEAKTRACER_AUTO_REPORTFILENAME=leaks.out \\
        LEAKTRACER_ONSIG_REPORT=36 EXEC
    $ LD_PRELOAD=./libleaktracer.so \\
        LEAKTRACER_ONSIG_REPORTFILENAME=leaks.out \\
        LEAKTRACER_ONSIG_STARTALLTHREAD=35 \\
        LEAKTRACER_ONSIG_REPORT=36 EXEC

    If the target process is on secure-execution mode,
    libleaktracer.so should be in standard search directoriesspecified in /etc/ld.so.conf,
    And all slashes in it's preload path will be ignored
    Otherwise add the library path to /etc/ld.so.preload

Options:
    -I  <FILE>                  set input path
    -o  <DIR|FILE>              save output data
    -c  <{{STARTSIZE:}}ENDSIZE>   set condition for RSS
    -g  <PID|COMM>              set target process
    -k  <{{START,}}TERM>          set signal
    -C  <PATH>                  set configuration path
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Create an output file for memory leakage hints of a specific process after sending signal 36 to stop profiling
        # {0:1} {1:1} -g a.out -I ~/work/test/leaks.out -k 36

    - Create an output file for memory leakage hints of a specific process when it's RSS reached the specific size
        # {0:1} {1:1} -g a.out -I ~/work/test/leaks.out -c 20m -k 35,36
        # {0:1} {1:1} -g a.out -I ~/work/test/leaks.out -c 15m,20m -k 35,36

    - Print funtions caused memory leakage of a specific process
        # {0:1} {1:1} -I leaks.out -g a.out
                    '''.format(cmd, mode)

                # printenv #
                elif SysMgr.isPrintEnvMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -g <PID> [OPTIONS] [--help]

Description:
    Show environment variables for a specific process

Options:
    -g  <PID|COMM>              set target process
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Print environment variables for a specific process
        # {0:1} {1:1} -g 1234
        # {0:1} {1:1} -g a.out
                    '''.format(cmd, mode)

                # printns #
                elif SysMgr.isPrintNsMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Show namespace list

Options:
    -a                          show all attributes
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Print namespace list
        # {0:1} {1:1}

    - Print namespace list with tasks
        # {0:1} {1:1} -a
                    '''.format(cmd, mode)

                # printsvc #
                elif SysMgr.isPrintSvcMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Show systemd services

Options:
    -a                          show all attributes
    -g  <NAME>                  set target file
    -c  <ATTR>                  set target attribute
    -I  <DIR>                   set input path
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Print systemd services
        # {0:1} {1:1}

    - Print systemd services about only specific files
        # {0:1} {1:1} -g test

    - Print systemd services including specific attributes
        # {0:1} {1:1} -c Restart

    - Print systemd services including specific value of attributes
        # {0:1} {1:1} -c :pid

    - Print systemd services in specific directories
        # {0:1} {1:1} -I /home/iipeace/services
                    '''.format(cmd, mode)

                # printinfo #
                elif SysMgr.isPrintInfoMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Show system general info

Options:
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Print system info
        # {0:1} {1:1}
                    '''.format(cmd, mode)

                # pstree #
                elif SysMgr.isPstreeMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Print the tree of processes

Options:
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Print tree of processes
        # {0:1} {1:1}
                    '''.format(cmd, mode)

                # systat #
                elif SysMgr.isSystatMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Print system status

Options:
    -e  <CHARACTER>             enable options
          t:thread
    -J                          print in JSON format
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Print system status
        # {0:1} {1:1}
                    '''.format(cmd, mode)

                # limitcpu #
                elif SysMgr.isLimitCpuMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -g <TID|PID:PER> [OPTIONS] [--help]

Description:
    Limit CPU usage of threads / processes

Options:
    -g  <TID|COMM>              set filter
    -R  <TIME>                  set timer
    -P                          group threads in a same process
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Limit CPU usage of specific threads for 3 seconds
        # {0:1} {1:1} -g 1234:10, yes:20 -R 3
                    '''.format(cmd, mode)

                # setcpu #
                elif SysMgr.isSetCpuMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -g <CORE:CLOCK:GOVERNOR> [OPTIONS] [--help]

Description:
    Set CPU clock and governor

Options:
    -g  <CORE:CLOCK:GOVERNOR>   set filter
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Set the clock of cpu1 to 10000000HZ and the governor of cpu1 to userspace
        # {0:1} {1:1} -g 1:10000000:userspace

    - Set the clock of cpu0 to 10000000HZ
        # {0:1} {1:1} -g 0:10000000

    - Set the governor of cpu2 to performance
        # {0:1} {1:1} -g 2:0:performance
                    '''.format(cmd, mode)

                # convert #
                elif SysMgr.isConvertMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} <FILE> [OPTIONS] [--help]

Description:
    Convert a text file to a image file

Options:
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Convert a text file to a image file
        # {0:1} {1:1} guider.out
                    '''.format(cmd, mode)

                # setsched #
                elif SysMgr.isSetSchedMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -g <POLICY:PRIORITY|TIME:TID|COMM> [OPTIONS] [--help]

Description:
    Set CPU scheduler policy and priority of threads / processes

Policy:
    c: CFS
    f: FIFO(RT)
    r: RR(RT)
    B: BATCH
    I: IDLE
    d: DEADLINE

Options:
    -g <POLICY:PRIORITY|TIME:TID|COMM> set value
    -P                                 group threads in a same process
    -v                                 verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Set CPU scheduler policy(CFS), priority(-20) for a specific thread
        # {0:1} {1:1} -g c:-20:1234

    - Set CPU scheduler policy(FIFO), priority(90) for a specific thread
        # {0:1} {1:1} -g f:90:1234

    - Set CPU scheduler policy(DEADLINE), runtime(1ms), deadline(10ms), period(10ms) for a specific thread
        # {0:1} {1:1} -g d:1000000/10000000/10000000:1234
                    '''.format(cmd, mode)

                # getaffinity #
                elif SysMgr.isGetAffinityMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -g <TID|COMM> [OPTIONS] [--help]

Description:
    Get CPU affinity of threads

Options:
    -g  <TID|COMM>              set values
    -P                          group threads in a same process
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Get CPU affinity of specific threads
        # {0:1} {1:1} -g a.out, 1234
                    '''.format(cmd, mode)

                # setaffinity #
                elif SysMgr.isSetAffinityMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -g <TID|COMM:MASK> [OPTIONS] [--help]

Description:
    Set CPU affinity of threads

Options:
    -g  <TID|COMM:MASK>         set values
    -P                          group threads in a same process
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Set CPU affinity of a specific thread to use only CPU 1 and CPU 2
        # {0:1} {1:1} -g a.out:3
                    '''.format(cmd, mode)

                # cputest #
                elif SysMgr.isCpuTestMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} <LOAD:NRTASK> [OPTIONS] [--help]

Description:
    Create tasks using cpu

Options:
    -R  <TIME>                  set timer
    -Y  <POLICY:PRIO|TIME       set sched
         {{:TID|COMM:CONT}}>
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Create 10 processes using 5% of a core each other
        # {0:1} {1:1} 50:10

    - Create threads using 250% CPU totally
        # {0:1} {1:1} 250

    - Create threads using 250% CPU totally with RR 1 priority
        # {0:1} {1:1} 250 -Y r:1

    - Create threads using 250% CPU totally and run them only on CPU 1
        # {0:1} {1:1} 250 -z :1

    - Create threads using 250% CPU totally and terminate them after 3 seconds
        # {0:1} {1:1} 250 -R 3
                    '''.format(cmd, mode)

                # memtest #
                elif SysMgr.isMemTestMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} <SIZE:INTERVAL:COUNT> [OPTIONS] [--help]

Description:
    Allocate physical memory

Options:
    -R  <TIME>                  set timer
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Allocate physical memory 1G
        # {0:1} {1:1} 1G

    - Allocate physical memory 200MB using a new process every 3 seconds
        # {0:1} {1:1} 200M:3

    - Allocate physical memory 100MB twoice using 2 processes
        # {0:1} {1:1} 100M:0:2

    - Allocate physical memory 100MB twoice using 2 processes and terminate them after 3 seconds
        # {0:1} {1:1} 100M:0:2 -R 3
                    '''.format(cmd, mode)

                # iotest #
                elif SysMgr.isIoTestMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} -g <OP:PATH> [OPTIONS] [--help]

Description:
    Run storage I/O operations

Options:
    -g  <OP:PATH>               set path
    -R  <TIME>                  set timer
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Read contents of all files from the current mount position
        # {0:1} {1:1}

    - Read contents of all files from current directory recusively
        # {0:1} {1:1} -g .

    - Read contents of all device nodes mounted
        # {0:1} {1:1} -a

    - Write contents to a specific file
        # {0:1} {1:1} -g write:TEST
                    '''.format(cmd, mode)

                # nettest #
                elif SysMgr.isNetTestMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Run network I/O operations

Options:
    -x  <IP:PORT>               set local address
    -I  <PRO{{:IP:PORT}}>         set job
    -R  <TIME>                  set timer
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Send UDP packets
        # {0:1} {1:1}

    - Send UDP packets with 3 processes
        # {0:1} {1:1} -I udp, udp, udp
                    '''.format(cmd, mode)

                # list #
                elif SysMgr.isListMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Show running {2:1} processes

Options:
    -v                          verbose
                        '''.format(cmd, mode, __module__)

                # start #
                elif SysMgr.isStartMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Send signal to all running Guider processes to run

Options:
    -v                          verbose
                        '''.format(cmd, mode)

                # event #
                elif SysMgr.isEventMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [<EVENT>] [OPTIONS] [--help]

Description:
    Send the event signal to all running Guider processes

Options:
    -v                          verbose
                        '''.format(cmd, mode)

                    helpStr +=  '''
Examples:
    - Send scene1 event to running Guider processes
        # {0:1} {1:1} scene1
                    '''.format(cmd, mode)

                # server #
                elif SysMgr.isServerMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Run server process

Options:
    -x  <IP:PORT>               set local address
    -u                          run in the background
    -C  <PATH>                  set configuration path
    -E  <DIR>                   set cache dir path
    -v                          verbose
                        '''.format(cmd, mode)

                # client #
                elif SysMgr.isClientMode():
                    helpStr = '''
Usage:
    # {0:1} {1:1} [OPTIONS] [--help]

Description:
    Run client process

Options:
    -x  <IP:PORT>               set local address
    -X  <IP:PORT>               set request address
    -E  <DIR>                   set cache dir path
    -v                          verbose
                        '''.format(cmd, mode)

                # default #
                elif mode.startswith('-') or \
                    mode == 'help':
                    helpStr = defStr + \
                        '''
COMMAND:
{0:1}
FILE:
    Profile file (e.g. guider.dat)
    Report  file (e.g. guider.out)

Options:
    Check COMMAND with --help (e.g. {1:1} top --help)
                    '''.format(SysMgr.getCmdString(), cmd)

                # wrong command #
                else:
                    SysMgr.printErr(\
                        'wrong command %s' % mode)
                    sys.exit(0)

                # print small logo #
                SysMgr.printLogo()

                printPipe(helpStr)

            else:
                helpStr = defStr + \
                    '''
Author:
    {0:1} ({1:1})

Bugs:
    {1:1} | {2:1}/issues

Copyright:
    {3:1}
    License {4:1}.
    This is free software
                    '''.format(__author__, __email__, \
                        __repository__, __copyright__, __license__)

                printPipe(helpStr)

            sys.exit(0)



    @staticmethod
    def getKernelVersion():
        if SysMgr.kernelVersion:
            return SysMgr.kernelVersion

        try:
            kernel = os.uname()[2]
            kernelList = kernel.split('.')

            # get kernel major version #
            kernelVersion = '.'.join(kernelList[0:2])

            # get kernel minor version #
            if len(kernel) > 2:
                kernelVersion = \
                    '%s.%s' % (kernelVersion, kernelList[2].split('-')[0])

            # update system info #
            SysMgr.kernelVersion = kernelVersion

            return kernelVersion
        except SystemExit:
            sys.exit(0)
        except:
            return None



    @staticmethod
    def getArch():
        if SysMgr.arch:
            return SysMgr.arch

        try:
            arch = os.uname()[4]

            if arch.startswith('arm'):
                SysMgr.arch = 'arm'
            elif arch.startswith('aarch64'):
                SysMgr.arch = 'aarch64'
            elif arch.startswith('x86_64') or arch.startswith('ia64'):
                SysMgr.arch = 'x64'
            elif arch.startswith('i386') or arch.startswith('i686'):
                SysMgr.arch = 'x86'
            else:
                SysMgr.arch = arch
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.arch = 'arm'

        return SysMgr.arch



    @staticmethod
    def setArch(arch):
        if not arch or len(arch) == 0:
            return

        arch = SysMgr.clearList(arch)

        # set systemcall table #
        if arch == 'arm':
            ConfigMgr.sysList = ConfigMgr.SYSCALL_ARM
            ConfigMgr.wordSize = 4
        elif arch == 'aarch64':
            ConfigMgr.sysList = ConfigMgr.SYSCALL_AARCH64
            ConfigMgr.wordSize = 8
        elif arch == 'x86':
            ConfigMgr.sysList = ConfigMgr.SYSCALL_X86
            ConfigMgr.wordSize = 4
        elif arch == 'x64':
            ConfigMgr.sysList = ConfigMgr.SYSCALL_X64
            ConfigMgr.wordSize = 8
        else:
            support = ' / '.join(ConfigMgr.supportArch)
            SysMgr.printErr(\
                'Fail to set architecture to %s, only %s supported' % \
                (arch, support))
            sys.exit(0)

        SysMgr.arch = arch



    @staticmethod
    def syscall(syscall, *args):
        if not SysMgr.isLinux:
            return None

        try:
            if not SysMgr.loadLibcObj():
                raise Exception()

            if UtilMgr.isNumber(syscall):
                nrSyscall = long(syscall)
                nmSyscall = ConfigMgr.sysList[nrSyscall]
            elif UtilMgr.isString(syscall):
                val = syscall.lower()
                if val[0:4] == 'sys_':
                    nmSyscall = val
                else:
                    nmSyscall = 'sys_%s' % val

                nrSyscall = ConfigMgr.sysList.index(nmSyscall)
            else:
                raise Exception()

            try:
                nrParams = \
                    len(ConfigMgr.SYSCALL_PROTOTYPES[nmSyscall[4:]][1])
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "Fail to get the number of arguments for %s" % nmSyscall)
                raise Exception()

            # check arguments #
            if len(args) != nrParams:
                SysMgr.printErr((\
                    "Fail to get arguments for %s "
                    "because of wrong parameters") % nmSyscall)
                raise Exception()

            if nrParams == 0:
                ret = SysMgr.libcObj.syscall(nrSyscall)
            elif nrParams == 1:
                ret = SysMgr.libcObj.syscall(\
                    nrSyscall, args[0])
            elif nrParams == 2:
                ret = SysMgr.libcObj.syscall(\
                    nrSyscall, args[0], args[1])
            elif nrParams == 3:
                ret = SysMgr.libcObj.syscall(\
                    nrSyscall, args[0], args[1], args[2])
            elif nrParams == 4:
                ret = SysMgr.libcObj.syscall(\
                    nrSyscall, args[0], args[1], args[2], args[3])
            elif nrParams == 5:
                ret = SysMgr.libcObj.syscall(\
                    nrSyscall, args[0], args[1], args[2], args[3], \
                        args[4])
            elif nrParams == 6:
                ret = SysMgr.libcObj.syscall(\
                    nrSyscall, args[0], args[1], args[2], args[3], \
                        args[4], args[5])

            return ret
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printWarn(\
                'Fail to call %s syscall' % syscall, True, reason=True)



    @staticmethod
    def checkPerm(exit=True, verb=True):
        if not SysMgr.isRoot():
            if verb:
                SysMgr.printErr(\
                    "Fail to get root permission")
            if exit:
                sys.exit(0)
            return False
        else:
            return True



    @staticmethod
    def isRoot():
        if SysMgr.isLinux and os.geteuid() == 0:
            return True
        else:
            return False



    @staticmethod
    def openPerfEvent(econfig, cpu=-1, pid=-1):
        try:
            perfEventList = ConfigMgr.PERF_EVENT_TYPE
            if econfig in ConfigMgr.PERF_HW_EVENT_TYPE:
                nrType = perfEventList.index('PERF_TYPE_HARDWARE')
                nrConfig = ConfigMgr.PERF_HW_EVENT_TYPE.index(econfig)
            elif econfig in ConfigMgr.PERF_SW_EVENT_TYPE:
                nrType = perfEventList.index('PERF_TYPE_SOFTWARE')
                nrConfig = ConfigMgr.PERF_SW_EVENT_TYPE.index(econfig)
            else:
                raise Exception()
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                'Fail to recognize %s as perf event type' % econfig)
            return

        if SysMgr.guiderObj:
            # reference to http://man7.org/linux/man-pages/man2/perf_event_open.2.html #
            func = SysMgr.guiderObj.perf_event_open # pylint: disable=no-member
            fd = func(nrType, nrConfig, pid, cpu, -1, 0)
            if fd < 0:
                # check root permission #
                if not SysMgr.isRoot():
                    SysMgr.printWarn(\
                        'Fail to get root permission to open perf event')
                    return
                else:
                    return -1
            else:
                return fd

        # import ctypes #
        if not SysMgr.importPkgItems('ctypes', False):
            SysMgr.perfEnable = False
            SysMgr.perfGroupEnable = False
            return

        if not SysMgr.loadLibcObj():
            SysMgr.perfEnable = False
            SysMgr.perfGroupEnable = False
            return

        # define struct perf_event_attr #
        class union_anon_5(Union):
            pass
        union_anon_5.__slots__ = [
            'sample_period',
            'sample_freq',
        ]
        union_anon_5._fields_ = [
            ('sample_period', c_uint64),
            ('sample_freq', c_uint64),
        ]

        class union_anon_6(Union):
            pass
        union_anon_6.__slots__ = [
            'wakeup_events',
            'wakeup_watermark',
        ]
        union_anon_6._fields_ = [
            ('wakeup_events', c_uint32),
            ('wakeup_watermark', c_uint32),
        ]

        class union_anon_7(Union):
            pass
        union_anon_7.__slots__ = [
            'bp_addr',
            'config1',
        ]
        union_anon_7._fields_ = [
            ('bp_addr', c_uint64),
            ('config1', c_uint64),
        ]

        class union_anon_8(Union):
            pass
        union_anon_8.__slots__ = [
            'bp_len',
            'config2',
        ]
        union_anon_8._fields_ = [
            ('bp_len', c_uint64),
            ('config2', c_uint64),
        ]

        class struct_perf_event_attr(Structure):
            pass
        '''
        struct perf_event_attr
        {

            uint32_t type;

            uint32_t size;

            uint64_t config;

            union
            {
                uint64_t sample_period;
                uint64_t sample_freq;
            };

            uint64_t sample_type;

            uint64_t read_format;

            uint64_t disabled:1,                /* off by default        */
                     inherit:1,                 /* children inherit it   */
                     pinned:1,                  /* must always be on PMU */
                     exclusive:1,               /* only group on PMU     */
                     exclude_user:1,            /* don't count user      */
                     exclude_kernel:1,          /* ditto kernel          */
                     exclude_hv:1,              /* ditto hypervisor      */
                     exclude_idle:1,            /* don't count when idle */
                     mmap:1,                    /* include mmap data     */
                     comm:1,                    /* include comm data     */
                     freq:1,                    /* use freq, not period  */
                     inherit_stat:1,            /* per task counts       */
                     enable_on_exec:1,          /* next exec enables     */
                     task:1,                    /* trace fork/exit       */
                     watermark:1,               /* wakeup_watermark      */
                     /*
                      * precise_ip:
                      *
                      *  0 - SAMPLE_IP can have arbitrary skid
                      *  1 - SAMPLE_IP must have constant skid
                      *  2 - SAMPLE_IP requested to have 0 skid
                      *  3 - SAMPLE_IP must have 0 skid
                      *
                      *  See also PERF_RECORD_MISC_EXACT_IP
                      */
                     precise_ip:2,              /* skid constraint       */
                     mmap_data:1,               /* non-exec mmap data    */
                     sample_id_all:1,           /* sample_type all events */
                     exclude_host:1,            /* don't count in host   */
                     exclude_guest:1,           /* don't count in guest  */
                     exclude_callchain_kernel:1,        /* exclude kernel callchains */
                     exclude_callchain_user:1,  /* exclude user callchains */
                     mmap2:1,                   /* include mmap with inode data     */
                     comm_exec:1,               /* flag comm events that are due to an exec */
                     use_clockid:1,             /* use @clockid for time fields */
                     context_switch:1,          /* context switch data */
                     write_backward:1,          /* Write ring buffer from end to beginning */
                     namespaces:1,              /* include namespaces data */
                     __reserved_1:35;

            union
            {
                uint32_t wakeup_events; /* wakeup every n events */
                uint32_t wakeup_watermark;      /* bytes before wakeup   */
            };

            uint32_t bp_type;

            union
            {
                uint64_t bp_addr;
                uint64_t config1;               /* extension of config */
            };

            union
            {
                uint64_t bp_len;
                uint64_t config2;               /* extension of config1 */
            };

            uint64_t branch_sample_type;        /* enum perf_branch_sample_type */

            uint64_t sample_regs_user;

            uint32_t sample_stack_user;

            int32_t clockid;

            uint64_t sample_regs_intr;

            uint32_t aux_watermark;

            uint16_t sample_max_stack;

            uint16_t __reserved_2;              /* align to uint64_t */
        };
        '''
        struct_perf_event_attr.__slots__ = [
            'type',
            'size',
            'config',
            'unnamed_1',
            'sample_type',
            'read_format',
            'disabled',
            'inherit',
            'pinned',
            'exclusive',
            'exclude_user',
            'exclude_kernel',
            'exclude_hv',
            'exclude_idle',
            'mmap',
            'comm',
            'freq',
            'inherit_stat',
            'enable_on_exec',
            'task',
            'watermark',
            'precise_ip',
            'mmap_data',
            'sample_id_all',
            'exclude_host',
            'exclude_guest',
            'exclude_callchain_kernel',
            'exclude_callchain_user',
            'mmap2',
            'comm_exec',
            'use_clockid',
            'context_switch',
            'write_backward',
            'namespaces',
            '__reserved_1',
            'unnamed_2',
            'bp_type',
            'unnamed_3',
            'unnamed_4',
            'branch_sample_type',
            'sample_regs_user',
            'sample_stack_user',
            'clockid',
            'sample_regs_intr',
            'aux_watermark',
            'sample_max_stack',
            '__reserved_2',
        ]
        struct_perf_event_attr._anonymous_ = [
            'unnamed_1',
            'unnamed_2',
            'unnamed_3',
            'unnamed_4',
        ]
        struct_perf_event_attr._fields_ = [
            ('type', c_uint32),
            ('size', c_uint32),
            ('config', c_uint64),
            ('unnamed_1', union_anon_5),
            ('sample_type', c_uint64),
            ('read_format', c_uint64),
            ('disabled', c_uint64, 1),
            ('inherit', c_uint64, 1),
            ('pinned', c_uint64, 1),
            ('exclusive', c_uint64, 1),
            ('exclude_user', c_uint64, 1),
            ('exclude_kernel', c_uint64, 1),
            ('exclude_hv', c_uint64, 1),
            ('exclude_idle', c_uint64, 1),
            ('mmap', c_uint64, 1),
            ('comm', c_uint64, 1),
            ('freq', c_uint64, 1),
            ('inherit_stat', c_uint64, 1),
            ('enable_on_exec', c_uint64, 1),
            ('task', c_uint64, 1),
            ('watermark', c_uint64, 1),
            ('precise_ip', c_uint64, 2),
            ('mmap_data', c_uint64, 1),
            ('sample_id_all', c_uint64, 1),
            ('exclude_host', c_uint64, 1),
            ('exclude_guest', c_uint64, 1),
            ('exclude_callchain_kernel', c_uint64, 1),
            ('exclude_callchain_user', c_uint64, 1),
            ('mmap2', c_uint64, 1),
            ('comm_exec', c_uint64, 1),
            ('use_clockid', c_uint64, 1),
            ('context_switch', c_uint64, 1),
            ('write_backward', c_uint64, 1),
            ('namespaces', c_uint64, 1),
            ('__reserved_1', c_uint64, 35),
            ('unnamed_2', union_anon_6),
            ('bp_type', c_uint32),
            ('unnamed_3', union_anon_7),
            ('unnamed_4', union_anon_8),
            ('branch_sample_type', c_uint64),
            ('sample_regs_user', c_uint64),
            ('sample_stack_user', c_uint32),
            ('clockid', c_int32),
            ('sample_regs_intr', c_uint64),
            ('aux_watermark', c_uint32),
            ('sample_max_stack', c_uint16),
            ('__reserved_2', c_uint16),
        ]

        # define constants for ioctl #
        _IOC_NRBITS = 8
        _IOC_TYPEBITS = 8
        _IOC_SIZEBITS = 14 # architecture specific
        _IOC_DIRBITS = 2
        _IOC_NRMASK = (1 << _IOC_NRBITS) - 1
        _IOC_TYPEMASK = (1 << _IOC_TYPEBITS) - 1
        _IOC_SIZEMASK = (1 << _IOC_SIZEBITS) - 1
        _IOC_DIRMASK = (1 << _IOC_DIRBITS) - 1
        _IOC_NRSHIFT = long(0)
        _IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS
        _IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS
        _IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS
        _IOC_NONE = long(0)
        _IOC_WRITE = 1
        _IOC_READ = 2

        def _IOC(dir, type, nr, size):
            return  dir  << _IOC_DIRSHIFT  | \
                    ord(type) << _IOC_TYPESHIFT | \
                    nr   << _IOC_NRSHIFT   | \
                    size << _IOC_SIZESHIFT

        def _IO(type, nr): return _IOC(_IOC_NONE, type, nr, 0)
        def _IOR(type, nr, size): return _IOC(_IOC_READ, type, nr, size)
        def _IOW(type, nr, size): return _IOC(_IOC_WRITE, type, nr, size)
        def _IOWR(type, nr, size): return _IOC(_IOC_READ | _IOC_WRITE, type, nr, size)

        # define CMD #
        PERF_EVENT_IOC_ENABLE = _IO('$', 0)
        PERF_EVENT_IOC_DISABLE = _IO('$', 1)
        PERF_EVENT_IOC_REFRESH = _IO('$', 2)
        PERF_EVENT_IOC_RESET = _IO('$', 3)
        PERF_EVENT_IOC_PERIOD = _IOW('$', 4, sizeof(c_uint64))
        PERF_EVENT_IOC_SET_OUTPUT = _IO('$', 5)
        PERF_EVENT_IOC_SET_FILTER = _IOW('$', 6, sizeof(c_uint))
        PERF_EVENT_IOC_ID = _IOR('$', 7, sizeof(c_uint64))
        PERF_EVENT_IOC_SET_BPF = _IOW('$', 8, sizeof(c_uint32))
        PERF_EVENT_IOC_PAUSE_OUTPUT = _IOW('$', 9, sizeof(c_uint32))

        # declare syscalls #
        SysMgr.libcObj.syscall.argtypes = \
            [c_int, POINTER(struct_perf_event_attr), \
                c_int, c_int, c_int, c_ulong]
        SysMgr.libcObj.syscall.restype = c_int
        SysMgr.libcObj.ioctl.restype = c_int
        SysMgr.libcObj.ioctl.argtypes = [c_int, c_ulong, c_int]

        # set struct perf_event_attr #
        perf_attr = struct_perf_event_attr()
        perf_attr.type = nrType
        perf_attr.config = nrConfig
        perf_attr.size = sizeof(perf_attr)
        perf_attr.disabled = 1
        #perf_attr.exclude_user = 1
        #perf_attr.exclude_kernel = 1
        #perf_attr.exclude_hv = 1
        #perf_attr.exclude_idle = 1

        # call a perf_event_open syscall #
        '''
        int perf_event_open(struct perf_event_attr *attr,
            pid_t pid, int cpu, int group_fd, unsigned long flags);
        '''
        # reference to http://man7.org/linux/man-pages/man2/perf_event_open.2.html #
        fd = SysMgr.libcObj.syscall(\
            ConfigMgr.sysList.index('sys_perf_event_open'), \
            pointer(perf_attr), pid, cpu, -1, 0)

        if fd < 0:
            # check root permission #
            if not SysMgr.isRoot():
                SysMgr.printWarn(\
                    'Fail to get root permission to open perf event')
                return
            else:
                return -1

        # control perf event #
        SysMgr.libcObj.ioctl(fd, PERF_EVENT_IOC_RESET, 0)
        SysMgr.libcObj.ioctl(fd, PERF_EVENT_IOC_ENABLE, 0)

        # free perf_attr object, but memory leak exists now #
        del perf_attr

        return fd



    @staticmethod
    def readPerfEvents(fdList):
        if SysMgr.guiderObj:
            retList = []

            for fd in fdList:
                try:
                    # read PMU data #
                    value = SysMgr.guiderObj.perf_event_read(fd) # pylint: disable=no-member

                    # add value to list #
                    retList.append(value)
                except SystemExit:
                    sys.exit(0)
                except:
                    retList.append(None)

            return retList

        # get ctypes object #
        if not SysMgr.importPkgItems('ctypes', False):
            return

        if not SysMgr.loadLibcObj():
            return

        # define struct read_group_format #
        class struct_anon_5(Structure):
            __slots__ = [
                'value',
                'id',
            ]

            _fields_ = [
                ('value', c_uint64),
                ('id', c_uint64),
            ]

        '''
        struct read_group_format {
            uint64_t nr;            /* The number of events */
            uint64_t time_enabled;  /* if PERF_FORMAT_TOTAL_TIME_ENABLED */
            uint64_t time_running;  /* if PERF_FORMAT_TOTAL_TIME_RUNNING */
            struct {
                uint64_t value;     /* The value of the event */
                uint64_t id;        /* if PERF_FORMAT_ID */
            } values[];
        };
        '''
        '''
        class struct_read_group_format(Structure):
            __slots__ = [
                'nr',
                #'time_enabled',
                #'time_running',
                'values',
            ]

            _fields_ = [
                ('nr', c_uint64),
                #('time_enabled', c_uint64),
                #('time_running', c_uint64),
                ('values', POINTER(struct_anon_5)),
            ]
        '''

        # define struct read_format #
        '''
        struct read_format {
            uint64_t value;         /* The value of the event */
            uint64_t time_enabled;  /* if PERF_FORMAT_TOTAL_TIME_ENABLED */
            uint64_t time_running;  /* if PERF_FORMAT_TOTAL_TIME_RUNNING */
            uint64_t id;            /* if PERF_FORMAT_ID */
        };
        '''
        class struct_read_format(Structure):
            __slots__ = [
                'value',
                #'time_enabled',
                #'time_running',
                'id',
            ]

            _fields_ = [
                ('value', c_uint64),
                #('time_enabled', c_uint64),
                #('time_running', c_uint64),
                ('id', c_uint64),
            ]

        # define IOC for ioctl call #
        _IOC_NRBITS = 8
        _IOC_TYPEBITS = 8
        _IOC_SIZEBITS = 14 # architecture specific
        _IOC_DIRBITS = 2
        _IOC_NRMASK = (1 << _IOC_NRBITS) - 1
        _IOC_TYPEMASK = (1 << _IOC_TYPEBITS) - 1
        _IOC_SIZEMASK = (1 << _IOC_SIZEBITS) - 1
        _IOC_DIRMASK = (1 << _IOC_DIRBITS) - 1
        _IOC_NRSHIFT = long(0)
        _IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS
        _IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS
        _IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS
        _IOC_NONE = long(0)
        _IOC_WRITE = 1
        _IOC_READ = 2

        def _IOC(dir, type, nr, size):
            return  dir  << _IOC_DIRSHIFT  | \
                    ord(type) << _IOC_TYPESHIFT | \
                    nr   << _IOC_NRSHIFT   | \
                    size << _IOC_SIZESHIFT

        def _IO(type, nr):
            return _IOC(_IOC_NONE, type, nr, 0)
        def _IOR(type, nr, size):
            return _IOC(_IOC_READ, type, nr, size)
        def _IOW(type, nr, size):
            return _IOC(_IOC_WRITE, type, nr, size)
        def _IOWR(type, nr, size):
            return _IOC(_IOC_READ | _IOC_WRITE, type, nr, size)

        # define CMD #
        PERF_EVENT_IOC_ENABLE = _IO ('$', 0)
        PERF_EVENT_IOC_DISABLE = _IO ('$', 1)
        PERF_EVENT_IOC_REFRESH = _IO ('$', 2)
        PERF_EVENT_IOC_RESET = _IO ('$', 3)
        PERF_EVENT_IOC_PERIOD = _IOW('$', 4, sizeof(c_uint64))
        PERF_EVENT_IOC_SET_OUTPUT = _IO ('$', 5)
        PERF_EVENT_IOC_SET_FILTER = _IOW('$', 6, sizeof(c_uint))
        PERF_EVENT_IOC_ID = _IOR('$', 7, sizeof(c_uint64))
        PERF_EVENT_IOC_SET_BPF = _IOW('$', 8, sizeof(c_uint32))
        PERF_EVENT_IOC_PAUSE_OUTPUT = _IOW('$', 9, sizeof(c_uint32))

        # declare syscalls #
        SysMgr.libcObj.ioctl.restype = c_int
        SysMgr.libcObj.ioctl.argtypes = [c_int, c_ulong]
        SysMgr.libcObj.read.argtypes = [c_int, POINTER(None), c_uint]
        SysMgr.libcObj.read.restype = c_int

        # declare buffer and retList #
        pbuf = (8 * c_ubyte)()
        retList = []

        for fd in fdList:
            try:
                # read PMU data #
                SysMgr.libcObj.read(fd, pointer(pbuf), sizeof(pbuf))

                # control perf event #
                SysMgr.libcObj.ioctl(fd, PERF_EVENT_IOC_RESET, 0)

                # cast buffer to data #
                retList.append(\
                    cast(pbuf, POINTER(c_ulong)).contents.value)
            except SystemExit:
                sys.exit(0)
            except:
                retList.append(None)

        return retList



    @staticmethod
    def initSystemPerfEvents():
        # check perf option #
        if not SysMgr.perfEnable:
            return

        # check root permission #
        if not SysMgr.isRoot():
            SysMgr.perfEnable = False
            return
        # check configuration #
        else:
            try:
                PMUs = '/sys/bus/event_source/devices'
                attrPath = '%s/sys/kernel/perf_event_paranoid' % \
                    SysMgr.procPath
                with open(attrPath, 'w+') as fd:
                    '''
                    -1 - not paranoid at all
                     0 - disallow raw tracepoint access for unpriv
                     1 - disallow CPU events for unpriv
                     2 - disallow kernel profiling for unpriv
                     3 - disallow user profiling for unpriv
                    '''
                    paranoid = long(fd.readline()[:-1])
                    if paranoid > -1:
                        fd.seek(0)
                        # write all privilege to read perf events #
                        fd.write('-1')
                        SysMgr.printWarn((\
                            'Change value of %s from %s to -1 '
                            'to read all perf events') % \
                            (attrPath, paranoid))
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printWarn(\
                    "enable CONFIG_PERF_EVENTS kernel option")
                return

        hwTargetList = [
            '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',
            ]

        swTargetList = [
            'PERF_COUNT_SW_CPU_CLOCK',
            'PERF_COUNT_SW_PAGE_FAULTS_MIN',
            'PERF_COUNT_SW_PAGE_FAULTS_MAJ',
            ]

        successCnt = long(0)
        cpuPath = '/sys/devices/system/cpu'
        cpuList = \
            [ coreId.strip('cpu') for coreId in os.listdir(cpuPath) \
            if coreId.startswith('cpu') ]

        for item in cpuList:
            try:
                coreId = long(item)
            except:
                continue

            SysMgr.perfEventChannel[coreId] = {}

            # HW Events #
            for evt in hwTargetList:
                # initialize hw event channels #
                SysMgr.perfEventChannel[coreId][evt] = \
                    SysMgr.openPerfEvent(evt, coreId)

                # handle unavailable hw events #
                if SysMgr.perfEventChannel[coreId][evt] == -1:
                    del SysMgr.perfEventChannel[coreId][evt]
                elif not SysMgr.perfEventChannel[coreId][evt]:
                    return
                else:
                    successCnt += 1

            # SW Events #
            for evt in swTargetList:
                # initialize sw event channels #
                SysMgr.perfEventChannel[coreId][evt] = \
                    SysMgr.openPerfEvent(evt, coreId)

                # handle unavailable sw events #
                if SysMgr.perfEventChannel[coreId][evt] == -1:
                    del SysMgr.perfEventChannel[coreId][evt]
                elif not SysMgr.perfEventChannel[coreId][evt]:
                    return
                else:
                    successCnt += 1

            if len(SysMgr.perfTargetEvent) == 0 and \
                len(SysMgr.perfEventChannel[coreId]) > 0:
                SysMgr.perfTargetEvent = \
                    list(SysMgr.perfEventChannel[coreId].keys())

        if successCnt == 0:
            SysMgr.printWarn('Fail to find available perf event')
            SysMgr.perfEnable = False
            SysMgr.perfGroupEnable = False



    @staticmethod
    def initProcPerfEvents(pid):
        eventChannel = {}

        for evt in SysMgr.perfTargetEvent:
            eventChannel[evt] = \
                SysMgr.openPerfEvent(evt, -1, pid)

        return eventChannel



    @staticmethod
    def collectSystemPerfData():
        SysMgr.perfEventData = {}

        # check perf event option #
        if SysMgr.perfGroupEnable and \
            len(SysMgr.perfEventChannel) == 0:
            return

        # check perf event channel #
        for coreId in list(SysMgr.perfEventChannel.keys()):
            # make event list #
            events = list(SysMgr.perfEventChannel[coreId].keys())

            # remove all core events if specific target process exist #
            if SysMgr.perfGroupEnable:
                for fd in SysMgr.perfEventChannel[coreId].values():
                    os.close(fd)
                del SysMgr.perfEventChannel[coreId]
                continue

            # get event data #
            values = SysMgr.readPerfEvents(\
                SysMgr.perfEventChannel[coreId].values())

            if not values:
                continue

            # summarize perf data of each cores #
            for idx, evt in enumerate(events):
                try:
                    SysMgr.perfEventData[evt] += values[idx]
                except:
                    SysMgr.perfEventData[evt] = values[idx]



    @staticmethod
    def collectProcPerfData(fdList):
        perfData = {}

        # make event list #
        events = list(fdList.keys())

        # get event data #
        values = SysMgr.readPerfEvents(fdList.values())

        # summarize perf data of each cores #
        for idx, evt in enumerate(events):
            perfData[evt] = values[idx]

        return perfData



    @staticmethod
    def getPerfString(value):
        perfbuf = ''

        if len(value) == 0:
            return perfbuf

        inst = buscycle = refcpucycle = cpucycle = -1
        cacheref = cachemiss = cachemissrate = -1
        branch = branchmiss = branchmissrate = -1

        # IPC stats #
        try:
            cpucycle = value['PERF_COUNT_HW_CPU_CYCLES']
            perfbuf = '%sCycle: %s / ' % \
                (perfbuf, UtilMgr.convSize2Unit(cpucycle))
            inst = value['PERF_COUNT_HW_INSTRUCTIONS']
            perfbuf = '%sInst: %s / ' % \
                (perfbuf, UtilMgr.convSize2Unit(inst))
            ipc = inst / float(cpucycle)
            perfbuf = '%sIPC: %.2f / ' % (perfbuf, ipc)
        except SystemExit:
            sys.exit(0)
        except:
            pass

        # CACHE stats #
        try:
            cacheref = value['PERF_COUNT_HW_CACHE_REFERENCES']
            cachemiss = value['PERF_COUNT_HW_CACHE_MISSES']
            cachemissrate = cachemiss / float(cacheref) * 100
            perfbuf = '%sCacheMiss : %s(%d%%) / ' % \
                (perfbuf, UtilMgr.convSize2Unit(cachemiss),\
                cachemissrate)
        except SystemExit:
            sys.exit(0)
        except:
            pass

        # BRANCH stats #
        try:
            branch = value['PERF_COUNT_HW_BRANCH_INSTRUCTIONS']
            branchmiss = value['PERF_COUNT_HW_BRANCH_MISSES']
            branchmissrate = branchmiss / float(branch) * 100
            perfbuf = '%sBrcMiss: %s(%d%%) / ' % \
                (perfbuf, UtilMgr.convSize2Unit(branchmiss),\
                branchmissrate)
        except SystemExit:
            sys.exit(0)
        except:
            pass

        # CPU stats #
        try:
            perfbuf = '%sClk: %s / ' % \
                (perfbuf, UtilMgr.convSize2Unit(\
                    value['PERF_COUNT_SW_CPU_CLOCK']))
        except SystemExit:
            sys.exit(0)
        except:
            pass

        # FAULT stats #
        try:
            faultmin = value['PERF_COUNT_SW_PAGE_FAULTS_MIN']
            faultmaj = value['PERF_COUNT_SW_PAGE_FAULTS_MAJ']
            perfbuf = '%sMinFlt: %s / MajFlt: %s / ' % \
                (perfbuf, format(faultmin, ','), format(faultmaj, ','))
        except SystemExit:
            sys.exit(0)
        except:
            pass

        try:
            if len(perfbuf) > 0:
                perfbuf = '[%s]' % perfbuf[:perfbuf.rfind(' /')]
        except SystemExit:
            sys.exit(0)
        except:
            pass

        return perfbuf



    @staticmethod
    def writeKernelCmd():
        effectiveCmd = []

        if not SysMgr.keventEnable:
            return
        elif len(SysMgr.kernelCmd) == 0:
            SysMgr.printErr(\
                "wrong format used with -K option, NAME:FUNC|ADDR{:ARGS:RET}")
            sys.exit(0)
        elif not os.path.isfile(\
            SysMgr.mountPath + '../kprobe_events'):
            SysMgr.printErr(\
                "enable CONFIG_KPROBES & CONFIG_KPROBE_EVENTS kernel option")
            sys.exit(0)

        for cmd in SysMgr.kernelCmd:
            cmdFormat = cmd.split(':')

            # check command format #
            cmdCnt = len(cmdFormat)
            if not (2 <= cmdCnt <= 4):
                SysMgr.printErr(\
                    "wrong format used with -K option, NAME:FUNC|ADDR{:ARGS:RET}")
                sys.exit(0)

            for item in effectiveCmd:
                if cmdFormat[0] == item[0]:
                    SysMgr.printErr(\
                        "redundant kernel event name '%s'" % item[0])
                    sys.exit(0)

            effectiveCmd.append(cmdFormat)

        # print kprobe event list #
        SysMgr.printInfo("enabled kernel events [ %s ]" % \
            ', '.join([ ':'.join(cmd) for cmd in effectiveCmd ]))

        # clear kprobe event filter #
        SysMgr.writeCmd("../kprobe_events", '')

        # apply kprobe events #
        for cmd in effectiveCmd:
            # check redundant event name #
            if SysMgr.userCmd and \
                cmd[0] in [ucmd.split(':')[0] for ucmd in SysMgr.userCmd]:
                SysMgr.printErr(\
                    "redundant event name '%s' as user event and kernel event" % \
                    cmd[0])
                sys.exit(0)

            # make entry commands #
            pCmd = 'p:%s_enter %s' % (cmd[0], cmd[1])
            sCmd = ''
            try:
                # parse argument option #
                for rCmd in cmd[2].split('.'):
                    # convert ; to : for type definition #
                    rCmd = rCmd.replace(';', ':')

                    # check absolute argument #
                    if len(rCmd) == 0:
                        pass
                    elif rCmd[0] == '#':
                        sCmd = '%s %s' % (sCmd, rCmd[1:])
                        continue
                    elif len(rCmd.split('/')) == 1:
                        sCmd = '%s %s' % (sCmd, rCmd)
                        continue

                    rVal = rCmd.split('/')
                    if len(rVal) < 2:
                        continue
                    elif len(rVal) > 2:
                        SysMgr.printErr(\
                            "wrong command '%s' with -K option" % rCmd)
                        sys.exit(0)
                    tVal = rVal[1]

                    # count the number of prefix * #
                    wCnt = long(0)
                    for idx, ch in enumerate(tVal):
                        if ch != '*':
                            wCnt = idx
                            break

                    # make entry command #
                    tVal = '%s%s%s:%s' % \
                        ('+0(' * wCnt, rVal[0], ')' * wCnt, tVal[wCnt:])

                    # add argument command to entry command #
                    sCmd = '%s %s' % (sCmd, tVal)
            except SystemExit:
                sys.exit(0)
            except:
                pass

            # apply entry command #
            if sCmd != ' NONE':
                pCmd = '%s %s' % (pCmd, sCmd)
                if SysMgr.writeCmd(\
                        '../kprobe_events', pCmd, append=True) < 0:
                    SysMgr.printErr(\
                        "wrong command '%s' with -K option" % pCmd)
                    sys.exit(0)

            # make return commands #
            rCmd = 'r:%s_exit %s' % (cmd[0], cmd[1])
            sCmd = ''

            try:
                tCmd = cmd[3]

                # check absolute argument #
                if tCmd[0] == '#':
                    sCmd = '%s' % (tCmd[1:])
                else:
                    rVal = tCmd.split('/')
                    if len(rVal) > 2:
                        SysMgr.printErr(\
                            "wrong command '%s' with -K option" % tCmd)
                        sys.exit(0)
                    tVal = rVal[0]

                    # count the number of prefix * #
                    wCnt = long(0)
                    for idx, ch in enumerate(tVal):
                        if ch != '*':
                            wCnt = idx
                            break

                    if tCmd != 'NONE':
                        # make return command #
                        sCmd = '%s%s%s:%s' % \
                            ('+0(' * wCnt, '$retval', ')' * wCnt, tVal[wCnt:])
                    else:
                        sCmd = 'NONE'
            except SystemExit:
                sys.exit(0)
            except:
                pass

            # apply return command #
            if sCmd != 'NONE':
                rCmd = '%s %s' % (rCmd, sCmd)
                if SysMgr.writeCmd(\
                    '../kprobe_events', rCmd, append=True) < 0:
                    SysMgr.printErr(\
                        "wrong command '%s' with -K option" % rCmd)
                    sys.exit(0)

        # apply filter #
        if SysMgr.filterGroup != []:
            cmd = SysMgr.getPidFilter()
            if cmd != '':
                SysMgr.writeCmd("kprobes/filter", cmd)
            else:
                SysMgr.printErr("Fail to apply kprobe filter")
                sys.exit(0)

        # enable kprobe events #
        if SysMgr.writeCmd("kprobes/enable", '1') < 0:
            SysMgr.printErr("Fail to apply kprobe events")
            sys.exit(0)



    @staticmethod
    def writeUserCmd():
        effectiveCmd = []

        if not SysMgr.ueventEnable:
            return
        elif len(SysMgr.userCmd) == 0:
            SysMgr.printErr(\
                "wrong format used with -U option, NAME:FUNC|ADDR:FILE")
            sys.exit(0)
        elif not os.path.isfile(\
            SysMgr.mountPath + '../uprobe_events'):
            SysMgr.printErr(\
                "enable CONFIG_UPROBES & CONFIG_UPROBE_EVENT kernel option")
            sys.exit(0)

        kernelCmd = SysMgr.kernelCmd

        for cmd in SysMgr.userCmd:
            addr = None
            cvtCmd = cmd.replace("::", "#")
            cmdFormat = cvtCmd.split(':')
            cmdFormat = [ cmd.replace("#", "::") for cmd in cmdFormat ]

            if len(cmdFormat) != 3:
                SysMgr.printErr(\
                    "wrong format used with -U option, NAME:FUNC|ADDR:FILE")
                sys.exit(0)

            # check redundant event name #
            if kernelCmd and \
                cmd[0] in [kcmd.split(':')[0] for kcmd in kernelCmd]:
                SysMgr.printErr((\
                    "redundant event name '%s' "
                    "as user event and kernel event") % cmd[0])
                sys.exit(0)

            # check binary file #
            if not os.path.isfile(cmdFormat[2]):
                SysMgr.printErr(\
                    "Fail to find '%s' binary" % cmdFormat[2])
                sys.exit(0)

            # symbol input #
            if not cmdFormat[1].startswith('0x'):
                # symbol input with no objdump path #
                if not SysMgr.objdumpPath:
                    # get address of symbol in binary #
                    addr = ElfAnalyzer.getSymOffset(\
                        cmdFormat[1], cmdFormat[2])

                    # use external objdump #
                    if not addr:
                        # get system objdump path #
                        objdumpPath = UtilMgr.which('objdump')

                        if not objdumpPath:
                            SysMgr.printErr((\
                                "Fail to find objdump "
                                "to get address of user-level function, "
                                "use -l option to set custom path"))
                            sys.exit(0)

                        SysMgr.objdumpPath = objdumpPath[0]

                        SysMgr.printInfo(\
                            "use %s as objdump path" % \
                            SysMgr.objdumpPath)
                # symbol input with objdump #
                elif not os.path.isfile(SysMgr.objdumpPath):
                    SysMgr.printErr(\
                        "Fail to find %s to use objdump" % \
                        SysMgr.objdumpPath)
                    sys.exit(0)

                # get address of symbol in binary #
                addr = ElfAnalyzer.getSymOffset(\
                    cmdFormat[1], cmdFormat[2], SysMgr.objdumpPath)
                if not addr:
                    SysMgr.printErr("Fail to find '%s' in %s" % \
                        (cmdFormat[1], cmdFormat[2]))
                    sys.exit(0)
            # address input #
            else:
                addr = cmdFormat[1]
                try:
                    hex(long(addr, base=16))
                except:
                    SysMgr.printErr(\
                        "Fail to recognize address %s" % addr)
                    sys.exit(0)

            for item in effectiveCmd:
                if cmdFormat[0] == item[0]:
                    SysMgr.printErr(\
                        "redundant user event name '%s'" % item[0])
                    sys.exit(0)

            if type(addr) is list:
                addr = str(addr[0][0])

            effectiveCmd.append([cmdFormat[0], addr, cmdFormat[2]])

        # print uprobe event list #
        SysMgr.printInfo("enabled user events [ %s ]" % \
            ', '.join([ ':'.join(cmd) for cmd in effectiveCmd ]))

        # clear uprobe event filter #
        SysMgr.writeCmd("../uprobe_events", '')

        # apply uprobe events #
        for cmd in effectiveCmd:
            # apply entry events #
            pCmd = 'p:%s_enter %s:%s' % (cmd[0], cmd[2], cmd[1])
            if SysMgr.writeCmd('../uprobe_events', pCmd, append=True) < 0:
                SysMgr.printErr(\
                    "wrong command '%s' with -U option" % pCmd)
                sys.exit(0)

            # apply return events #
            rCmd = 'r:%s_exit %s:%s' % (cmd[0], cmd[2], cmd[1])
            if SysMgr.writeCmd('../uprobe_events', rCmd, append=True) < 0:
                SysMgr.printErr(\
                    "wrong command '%s' with -U option" % rCmd)
                sys.exit(0)

        # apply filter #
        if SysMgr.filterGroup != []:
            cmd = SysMgr.getPidFilter()
            if cmd != '':
                SysMgr.writeCmd("uprobes/filter", cmd)
            else:
                SysMgr.printErr("Fail to apply uprobe filter")
                sys.exit(0)

        # enable uprobe events #
        if SysMgr.writeCmd("uprobes/enable", '1') < 0:
            SysMgr.printErr("Fail to apply uprobe events")
            sys.exit(0)



    @staticmethod
    def writeSyscallCmd(enable):
        scmd = ""
        defaultList = [
            'sys_execve',
            'sys_execveat',
            'sys_nice',
            'sys_setpriority',
            'sys_sched_setparam',
            'sys_sched_setscheduler',
            'sys_sched_setattr',
            'sys_bpf',
            'sys_ioprio_set',
            ]

        if SysMgr.isFunctionMode() and \
            not SysMgr.heapEnable:
            cmd = 'raw_syscalls/sys_enter/enable'
        else:
            cmd = 'raw_syscalls/enable'

        # specific syscalls #
        if enable:
            sfilter = ""
            pfilter = SysMgr.getPidFilter()
            if len(SysMgr.syscallList) > 0:
                sfilter = "("
                for val in SysMgr.syscallList:
                    sfilter += " id == %s ||" % val
                sfilter = "%s )" % sfilter[:sfilter.rfind(" ||")]

            if len(sfilter) > 0 and len(pfilter) > 0:
                scmd = "(%s && %s)" % (sfilter, pfilter)
            elif len(sfilter) > 0:
                scmd = sfilter
                for item in defaultList:
                    try:
                        scmd = "%s || ( id == %s )" % \
                            (scmd, ConfigMgr.sysList.index(item))
                    except:
                        continue
            elif len(pfilter) > 0:
                scmd = "(%s)" % pfilter
            else:
                pass
        # default syscalls #
        else:
            for item in defaultList:
                try:
                    scmd = "%s || ( id == %s )" % \
                        (scmd, ConfigMgr.sysList.index(item))
                except:
                    continue
            scmd = scmd[scmd.find("("):]

        SysMgr.writeCmd('raw_syscalls/filter', scmd)
        ret = SysMgr.writeCmd(cmd, '1')
        if ret < 0:
            SysMgr.printWarn("Fail to enable syscall events", True)



    @staticmethod
    def printSigError(tid, signal, warn=True):
        if warn:
            printFunc = SysMgr.printWarn
        else:
            printFunc = SysMgr.printErr

        printFunc(\
            "Fail to send %s to thread %s" % (signal, tid), reason=True)



    @staticmethod
    def getErrMsg():
        et, err, to = sys.exc_info()

        try:
            if len(err.args) == 0 or err.args[0] == 0:
                return '%s at %s' % \
                    (sys.exc_info()[0].__name__, to.tb_lineno)
        except:
            if to:
                return 'N/A at %s' % to.tb_lineno
            else:
                return 'N/A'

        try:
            code = '%s-' % errno.errorcode[err.args[0]]
        except:
            code = ''

        errstr = ' '.join(list(map(str, err.args)))
        return '%s%s at %s' % (code, errstr, to.tb_lineno)



    def disableAllEvents(self):
        for event in list(self.cmdList.keys()):
            self.cmdList[event] = False



    @staticmethod
    def writeCustomCmd():
        effectiveCmd = []

        if not SysMgr.customCmd:
            return

        if SysMgr.filterGroup == []:
            pidFilter = 'common_pid != 0'
        else:
            pidFilter = SysMgr.getPidFilter()

        for cmd in SysMgr.customCmd:
            cmdFormat = cmd.split(':')

            if cmdFormat[0] == '':
                SysMgr.printErr("wrong event '%s'" % cmdFormat[0])
                sys.exit(0)

            # check filter #
            if len(cmdFormat) == 1:
                origFilter = ''
                cmdFormat.append(pidFilter)
            else:
                origFilter = cmdFormat[1]
                cmdFormat[1] = pidFilter + " && " + cmdFormat[1]

            # check effective event #
            if SysMgr.writeCmd(cmdFormat[0] + '/enable', '0') < 0:
                SysMgr.printErr("wrong event '%s'" % cmdFormat[0])
                sys.exit(0)

            # check and enable effective filter #
            if len(cmdFormat) > 1 and \
                SysMgr.writeCmd(\
                cmdFormat[0] + '/filter', cmdFormat[1]) < 0:
                SysMgr.printErr("wrong filter '%s' for '%s' event" % \
                    (origFilter, cmdFormat[0]))
                sys.exit(0)

            # check and enable effective event #
            if SysMgr.writeCmd(cmdFormat[0] + '/enable', '1') < 0:
                SysMgr.printErr("wrong event '%s'" % cmdFormat[0])
                sys.exit(0)
            else:
                effectiveCmd.append(cmdFormat[0])

        if len(effectiveCmd) > 0:
            SysMgr.printInfo(\
                "enabled custom events [ %s ]" % ', '.join(effectiveCmd))



    @staticmethod
    def printAnalOption():
        enableStat = ''
        disableStat = ''

        if SysMgr.outputFile:
            return

        if not SysMgr.isRecordMode() and \
            not SysMgr.isTopMode():
            # common options #
            enableStat += SysMgr.arch.upper() + ' '
            if SysMgr.warnEnable:
                enableStat += 'WARN '

        # function mode #
        if SysMgr.isFunctionMode():
            if not SysMgr.heapEnable:
                disableStat += 'HEAP '
            else:
                enableStat += 'HEAP '

            if not SysMgr.userEnable:
                disableStat += 'USER '
            else:
                enableStat += 'USER '

            if SysMgr.customCmd:
                SysMgr.printInfo(\
                    "selected custom events [ %s ]" % \
                    ', '.join(SysMgr.customCmd))
        # thread mode #
        else:
            if SysMgr.intervalEnable > 0:
                enableStat += 'INTERVAL '
            else:
                disableStat += 'INTERVAL '

            if SysMgr.latEnable:
                enableStat += 'LATENCY '
            else:
                disableStat += 'LATENCY '

            if SysMgr.depEnable:
                enableStat += 'DEP '
            else:
                disableStat += 'DEP '

            if SysMgr.ueventEnable:
                enableStat += 'UEVT '
            else:
                disableStat += 'UEVT '

            if SysMgr.keventEnable:
                enableStat += 'KEVT '
            else:
                disableStat += 'KEVT '

            if SysMgr.irqEnable:
                enableStat += 'IRQ '
            else:
                disableStat += 'IRQ '

            if SysMgr.networkEnable:
                enableStat += 'NET '
            else:
                disableStat += 'NET '

            if SysMgr.powerEnable:
                enableStat += 'POWER '
            else:
                disableStat += 'POWER '

            if len(SysMgr.preemptGroup) > 0:
                enableStat += 'PREEMPT '
            else:
                disableStat += 'PREEMPT '

            if len(SysMgr.perCoreList) > 0:
                enableStat += 'PERCORE '
            else:
                disableStat += 'PERCORE '

            if SysMgr.customCmd:
                SysMgr.printInfo(\
                    "selected custom events [ %s ]" % \
                    ', '.join(SysMgr.customCmd))

        # common options #
        if SysMgr.showAll:
            enableStat += 'ALL '
        else:
            disableStat += 'ALL '

        if SysMgr.groupProcEnable:
            enableStat += 'PGRP '
        else:
            disableStat += 'PGRP '

        if SysMgr.cpuEnable:
            enableStat += 'CPU '
        else:
            disableStat += 'CPU '

        if SysMgr.memEnable:
            enableStat += 'MEM '
        else:
            disableStat += 'MEM '

        if SysMgr.blockEnable:
            enableStat += 'BLOCK '
        else:
            disableStat += 'BLOCK '

        if SysMgr.printEnable:
            enableStat += 'PRINT '
        else:
            disableStat += 'PRINT '

        if SysMgr.sysEnable:
            enableStat += 'SYSCALL '
        else:
            disableStat += 'SYSCALL '

        if SysMgr.lockEnable:
            enableStat += 'LOCK '
        else:
            disableStat += 'LOCK '

        if SysMgr.compressEnable:
            enableStat += 'COMP '
        else:
            disableStat += 'COMP '

        if SysMgr.countEnable:
            enableStat += 'CUT '
        else:
            disableStat += 'CUT '

        # check current mode #
        if SysMgr.disableAll:
            enableStat += 'DISABLE '

        # print options #
        if enableStat != '':
            SysMgr.printInfo(\
                "enabled analysis options [ %s]" % enableStat)

        if disableStat != '':
            SysMgr.printWarn(\
                "disabled analysis options [ %s]" % disableStat)



    @staticmethod
    def getUdsList():
        udsBuf = []
        udsPath = '%s/net/unix' % SysMgr.procPath

        try:
            with open(udsPath, 'r') as fd:
                udsBuf = fd.readlines()
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printOpenErr(udsPath)
            return udsBuf

        UDS_ATTR = []
        for line in udsBuf:
            UDS_ATTR.append(line.split())

        # remove title #
        UDS_ATTR.pop(0)

        return UDS_ATTR



    @staticmethod
    def getUdpList():
        if SysMgr.udpListCache:
            return SysMgr.udpListCache

        udpBuf = []
        udpPath = '%s/net/udp' % SysMgr.procPath

        try:
            with open(udpPath, 'r') as fd:
                udpBuf = fd.readlines()
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printOpenErr(udpPath)
            return udpBuf

        udpList = []
        for line in udpBuf:
            udpList.append(line.split())

        # remove title #
        udpList.pop(0)

        SysMgr.udpListCache = udpList

        return udpList



    @staticmethod
    def getTcpList():
        if SysMgr.tcpListCache:
            return SysMgr.tcpListCache

        tcpBuf = []
        tcpPath = '%s/net/tcp' % SysMgr.procPath

        try:
            with open(tcpPath, 'r') as fd:
                tcpBuf = fd.readlines()
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printOpenErr(tcpPath)
            return tcpBuf

        tcpList = []
        for line in tcpBuf:
            tcpList.append(line.split())

        # remove title #
        tcpList.pop(0)

        SysMgr.tcpListCache = tcpList

        return tcpList



    @staticmethod
    def printProfileCmd():
        for idx, val in SysMgr.rcmdList.items():
            if len(val) == 0:
                continue

            cmds = []
            for item in val:
                cmds.append(':'.join(item))
            SysMgr.printInfo(\
                "user custom commands on %s [ %s ]" % (idx, ', '.join(cmds)))



    @staticmethod
    def getVdso(debug=False):
        # get address of vdso object #
        addr = SysMgr.getauxval("AT_SYSINFO_EHDR")

        # create a memory file #
        fd = MemoryFile(addr)

        # return vDSO #
        obj = ElfAnalyzer(path='vdso', fd=fd, debug=debug)
        if obj:
            ElfAnalyzer.cachedFiles['vdso'] = obj

        return obj



    @staticmethod
    def getauxval(attype):
        if not SysMgr.isLinux:
            return None

        try:
            nrType = ConfigMgr.AT_TYPE[attype]
        except:
            SysMgr.printErr(\
                "Fail to get entry type %s" % attype, True)
            return

        # import ctypes #
        SysMgr.importPkgItems('ctypes')

        if not SysMgr.loadLibcObj():
            return

        # declare syscalls #
        SysMgr.libcObj.getauxval.restype = c_ulong
        SysMgr.libcObj.getauxval.argtypes = [c_ulong]

        return SysMgr.libcObj.getauxval(c_ulong(nrType))



    @staticmethod
    def printProfileOption():
        enableStat = ''
        disableStat = ''

        # common options #
        enableStat += SysMgr.arch.upper() + ' '

        if SysMgr.warnEnable:
            enableStat += 'WARN '
        else:
            disableStat += 'WARN '

        if SysMgr.pipeEnable:
            enableStat += 'PIPE '
        else:
            disableStat += 'PIPE '

        if SysMgr.printEnable:
            enableStat += 'PRINT '
        else:
            disableStat += 'PRINT '

        if SysMgr.cgroupEnable:
            enableStat += 'CGROUP '
        else:
            disableStat += 'CGROUP '

        if SysMgr.encodeEnable:
            enableStat += 'ENCODE '
        else:
            disableStat += 'ENCODE '

        # check current mode #
        if SysMgr.isTopMode():
            SysMgr.printInfo("TOP MODE")

            if SysMgr.fileTopEnable:
                enableStat += 'FILE '
            else:
                if SysMgr.processEnable:
                    enableStat += 'PROCESS '
                else:
                    enableStat += 'THREAD '

                if SysMgr.cpuEnable:
                    enableStat += 'CORE '
                else:
                    disableStat += 'CORE '

                if SysMgr.gpuEnable:
                    enableStat += 'GPU '
                else:
                    disableStat += 'GPU '

                if SysMgr.memEnable:
                    enableStat += 'MEM '
                else:
                    disableStat += 'MEM '

                if SysMgr.blockEnable:
                    enableStat += 'BLOCK '
                else:
                    disableStat += 'BLOCK '

                if SysMgr.irqEnable:
                    enableStat += 'IRQ '
                else:
                    disableStat += 'IRQ '

                if SysMgr.diskEnable:
                    enableStat += 'DISK '
                else:
                    disableStat += 'DISK '

                if SysMgr.perfEnable or \
                    SysMgr.perfGroupEnable:
                    enableStat += 'PERF '
                else:
                    disableStat += 'PERF '

                if SysMgr.nsEnable:
                    enableStat += 'NS '
                else:
                    disableStat += 'NS '

                if SysMgr.wchanEnable:
                    enableStat += 'WCHAN '
                else:
                    disableStat += 'WCHAN '

                if SysMgr.oomEnable:
                    enableStat += 'OOM '
                else:
                    disableStat += 'OOM '

                if SysMgr.floatEnable:
                    enableStat += 'FLOAT '
                else:
                    disableStat += 'FLOAT '

                if SysMgr.sigHandlerEnable:
                    enableStat += 'SIG '
                else:
                    disableStat += 'SIG '

                if SysMgr.wfcEnable:
                    enableStat += 'WFC '
                else:
                    disableStat += 'WFC '

                if SysMgr.cmdlineEnable:
                    enableStat += 'CMD '
                else:
                    disableStat += 'CMD '

                if SysMgr.stackEnable:
                    enableStat += 'STACK '

                if SysMgr.networkEnable:
                    enableStat += 'NET '

                if SysMgr.affinityEnable:
                    enableStat += 'AFNT '
                else:
                    disableStat += 'AFNT '

                if SysMgr.reportFileEnable:
                    enableStat += 'RFILE '
                else:
                    disableStat += 'RFILE '

                if SysMgr.pssEnable:
                    enableStat += 'PSS '
                else:
                    disableStat += 'PSS '

                if SysMgr.ussEnable:
                    enableStat += 'USS '
                else:
                    disableStat += 'USS '

                if SysMgr.wssEnable:
                    enableStat += 'WSS '
                else:
                    disableStat += 'WSS '

                if SysMgr.dltEnable:
                    enableStat += 'DLT '
                else:
                    disableStat += 'DLT '

                if SysMgr.syslogEnable:
                    enableStat += 'SYSLOG '
                else:
                    disableStat += 'SYSLOG '

                if SysMgr.kmsgEnable:
                    enableStat += 'KMSG '
                else:
                    disableStat += 'KMSG '

                if SysMgr.journalEnable:
                    enableStat += 'JRL '
                else:
                    disableStat += 'JRL '

                if SysMgr.schedEnable:
                    enableStat += 'SCHED '
                else:
                    disableStat += 'SCHED '

                if SysMgr.delayEnable:
                    enableStat += 'DELAY '
                else:
                    disableStat += 'DELAY '

                if SysMgr.groupProcEnable:
                    enableStat += 'PGRP '
                else:
                    disableStat += 'PGRP '

                if SysMgr.reportEnable:
                    enableStat += 'REPORT '
                else:
                    disableStat += 'REPORT '

        elif SysMgr.isFunctionMode():
            SysMgr.printInfo("FUNCTION MODE")

            if SysMgr.graphEnable:
                enableStat += 'GRAPH '
            else:
                disableStat += 'GRAPH '

                if not SysMgr.cpuEnable:
                    disableStat += 'CPU '
                else:
                    enableStat += 'CPU '

                if not SysMgr.memEnable:
                    disableStat += 'MEM '
                else:
                    enableStat += 'MEM '

                if not SysMgr.heapEnable:
                    disableStat += 'HEAP '
                else:
                    enableStat += 'HEAP '

                if not SysMgr.blockEnable:
                    disableStat += 'BLOCK '
                else:
                    enableStat += 'BLOCK '

                if not SysMgr.userEnable:
                    disableStat += 'USER '
                else:
                    enableStat += 'USER '

                if SysMgr.sysEnable:
                    enableStat += 'SYSCALL '
                else:
                    disableStat += 'SYSCALL '

                if SysMgr.lockEnable:
                    enableStat += 'LOCK '
                else:
                    disableStat += 'LOCK '

                if SysMgr.compressEnable:
                    enableStat += 'COMP '
                else:
                    disableStat += 'COMP '

                if SysMgr.disableAll:
                    enableStat += 'DISABLE '
                else:
                    disableStat += 'DISABLE '

        elif SysMgr.isFileMode():
            SysMgr.printInfo("FILE MODE")

        elif SysMgr.isSystemMode():
            SysMgr.printInfo("SYSTEM MODE")

        else:
            SysMgr.printInfo("THREAD MODE")
            SysMgr.threadEnable = True

            if not SysMgr.cpuEnable:
                disableStat += 'CPU '
            else:
                enableStat += 'CPU '

            if SysMgr.memEnable:
                enableStat += 'MEM '
            else:
                disableStat += 'MEM '

            if SysMgr.blockEnable:
                enableStat += 'BLOCK '
            else:
                disableStat += 'BLOCK '

            if SysMgr.irqEnable:
                enableStat += 'IRQ '
            else:
                disableStat += 'IRQ '

            if SysMgr.ueventEnable:
                enableStat += 'UEVT '
            else:
                disableStat += 'UEVT '

            if SysMgr.keventEnable:
                enableStat += 'KEVT '
            else:
                disableStat += 'KEVT '

            if SysMgr.networkEnable:
                enableStat += 'NET '
            else:
                disableStat += 'NET '

            if SysMgr.depEnable:
                enableStat += 'DEP '
            else:
                disableStat += 'DEP '

            if SysMgr.latEnable:
                enableStat += 'LATENCY '
            else:
                disableStat += 'LATENCY '

            if SysMgr.sysEnable:
                enableStat += 'SYSCALL '
            else:
                disableStat += 'SYSCALL '

            if SysMgr.lockEnable:
                enableStat += 'LOCK '
            else:
                disableStat += 'LOCK '

            if SysMgr.powerEnable:
                enableStat += 'POWER '
            else:
                disableStat += 'POWER '

            if SysMgr.resetEnable:
                enableStat += 'RESET '

            if SysMgr.compressEnable:
                enableStat += 'COMP '
            else:
                disableStat += 'COMP '

            if SysMgr.disableAll:
                enableStat += 'DISABLE '

        # print options #
        if enableStat != '':
            SysMgr.printInfo(\
                "enabled runtime options [ %s]" % enableStat)

        if disableStat != '':
            SysMgr.printWarn(\
                "disabled runtime options [ %s]" % disableStat)



    @staticmethod
    def isThreadMode():
        return SysMgr.threadEnable



    @staticmethod
    def isFunctionMode():
        return SysMgr.functionEnable



    @staticmethod
    def isFileMode():
        return SysMgr.fileEnable



    @staticmethod
    def isSystemMode():
        return SysMgr.systemEnable



    @staticmethod
    def defaultHandler(signum, frame):
        return



    @staticmethod
    def chldHandler(signum, frame):
        try:
            os.waitpid(-1, os.WNOHANG)
        except:
            pass



    @staticmethod
    def fgHandler(signum, frame):
        SysMgr.bgStatus = False



    @staticmethod
    def bgHandler(signum, frame):
        SysMgr.bgStatus = True

        if signum == signal.SIGTSTP:
            os.kill(SysMgr.pid, signal.SIGSTOP)



    @staticmethod
    def winchHandler(signum, frame):
        SysMgr.getTty(update=True)



    @staticmethod
    def stopHandler(signum, frame):
        if SysMgr.exitFlag:
            os._exit(0)

        # masking signal #
        signal.signal(signum, signal.SIG_IGN)

        # write user command #
        SysMgr.writeTraceCmd('STOP')

        if SysMgr.isFileMode() or \
            SysMgr.isSystemMode():
            SysMgr.condExit = True

        elif SysMgr.isTopMode() or SysMgr.isTraceMode():
            if SysMgr.printFile:
                # reload data written to file #
                if SysMgr.pipeEnable:
                    SysMgr.reloadFileBuffer()

                SysMgr.printLogo(absolute=True, big=True)

                # save system info #
                SysMgr.sysInstance.saveSysStat()
                SysMgr.printInfoBuffer()

                # submit summarized report and details #
                ThreadAnalyzer.printIntervalUsage()

                fsize = \
                    UtilMgr.convSize2Unit(\
                        long(os.path.getsize(SysMgr.inputFile)))

                SysMgr.printInfo(\
                    "save results based monitoring into "
                    "%s [%s] successfully" % \
                    (SysMgr.inputFile, fsize))

            SysMgr.releaseResource()

            # enable signal again #
            signal.signal(signum, SysMgr.stopHandler)

            # quit to avoid termination #
            if not SysMgr.termFlag:
                SysMgr.progressCnt = long(0)
                return

            # enable for cProfile #
            #sys.settrace
            #sys.exit(0)

            # do terminate #
            os._exit(0)

        else:
            SysMgr.writeEvent("EVENT_STOP", False)
            signal.signal(signal.SIGINT, signal.SIG_DFL)
            SysMgr.stopRecording()

        # update record status #
        SysMgr.recordStatus = False

        SysMgr.repeatCount = long(0)

        SysMgr.printStat(\
            'ready to save and analyze... [ STOP(Ctrl+c) ]')

        # enable signal again #
        signal.signal(signum, SysMgr.stopHandler)

        if not "ISMAIN" in os.environ:
            sys.exit(0)

        raise Exception()



    @staticmethod
    def newHandler(signum, frame):
        SysMgr.condExit = False

        if SysMgr.isFileMode():
            SysMgr.printStat("saved file usage successfully")
        elif SysMgr.isSystemMode():
            pass
        elif SysMgr.isTopMode():
            # check silent mode #
            if not SysMgr.printFile:
                return

            # masking signal #
            signal.signal(signum, signal.SIG_IGN)

            # reload data written to file #
            if SysMgr.pipeEnable:
                SysMgr.reloadFileBuffer()

            SysMgr.printLogo(absolute=True, big=True)

            # save system info #
            SysMgr.sysInstance.saveSysStat()
            SysMgr.printInfoBuffer()

            # submit summarized report and details #
            ThreadAnalyzer.printIntervalUsage()

            # close an output file to sync #
            try:
                SysMgr.fileForPrint.close()
            except:
                pass
            finally:
                SysMgr.fileForPrint = None

            # print output info #
            fsize = \
                UtilMgr.convSize2Unit(\
                    long(os.path.getsize(SysMgr.inputFile)))

            SysMgr.printInfo(\
                "save results based monitoring into "
                "%s [%s] successfully" % \
                    (SysMgr.inputFile, fsize))

            # enable signal again #
            signal.signal(signum, SysMgr.newHandler)
        elif SysMgr.resetEnable:
            SysMgr.writeEvent("EVENT_START")
        else:
            SysMgr.writeEvent("EVENT_MARK")



    @staticmethod
    def exitHandler(signum, frame):
        if SysMgr.exitFlag:
            os._exit(0)

        # block signals for stable termination #
        SysMgr.setIgnoreSignal()

        signal.alarm(0)
        SysMgr.condExit = True

        SysMgr.printWarn('Terminated by user\n')

        sys.exit(0)



    @staticmethod
    def faultHandler(signum, frame):
        '''
        SysMgr.releaseResource()
        sys.stdout.write('Terminated by SEGFAULT signal\n')
        '''
        os._exit(0)



    @staticmethod
    def timerHandler(signum, frame):
        raise Exception()



    @staticmethod
    def alarmHandler(signum, frame):
        if SysMgr.repeatCount <= SysMgr.progressCnt and \
            SysMgr.termFlag:
            UtilMgr.deleteProgress()
            sys.exit(0)

        UtilMgr.printProgress(\
            SysMgr.progressCnt, SysMgr.repeatCount)

        # update count #
        SysMgr.progressCnt += 1
        progressCnt = SysMgr.progressCnt
        repeatInterval = SysMgr.repeatInterval
        repeatCount = SysMgr.repeatCount

        # disable alarm handler #
        signal.signal(signal.SIGALRM, SysMgr.defaultHandler)

        if SysMgr.pipeEnable:
            if repeatCount == progressCnt:
                SysMgr.stopRecording()
                SysMgr.recordStatus = False
            signal.alarm(repeatInterval)
        elif SysMgr.outputFile:
            if repeatCount == 1 and SysMgr.termFlag:
                output = SysMgr.outputFile
            else:
                output = '%s_%s' % \
                    (SysMgr.outputFile, SysMgr.getRuntime())

            # save system info #
            SysMgr.sysInstance.saveSysStat()

            # compress by gzip #
            if SysMgr.compressEnable:
                compressor = SysMgr.getPkg('gzip', False)
            else:
                compressor = None

            # read trace data #
            try:
                rpath = os.path.join(SysMgr.mountPath, '../trace')
                with open(rpath, 'r') as fr:
                    lines = fr.readlines()
            except:
                err = SysMgr.getErrMsg()
                SysMgr.printOpenErr(rpath)
                sys.exit(0)

            # write trace data #
            try:
                SysMgr.saveTraceData(lines, output)
                SysMgr.clearInfoBuffer()
            except:
                sys.exit(0)
        else:
            SysMgr.printErr(\
                'Fail to save data because file path is not set')
            sys.exit(0)

        # set alarm again #
        signal.signal(signal.SIGALRM, SysMgr.alarmHandler)



    @staticmethod
    def isTermSignal(sig):
        if sig == signal.SIGKILL or \
            sig == signal.SIGSEGV or \
            sig == signal.SIGABRT:
            return True
        else:
            return False



    @staticmethod
    def saveTraceData(lines, outputFile=None):
        if not outputFile:
            outputFile = SysMgr.outputFile

        # backup data file already exist #
        try:
            if os.path.isfile(outputFile):
                backupFile = outputFile + '.old'

                os.rename(outputFile, backupFile)
                SysMgr.printInfo(\
                    '%s is renamed to %s' % (outputFile, backupFile))
        except:
            SysMgr.printErr(\
                "Fail to backup %s to %s" % \
                    (outputFile, backupFile), True)

        # compress by gzip #
        if SysMgr.isRecordMode() and SysMgr.compressEnable:
            compressor = SysMgr.getPkg('gzip', False)
        else:
            compressor = None

        size = long(0)
        for line in lines:
            size += len(line)

        SysMgr.printInfo(\
            "wait for writing data to %s [%s] " % \
                (outputFile, UtilMgr.convSize2Unit(size)))

        try:
            if compressor:
                fd = open(outputFile, 'wb')
                magicStr = 'gzip %s\n' % ' '.join(sys.argv)
                fd.write(magicStr.encode())

                f = compressor.GzipFile(fileobj=fd)

                # write system info #
                if SysMgr.systemInfoBuffer != '':
                    totalStr = '%s\n%s\n%s\n' % \
                        (SysMgr.magicString, \
                        SysMgr.systemInfoBuffer, \
                        SysMgr.magicString)
                    f.write(totalStr.encode())

                # convert data #
                lstring = '\n'.join(lines)
                try:
                    lstring = lstring.encode()
                except:
                    SysMgr.printErr(\
                        "Fail to encoding data")
                    sys.exit(0)

                f.write(lstring)
            else:
                f = open(outputFile, 'w')

                # write system info #
                if SysMgr.systemInfoBuffer != '':
                    magicStr = '%s\n' % SysMgr.magicString
                    f.writelines(magicStr)
                    f.writelines(SysMgr.systemInfoBuffer)
                    f.writelines(magicStr)

                # write trace info #
                f.writelines(lines)

            f.close()

            try:
                fsize = UtilMgr.convSize2Unit(\
                    long(os.path.getsize(outputFile)))
            except:
                fsize = '?'

            SysMgr.printInfo(\
                'finish saving trace data into %s [%s] successfully' % \
                (outputFile, fsize))
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Fail to write trace data to %s" % outputFile, True)



    @staticmethod
    def writeTraceCmd(time):
        if SysMgr.rcmdList == {}:
            return

        for cmd in SysMgr.rcmdList[time]:
            if len(cmd) == 2:
                path = cmd[0]
                val = cmd[1]

                try:
                    with open(path, 'w') as fd:
                        fd.write(val)
                        SysMgr.printInfo(\
                            "applied command '%s' to %s successfully" % \
                            (val, path))
                except:
                    SysMgr.printWarn(\
                        "Fail to apply command '%s' to %s" % (val, path))
            elif len(cmd) == 1:
                os.system(cmd[0])



    @staticmethod
    def readCmdVal(path):
        # open for applying command #
        try:
            target = '%s%s' % (SysMgr.mountPath, path)
            with open(target, 'r') as fd:
                return fd.read()[:-1]
        except:
            SysMgr.printErr(\
                "Fail to read data from %s\n" % target)
            return None



    @staticmethod
    def procReadline(path):
        target = '%s/%s' % (SysMgr.procPath, path)
        with open(target, 'r') as fd:
            return fd.readline()



    @staticmethod
    def procReadlines(path):
        target = '%s/%s' % (SysMgr.procPath, path)
        with open(target, 'r') as fd:
            return fd.readlines()



    @staticmethod
    def writeCmd(path, val, append=False):
        # set file open permission #
        if append:
            perm = 'a+'
        else:
            perm = 'w'

        # record command to file #
        if SysMgr.cmdEnable:
            if not SysMgr.cmdFd:
                try:
                    SysMgr.cmdFd = open(SysMgr.cmdEnable, perm)
                    SysMgr.cmdFd.write(\
                        'mount -t debugfs nodev %s 2>/dev/null\n' % \
                        SysMgr.debugfsPath)
                    SysMgr.cmdFd.write(\
                        'echo "\nstart recording... [ STOP(Ctrl+c) ]\n"\n')
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printOpenErr(SysMgr.cmdEnable)
                    return -1
            if SysMgr.cmdFd:
                try:
                    cmd = 'echo "%s" > %s%s 2>/dev/null\n' %\
                        (str(val), SysMgr.mountPath, path)
                    SysMgr.cmdFd.write(cmd)
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printErr("Fail to write command")
                    return -1

        # open for applying command #
        try:
            target = '%s%s' % (SysMgr.mountPath, path)

            if append:
                if target in SysMgr.cmdAttachCache:
                    fd = SysMgr.cmdAttachCache[target]
                    os.lseek(fd, 0, 0)
                else:
                    fd = os.open(target, os.O_RDWR|os.O_CREAT|os.O_APPEND)
                    SysMgr.cmdAttachCache[target] = fd
            else:
                if target in SysMgr.cmdFileCache:
                    fd = SysMgr.cmdFileCache[target]
                    fd.seek(0, 0)
                else:
                    fd = open(target, perm)
                    SysMgr.cmdFileCache[target] = fd
        except SystemExit:
            sys.exit(0)
        except:
            fpos = path.rfind('/')
            try:
                if path[fpos+1:] == 'enable':
                    epath = path[:fpos]
                else:
                    epath = path[fpos+1:]
            except:
                epath = path

            try:
                SysMgr.sysInstance.cmdList[epath] = False
            except:
                pass

            SysMgr.printWarn(\
                "Fail to use %s event, please check kernel configuration" % \
                    epath, reason=True)
            return -1

        # apply command #
        try:
            if append:
                os.write(fd, bytes(UtilMgr.encodeStr(val)))
                #os.fsync(fd)
            else:
                fd.write(val)
                fd.flush()

            # modify flags in command list #
            if path.endswith('/enable'):
                if val == '1':
                    SysMgr.sysInstance.\
                        cmdList[path[:path.rfind('/enable')]] = True
                elif val == '0':
                    SysMgr.sysInstance.\
                        cmdList[path[:path.rfind('/enable')]] = False
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printWarn(\
                "Fail to apply command '%s' to %s" % \
                    (val, path), reason=True)
            return -2

        return 0



    @staticmethod
    def doPrint(newline=True, clear=False, flush=True, addLine=False):
        if len(SysMgr.bufferString) == 0:
            return

        if addLine:
            output = '%s\n' % SysMgr.bufferString
        else:
            output = SysMgr.bufferString

        SysMgr.printPipe(output, newline=newline, flush=flush)

        if clear:
            SysMgr.clearPrint()



    @staticmethod
    def printConsole(string):
        # split and cut lines by cols #
        string = '\n'.join(\
            [nline[:SysMgr.ttyCols-1] for nline in string.split('\n')])

        # print on console #
        print(string[:-1])



    @staticmethod
    def addPrint(string, newline=1, force=False, listBuf=False):
        if not force and SysMgr.checkCutCond(newline):
            return False

        # add string to buffer #
        if listBuf:
            SysMgr.bufferList.append(string)
        else:
            SysMgr.bufferString = \
                "%s%s" % (SysMgr.bufferString, string)

        SysMgr.bufferRows += newline

        if SysMgr.terminalOver or \
            not SysMgr.printFile or \
            not SysMgr.printStreamEnable:
            return True

        SysMgr.printConsole(string)

        return True



    @staticmethod
    def getPrintList(retStr=False, sort=False):
        if sort:
            SysMgr.bufferList.sort()

        if retStr:
            return '\n'.join(SysMgr.bufferList)
        else:
            return SysMgr.bufferList



    @staticmethod
    def delPrint(newline=1):
        try:
            target = SysMgr.bufferString
            start = target.rfind('\n')
            pos = newline

            while start >= 0 and pos > 1:
                start = target.rfind('\n', start - 1)
                pos -= 1

            SysMgr.bufferString = target[:start + 1]
            SysMgr.bufferRows -= newline
        except:
            pass



    @staticmethod
    def clearPrint():
        del SysMgr.bufferString
        SysMgr.bufferString = ''
        SysMgr.bufferRows = long(0)
        SysMgr.terminalOver = False



    @staticmethod
    def clearScreen():
        # check stdout status #
        if not SysMgr.printEnable or \
            SysMgr.pipeForPrint:
            return

        if SysMgr.isLinux and \
            not 'REMOTERUN' in os.environ:
            sys.stdout.write("\x1b[2J\x1b[H")
        elif sys.platform.startswith('win'):
            os.system('cls')
        else:
            pass



    @staticmethod
    def printLogo(absolute=False, big=False, onlyFile=False, pager=True):
        # check package #
        if not "ISMAIN" in os.environ:
            print("\nPowered by %s" % ConfigMgr.logo)
            return

        # check print option and remote runner #
        if not SysMgr.printEnable or \
            "REMOTERUN" in os.environ:
            return

        # check extended ascii support #
        SysMgr.convertExtAscii(ConfigMgr.logo)

        if not SysMgr.printFile:
            if SysMgr.printStreamEnable:
                if not absolute:
                    return
            elif onlyFile:
                return

        # print logo #
        if big:
            if pager:
                SysMgr.printPipe(ConfigMgr.logo)
            else:
                print(ConfigMgr.logo)
        else:
            title = "/ G.u.i.d.e.r \tver.%s /" % __version__
            underline = '_' * (len(title))
            overline = '-' * (len(title))
            SysMgr.printPipe(\
                ' %s\n%s\n%s' % (underline, title, overline))



    @staticmethod
    def printInfoBuffer():
        SysMgr.printPipe(SysMgr.systemInfoBuffer)
        SysMgr.clearInfoBuffer()



    @staticmethod
    def parseCustomRecordCmd(cmdList):
        tempList = {'BEFORE': [], 'AFTER': [], 'STOP': []}

        if not cmdList:
            return {}

        cmdList = cmdList.split(',')

        for item in cmdList:
            sitem = item.split(':')
            ltime = sitem[0]

            if len(sitem) < 2 or len(sitem) > 3 or \
                (ltime != 'BEFORE' and ltime != 'AFTER' and ltime != 'STOP'):
                SysMgr.printErr(\
                    "wrong format used, BEFORE|AFTER|STOP:file:value")
                sys.exit(0)
            elif len(sitem) == 2:
                tempList[ltime].append([sitem[1]])
            elif len(sitem) == 3:
                tempList[ltime].append([sitem[1], sitem[2]])

        return tempList



    @staticmethod
    def clearList(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 and union:
            # remove redundant values #
            targetList = list(set(targetList))

            # remove empty values #
            newList = []
            for val in targetList:
                if val != '':
                    newList.append(val)

            return newList
        else:
            return targetList



    @staticmethod
    def getMountInfo():
        # check whether there is mount info in saved buffer #
        infoBuf = SysMgr.systemInfoBuffer

        if infoBuf == '':
            return

        mountPosStart = infoBuf.find('Storage Info')
        if mountPosStart == -1:
            return

        mountPosStart = infoBuf.find(twoLine, mountPosStart+1)
        if mountPosStart == -1:
            return

        mountPosStart = infoBuf.find(twoLine, mountPosStart+1)
        if mountPosStart == -1:
            return

        mountPosStart = infoBuf.find('\n', mountPosStart)
        if mountPosStart == -1:
            return

        mountPosEnd = infoBuf.find(oneLine, mountPosStart)
        if mountPosEnd == -1:
            return

        try:
            mountTable = []
            tempTable = infoBuf[mountPosStart:mountPosEnd].split('\n')
            for idx, line in enumerate(tempTable):
                nrItem = len(line.split())
                if 1 < nrItem < 4:
                    mountTable.append('%s %s' % (line, tempTable[idx+1]))
        except:
            pass

        init_mountData = {'dev': ' ', 'filesystem': ' ', 'mount': ' '}

        for item in mountTable:
            m = re.match((\
                r'(?P<dev>\S+)\s+\((?P<devt>\S+)\)\s+\[(?P<range>\S+)\]\s+'
                r'(?P<maj>[0-9]+):(?P<min>[0-9]+)\s+(?P<readSize>\S+)\s+'
                r'(?P<writeSize>\S+)\s+(?P<totalSize>\S+)\s+'
                r'(?P<freeSize>\S+)\s+(?P<Usage>\S+)\s+(?P<nrFile>\S+)\s+'
                r'(?P<filesystem>\S+)\s+(?P<mount>.+)'), item)
            if not m:
                continue

            d = m.groupdict()
            mid = '%s:%s' % (d['maj'], d['min'])
            SysMgr.savedMountTree[mid] = dict(init_mountData)
            SysMgr.savedMountTree[mid]['dev'] = d['dev']
            SysMgr.savedMountTree[mid]['filesystem'] = d['filesystem']
            SysMgr.savedMountTree[mid]['mount'] = d['mount']

            # add block range info #
            try:
                start, end = d['range'].split('-')
                SysMgr.savedMountTree[mid]['start'] = long(start)
                SysMgr.savedMountTree[mid]['end'] = long(end)
            except:
                pass



    @staticmethod
    def getProcTreeInfo():
        # check whether there is procTreeInfo in saved buffer #
        infoBuf = SysMgr.systemInfoBuffer

        if infoBuf == '':
            return

        treePosStart = infoBuf.find('!!!!!')
        if treePosStart == -1:
            return

        # check whether there is procTreeInfo in saved buffer #
        procTree = infoBuf[treePosStart + len('!!!!!'):].split(',')
        for pair in procTree:
            try:
                ids = pair.split(':')
                tid = ids[0]
                pid = ids[1]

                # get pid and comm #
                if not pid.isdigit():
                    group = pid
                    pidPos = group.find('(')
                    pid = group[:pidPos]
                    comm = group[pidPos+1:-1]
                    SysMgr.savedProcComm[pid] = comm

                SysMgr.savedProcTree[tid] = pid
            except:
                continue

        # remove process tree info #
        SysMgr.systemInfoBuffer = infoBuf[:treePosStart]



    @staticmethod
    def applyLaunchOption():
        # check whether there is launch option in saved buffer #
        infoBuf = SysMgr.systemInfoBuffer

        # get position of launch option #
        if infoBuf == '':
            return

        launchPosStart = infoBuf.find('Launch')
        if launchPosStart == -1:
            return

        launchPosEnd = infoBuf.find('\n', launchPosStart)
        if launchPosEnd == -1:
            return

        SysMgr.launchBuffer = infoBuf[launchPosStart:launchPosEnd]

        # check version #
        try:
            verPosStart = infoBuf.find('Version')
            verPosEnd = infoBuf.find('\n', verPosStart)
            recVer = infoBuf[verPosStart:verPosEnd].split()[1]
            if recVer != __version__:
                SysMgr.printWarn(\
                    "data version %s is different from current software %s" % \
                    (__version__, recVer), True)
        except:
            pass

        # apply arch type #
        if not SysMgr.archOption:
            try:
                archPosStart = infoBuf.find('Arch')
                archPosEnd = infoBuf.find('\n', archPosStart)
                arch = infoBuf[archPosStart:archPosEnd].split()[1]
                SysMgr.setArch(arch)
            except:
                pass

        # add anlaysis option #
        archPosStart = infoBuf.find('Arch')
        archPosEnd = infoBuf.find('\n', archPosStart)
        if archPosStart >= 0 and archPosEnd >= 0:
            analOption = "{0:20} {1:<100}".format(\
                'Analysis', '# %s' % (' '.join(sys.argv)))
            SysMgr.systemInfoBuffer = '%s\n%s\n%s' % \
                (infoBuf[:archPosEnd], analOption, infoBuf[archPosEnd+1:])

        # apply mode option #
        if SysMgr.isDrawMode():
            SysMgr.printInfo("DRAW MODE")
        elif ' funcrec ' in SysMgr.launchBuffer or \
            ' funcrecord ' in SysMgr.launchBuffer:
            SysMgr.threadEnable = False
            SysMgr.functionEnable = True
            SysMgr.printInfo("FUNCTION MODE")
        else:
            SysMgr.threadEnable = True
            SysMgr.printInfo("THREAD MODE")

        # apply filter option #
        filterList = None
        launchPosStart = SysMgr.launchBuffer.find(' -g')
        if SysMgr.isThreadMode() and launchPosStart > -1:
            filterList = SysMgr.launchBuffer[launchPosStart + 3:]
            filterList = filterList[:filterList.find(' -')].strip()
            SysMgr.filterGroup = filterList.split(',')
            SysMgr.filterGroup = \
                SysMgr.clearList(SysMgr.filterGroup)
            SysMgr.printInfo(\
                "only specific threads [ %s ] were recorded" % \
                ', '.join(SysMgr.filterGroup))

        # check filter list #
        if len(SysMgr.filterGroup) > 0:
            if not SysMgr.groupProcEnable:
                SysMgr.printInfo(\
                    "only specific threads [ %s ] are shown" % \
                    ', '.join(SysMgr.filterGroup))
            else:
                SysMgr.printInfo((\
                    "only specific threads that involved "
                    "in the process group [ %s ] are shown") % \
                    ', '.join(SysMgr.filterGroup))

        # apply dependency option #
        if ' -D' in SysMgr.launchBuffer:
            SysMgr.depEnable = True

        # apply syscall option #
        if ' -t' in SysMgr.launchBuffer:
            SysMgr.sysEnable = True

        # apply disable option #
        launchPosStart = SysMgr.launchBuffer.find(' -d')
        if launchPosStart > -1:
            filterList = SysMgr.launchBuffer[launchPosStart + 3:]
            filterList = filterList[:filterList.find(' -')]
            if 'u' in filterList:
                SysMgr.userEnable = False
                SysMgr.userRecordEnable = False
            if 'a' in filterList:
                SysMgr.disableAll = True
            if 'c' in filterList:
                SysMgr.cpuEnable = False
                SysMgr.latEnable = False
            if 'l' in filterList:
                SysMgr.latEnable = False

        # apply enable option #
        launchPosStart = SysMgr.launchBuffer.find(' -e')
        if launchPosStart > -1:
            filterList = SysMgr.launchBuffer[launchPosStart + 3:]
            filterList = filterList[:filterList.find(' -')]
            if 'm' in filterList:
                SysMgr.memEnable = True
            if 'b' in filterList:
                SysMgr.blockEnable = True
            if 'P' in filterList:
                SysMgr.powerEnable = True
            if 'h' in filterList:
                SysMgr.heapEnable = True
            if 'L' in filterList:
                SysMgr.lockEnable = True
            if 'i' in filterList:
                SysMgr.irqEnable = True
            if 'n' in filterList:
                SysMgr.networkEnable = True

            # memory type #
            if 'S' in filterList:
                SysMgr.pssEnable = True
            elif 'u' in filterList:
                SysMgr.ussEnable = True
            elif not SysMgr.isDrawMode():
                SysMgr.rssEnable = True
        elif not SysMgr.isDrawMode():
            SysMgr.rssEnable = True

        # apply custom option #
        launchPosStart = SysMgr.launchBuffer.find(' -c')
        if launchPosStart > -1:
            filterList = SysMgr.launchBuffer[launchPosStart + 3:]
            endIdx = filterList.find(' -')
            if endIdx >= 0:
                filterList = filterList[:endIdx]
            filterList = filterList.strip().split(',')
            for idx, item in enumerate(filterList):
                tempItem = filterList[idx].split('/')
                if len(tempItem) == 2:
                    filterList[idx] = tempItem[1]
                    SysMgr.customEventList.append(tempItem[1])
                elif len(tempItem) == 1:
                    filterList[idx] = tempItem[0]
                    SysMgr.customEventList.append(tempItem[0])
                else:
                    filterList.pop(idx)
            if len(filterList) > 0:
                SysMgr.printInfo(\
                    "profiled custom events [ %s ]" % ', '.join(filterList))
                if not SysMgr.customCmd:
                    SysMgr.customCmd = filterList

        # apply user event option #
        launchPosStart = SysMgr.launchBuffer.find(' -U')
        if launchPosStart > -1:
            SysMgr.ueventEnable = True
            filterList = SysMgr.launchBuffer[launchPosStart + 3:]
            filterList = filterList[:filterList.find(' -')].strip()
            SysMgr.userCmd = str(filterList).split(',')
            SysMgr.userCmd = \
                SysMgr.clearList(SysMgr.userCmd)
            SysMgr.printInfo("profiled user events [ %s ]" % \
                ', '.join([ cmd.strip() for cmd in SysMgr.userCmd]))
            SysMgr.userEventList = \
                [ cmd.split(':')[0].strip() for cmd in SysMgr.userCmd]

        # apply kernel event option #
        launchPosStart = SysMgr.launchBuffer.find(' -K')
        if launchPosStart > -1:
            SysMgr.keventEnable = True
            filterList = SysMgr.launchBuffer[launchPosStart + 3:]
            filterList = filterList[:filterList.find(' -')].strip()
            SysMgr.kernelCmd = str(filterList).split(',')
            SysMgr.kernelCmd = \
                SysMgr.clearList(SysMgr.kernelCmd)
            SysMgr.printInfo("profiled kernel events [ %s ]" % \
                ', '.join([ cmd.strip() for cmd in SysMgr.kernelCmd]))
            SysMgr.kernelEventList = \
                [ cmd.split(':')[0].strip() for cmd in SysMgr.kernelCmd]

        # apply arch option #
        launchPosStart = SysMgr.launchBuffer.find(' -A')
        if launchPosStart > -1:
            filterList = SysMgr.launchBuffer[launchPosStart + 3:]
            filterList = filterList[:filterList.find(' -')].strip()

            if SysMgr.arch != filterList:
                SysMgr.printErr((\
                    "arch(%s) of recorded target is different with "
                    "current arch(%s), use -A option with %s") % \
                    (filterList, SysMgr.arch, filterList))
                sys.exit(0)



    @staticmethod
    def writeEvent(message, show=True):
        if not SysMgr.eventLogFd:
            if not SysMgr.eventLogPath:
                SysMgr.eventLogPath = \
                    '%s%s' % (SysMgr.mountPath, '../trace_marker')

            try:
                SysMgr.eventLogFd = \
                    open(SysMgr.eventLogPath, 'w')
            except:
                SysMgr.printOpenWarn(\
                    "Fail to open %s" % SysMgr.eventLogPath)
                return

        if SysMgr.eventLogFd:
            try:
                SysMgr.eventLogFd.write(message)
                event = message[message.find('_')+1:]
                if show:
                    SysMgr.printInfo('wrote %s event' % event)
                SysMgr.eventLogFd.flush()
                return True
            except:
                SysMgr.printWarn(\
                    "Fail to write %s event" % (message), reason=True)
                return
        else:
            SysMgr.printErr(\
                "Fail to write %s event because there is no file descriptor\n" % \
                message)



    @staticmethod
    def infoBufferPrint(line):
        SysMgr.systemInfoBuffer = \
            '%s%s\n' % (SysMgr.systemInfoBuffer, line)



    @staticmethod
    def clearInfoBuffer():
        SysMgr.systemInfoBuffer = ''



    @staticmethod
    def printPipWarn(name, pkg):
        SysMgr.printWarn((\
            "Fail to import python package: %s, "
            "Try to enter 'pip%s install %s'") % \
                (name, sys.version_info[0], pkg), True)



    @staticmethod
    def drawText(lines):
        imageType = None

        # get textwrap object #
        textwrap = SysMgr.getPkg('textwrap', False)
        if not textwrap:
            SysMgr.printPipWarn('textwrap', 'textwrap3')
            sys.exit(0)

        # get PIL object #
        PIL = SysMgr.getPkg('PIL', False)
        if not PIL:
            SysMgr.printPipWarn('PIL', 'pillow')
            sys.exit(0)

        from PIL import Image, ImageFont, ImageDraw

        # load jpeg plugin #
        try:
            if not imageType:
                from PIL import JpegImagePlugin
                imageType = 'jpg'
        except ImportError:
            err = sys.exc_info()[1]
            SysMgr.printWarn(\
                "Fail to import python package: %s" % err.args[0])

        # load bmp plugin instead of jpeg #
        try:
            if not imageType:
                from PIL import BmpImagePlugin
                imageType = 'bmp'
        except ImportError:
            err = sys.exc_info()[1]
            SysMgr.printErr(\
                "Fail to import python package: %s" % err.args[0])
            return

        if not SysMgr.imagePath:
            SysMgr.printErr("Fail to load image path")
            return

        # set image file extension #
        SysMgr.imagePath += '.%s' % imageType

        if SysMgr.fontPath:
            try:
                # load specific font #
                imageFont = ImageFont.truetype(SysMgr.fontPath, 10)
            except:
                SysMgr.printErr(\
                    "Fail to load font from %s" % SysMgr.fontPath)
                return
        else:
            try:
                # load default font #
                imageFont = ImageFont.load_default().font
            except:
                SysMgr.printErr((\
                    "Fail to load default font because %s, "
                    "try to use -T option") % SysMgr.getErrMsg())
                return

        # get default font size and image length #
        text = textwrap.fill('A', width=150)
        fontSizeX, fontSizeY = imageFont.getsize(text)

        # check input parameter #
        if type(lines) is list:
            lines = ''.join(lines)

        # convert string to list #
        lines = lines.split('\n')

        # calculate image size #
        imageSizeX = fontSizeX * SysMgr.lineLength
        imageSizeY = fontSizeY * len(lines) + (fontSizeY * 2)
        imagePosY = 1

        # make new blink image #
        if imageType == 'jpg':
            imageObject = \
                Image.new("RGB", (imageSizeX, imageSizeY), (255, 255, 255))
        elif imageType == 'bmp':
            imageObject = \
                Image.new("RGB", (900, imageSizeY), (255, 255, 255))
        else:
            SysMgr.printErr("No output image type")
            return

        # make palette #
        drawnImage = ImageDraw.Draw(imageObject)

        for line in lines:
            text = textwrap.fill(line, width=170)

            imagePosY += fontSizeY

            # write text on image #
            drawnImage.text((1, imagePosY), text, (0,0,0), font=imageFont)

        imageObject.save(SysMgr.imagePath)
        try:
            # save image as file #
            imageObject.save(SysMgr.imagePath)
        except:
            SysMgr.printErr(\
                "Fail to save image as %s\n" % SysMgr.imagePath)
            return

        try:
            fsize = \
                UtilMgr.convSize2Unit(\
                long(os.path.getsize(SysMgr.imagePath)))
        except:
            fsize = '?'
        SysMgr.printStat(\
            "saved image into %s [%s] successfully" % \
            (SysMgr.imagePath, fsize))



    @staticmethod
    def addProcBuffer(data):
        SysMgr.procBuffer.insert(0, data)
        SysMgr.procBufferSize += len(data)

        bufferSize = SysMgr.bufferSize

        while SysMgr.procBufferSize > bufferSize > 0:
            if not SysMgr.bufferOverflowed:
                SysMgr.printWarn((\
                    "New data is going to be overwritten to the buffer"
                    " because of buffer overflow\n"
                    "\tIncrease Buffer size (%s) with -b option"
                    " if you want to prevent data loss") % \
                        UtilMgr.convSize2Unit(SysMgr.bufferSize), True)
                SysMgr.bufferOverflowed = True

            if len(SysMgr.procBuffer) == 1:
                break

            SysMgr.procBufferSize -= len(SysMgr.procBuffer[-1])

            SysMgr.procBuffer.pop(-1)



    @staticmethod
    def updateSession():
        if len(SysMgr.addrListForPrint) == 0:
            return

        addrListForPrint = dict(SysMgr.addrListForPrint)
        for addr, cli in addrListForPrint.items():
            if cli.status == 'SENT' and cli.ignore > 1:
                SysMgr.printInfo(\
                    "unregistered %s:%d for PRINT" % (cli.ip, cli.port))
                del SysMgr.addrListForPrint[addr]



    @staticmethod
    def printTopStats():
        # JSON mode #
        if SysMgr.jsonOutputEnable:
            # convert dict data to JSON-type string #
            jsonObj = UtilMgr.convDict2Str(SysMgr.jsonData)
            if not jsonObj:
                SysMgr.printWarn(\
                    "Fail to convert report data to JSON type")
            else:
                SysMgr.printPipe(jsonObj)
        # realtime mode #
        elif not SysMgr.printFile:
            if not SysMgr.printStreamEnable:
                SysMgr.clearScreen()
            SysMgr.doPrint()
        # pipe mode #
        elif SysMgr.pipeEnable:
            SysMgr.doPrint(addLine=True)
        # buffered mode #
        else:
            SysMgr.addProcBuffer(SysMgr.bufferString+'\n')

        # flush buffer #
        SysMgr.clearPrint()



    @staticmethod
    def checkCutCond(newline=0):
        if SysMgr.terminalOver:
            return True
        elif not SysMgr.printFile and \
            not SysMgr.jsonOutputEnable and \
            not SysMgr.printStreamEnable and \
            SysMgr.bufferRows + newline >= \
                SysMgr.ttyRows - SysMgr.ttyRowsMargin:
            SysMgr.terminalOver = True
            SysMgr.addPrint('---more---', force=True)
            return True
        else:
            return False



    @staticmethod
    def updateTimer(interval=None):
        if interval:
            signal.alarm(long(interval))
        else:
            signal.alarm(SysMgr.intervalEnable)



    @staticmethod
    def printPipe(line='', newline=True, flush=False, pager=True):
        # check logging option #
        if SysMgr.loggingEnable:
            if SysMgr.dltEnable:
                DltAnalyzer.doLogDlt(msg=line)
            if SysMgr.kmsgEnable:
                LogMgr.doLogKmsg(msg=line)
            if SysMgr.syslogEnable:
                LogMgr.doLogSyslog(msg=line)
            if SysMgr.journalEnable:
                LogMgr.doLogJournal(msg=line)

        # socket output #
        if line and len(SysMgr.addrListForPrint) > 0:
            addrListForPrint = dict(SysMgr.addrListForPrint)
            for addr, cli in addrListForPrint.items():
                udpSeg = 65507 # maxium UDP diagram size
                start = 0
                end = udpSeg
                while 1:
                    # split by newline #
                    if len(line) >= end:
                        pos = line[start:end].rfind('\n')
                        if pos > 0:
                            end = pos + start

                    # send data #
                    ret = cli.send(line[start:end])
                    if not ret:
                        del SysMgr.addrListForPrint[addr]
                        break
                    else:
                        cli.ignore += 1

                    if end >= len(line):
                        break

                    # update sending part #
                    start = end
                    end += udpSeg

        # check print status #
        if not SysMgr.printEnable:
            return

        # convert list to string #
        if type(line) is list:
            if not line:
                line = ''
            elif line[0][-1] == '\n':
                line = ''.join(line)
            else:
                line = '\n'.join(line)

        # pager initialization #
        if not pager:
            pass
        elif SysMgr.pipeForPrint or \
            SysMgr.printFile or \
            SysMgr.printStreamEnable:
            pass
        elif not SysMgr.isTopMode() or SysMgr.isHelpMode():
            try:
                if SysMgr.isLinux:
                    if UtilMgr.which('less'):
                        #defopt = '-FRSXMQi'
                        defopt = '-FRXMQi'

                        # verify pager option support #
                        ret = os.popen(\
                            'echo | less %s 2>&1' % defopt, 'r').read()
                        if len(ret) <= 1:
                            poption = 'less %s' % defopt
                        else:
                            poption = 'less'

                        # run less as pager #
                        SysMgr.pipeForPrint = \
                            os.popen(poption, 'w')
                    elif UtilMgr.which('more'):
                        SysMgr.pipeForPrint = \
                            os.popen('more', 'w')
                elif sys.platform.startswith('win'):
                    if UtilMgr.which('more'):
                        SysMgr.pipeForPrint = \
                            os.popen('more', 'w')
                else:
                    # no supported OS #
                    SysMgr.pipeForPrint = None

                SysMgr.encodeEnable = False

                SysMgr.setPipeHandler()
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printWarn(\
                    "Fail to use pager", True, reason=True)

        # pager output #
        if SysMgr.pipeForPrint:
            try:
                if line:
                    SysMgr.pipeForPrint.write(line)

                    if newline and line[-1] != '\n':
                        SysMgr.pipeForPrint.write('\n')

                return
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "Fail to print to pager\n", True)
                SysMgr.pipeForPrint = None

        # file initialization #
        if SysMgr.printFile and \
            not SysMgr.fileForPrint:

            # profile #
            if SysMgr.isRuntimeMode():
                # dir #
                if os.path.isdir(SysMgr.printFile):
                    SysMgr.inputFile = \
                        os.path.join(SysMgr.printFile, SysMgr.outFileName)
                # file #
                else:
                    SysMgr.inputFile = SysMgr.printFile

                # append suffix to output file #
                if SysMgr.fileSuffix:
                    name, ext = os.path.splitext(\
                        os.path.basename(SysMgr.inputFile))
                    SysMgr.inputFile = \
                        '%s_%s%s' % (name, SysMgr.fileSuffix, ext)

                # append uptime to the output file #
                if not SysMgr.termFlag:
                    SysMgr.inputFile = '%s_%s' % \
                        (SysMgr.inputFile, SysMgr.getRuntime())
            # analysis #
            else:
                # dir #
                if os.path.isdir(SysMgr.printFile):
                    name, ext = os.path.splitext(\
                        os.path.basename(SysMgr.inputFile))
                    if ext == '' or ext == '.dat':
                        name = '%s.out' % name
                    if name.endswith('.dat'):
                        name = name.replace('.dat', '.out')
                    SysMgr.inputFile = \
                        os.path.join(SysMgr.printFile, name)
                # file #
                else:
                    SysMgr.inputFile = SysMgr.printFile

            # convert abnormal characters from full path #
            SysMgr.inputFile = \
                os.path.normpath(SysMgr.inputFile)

            # backup an exist file #
            if os.path.isfile(SysMgr.inputFile):
                backupFile = '%s.old' % SysMgr.inputFile

                try:
                    os.rename(SysMgr.inputFile, backupFile)
                    SysMgr.printInfo('%s is renamed to %s' % \
                        (SysMgr.inputFile, backupFile))
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printErr(\
                        "Fail to backup %s to %s" % \
                            (SysMgr.inputFile, backupFile), True)

            # open file #
            try:
                SysMgr.fileForPrint = \
                    open(SysMgr.inputFile, 'w+')

                # print file name #
                if SysMgr.printFile:
                    SysMgr.printInfo(\
                        "start writing statistics to %s" % \
                            SysMgr.inputFile)
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printOpenErr(SysMgr.inputFile)
                sys.exit(0)

        # file output #
        if SysMgr.fileForPrint:
            try:
                if line:
                    SysMgr.fileForPrint.write(line)

                    if newline and line[-1] != '\n':
                        SysMgr.fileForPrint.write('\n')

                if flush:
                    SysMgr.fileForPrint.flush()
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "Fail to write to file", True)
        # console output #
        else:
            ttyCols = SysMgr.ttyCols

            # cut output by terminal size #
            try:
                if ttyCols == 0 or SysMgr.jsonOutputEnable:
                    line = '\n'.join([nline for nline in line.split('\n')])
                else:
                    line = '\n'.join(\
                        [nline[:ttyCols-1] for nline in line.split('\n')])
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printWarn("Fail to print to console", reason=True)
                return

            # convert to extended ascii #
            nline = SysMgr.convertExtAscii(line)

            # print string to console #
            try:
                sys.stdout.write(nline)
            except SystemExit:
                sys.exit(0)
            except:
                if SysMgr.encodeEnable:
                    SysMgr.encodeEnable = False

                    sys.stdout.write(line)

            if newline:
                sys.stdout.write('\n')

            # flush buffer #
            if flush or SysMgr.remoteRun:
                sys.stdout.flush()



    @staticmethod
    def convertExtAscii(line):
        # pylint: disable=no-member
        # pylint: disable=undefined-variable
        if not SysMgr.encodeEnable:
            return line

        try:
            newline = line.replace('-------', '───────')
            newline = newline.replace('=', '═')
            newline = newline.replace('|-', '├─')
            newline = newline.replace('|', '│')

            if sys.version_info < (3, 0) and not SysMgr.encoding:
                if not sys.getdefaultencoding().lower().startswith('utf'):
                    try:
                        reload(sys)
                        sys.setdefaultencoding('utf-8')
                        SysMgr.encoding = sys.getdefaultencoding()
                    except:
                        pass

            return newline
        except:
            SysMgr.encodeEnable = False
            return line



    @staticmethod
    def printWarn(line, always=False, reason=False):
        if not SysMgr.logEnable:
            return

        if not SysMgr.warnEnable and \
            not always:
            return

        if reason:
            rstring = ' because %s' % SysMgr.getErrMsg()
        else:
            rstring = ''

        msg = ('\n%s%s%s%s%s\n' % \
            (ConfigMgr.WARNING, '[Warning] ', line, rstring, ConfigMgr.ENDC))

        if 'REMOTERUN' in os.environ:
            print(msg.replace('\n', ''))
        else:
            SysMgr.stderr.write(msg)



    @staticmethod
    def printErr(line, reason=False):
        # print backtrace #
        #SysMgr.printBacktrace()

        if not SysMgr.logEnable:
            return

        SysMgr.flushAllForPrint()

        if reason:
            rstring = ' because %s' % SysMgr.getErrMsg()
        else:
            rstring = ''

        try:
            line = line.rstrip('\n')
        except:
            pass

        msg = ('\n%s%s%s%s%s\n' % \
            (ConfigMgr.FAIL, '[Error] ', line, rstring, ConfigMgr.ENDC))

        if 'REMOTERUN' in os.environ:
            print(msg.replace('\n', ''))
        else:
            SysMgr.stderr.write(msg)



    @staticmethod
    def printInfo(line, prefix=True, suffix=True, notitle=False):
        if not SysMgr.logEnable:
            return

        if notitle:
            title = ''
        else:
            title = '[Info] '

        if prefix:
            prefix = '\n'
        else:
            prefix = ''

        if suffix:
            try:
                print('%s%s%s%s%s' % \
                    (prefix, ConfigMgr.BOLD, title, line, ConfigMgr.ENDC))
            except:
                return
        else:
            sys.stdout.write('%s%s%s%s%s' % \
                (prefix, ConfigMgr.BOLD, title, line, ConfigMgr.ENDC))
            sys.stdout.flush()



    @staticmethod
    def printGood(line):
        if not SysMgr.logEnable:
            return

        print('\n%s%s%s%s' % \
            (ConfigMgr.OKGREEN, '[Info] ', line, ConfigMgr.ENDC))



    @staticmethod
    def printLine(line):
        if not SysMgr.logEnable:
            return

        print('\n%s%s%s' % \
            (ConfigMgr.UNDERLINE, line, ConfigMgr.ENDC))



    @staticmethod
    def printStat(line):
        if not SysMgr.logEnable:
            return

        print('\n%s%s%s%s' % \
            (ConfigMgr.SPECIAL, '[Step] ', line, ConfigMgr.ENDC))



    @staticmethod
    def isEffectiveRequest(request):
        try:
            if request.startswith('EVENT_') or \
                ThreadAnalyzer.requestType.index(request):
                pass
            else:
                raise Exception()

            return True
        except SystemExit:
            sys.exit(0)
        except:
            return False



    @staticmethod
    def printOpenErr(path):
        SysMgr.printErr(\
            'Fail to open %s' % path, True)



    @staticmethod
    def printOpenWarn(path, always=False):
        SysMgr.printWarn(\
            'Fail to open %s' % path, always, reason=True)



    @staticmethod
    def parseOption(option=None):
        if not "ISMAIN" in os.environ:
            return

        if not option and SysMgr.optionList:
            return

        # parse options #
        parsedOpt = []
        previousIdx = long(0)

        # choose option #
        if option:
            optList = [sys.argv[1]] + option
        else:
            optList = sys.argv[1:]

        # parse option string #
        for idx, opt in enumerate(optList):
            if opt.startswith('-'):
                parsedOpt.append(''.join(optList[previousIdx:idx])[1:])
                previousIdx = idx

        parsedOpt.append(''.join(optList[previousIdx:])[1:])

        # save parsed option #
        SysMgr.optionList = parsedOpt[1:]

        # check double option #
        usedOpt = {}
        for opt in SysMgr.optionList:
            try:
                if not opt[0] in usedOpt:
                    usedOpt[opt[0]] = True
                    raise Exception()
            except:
                continue

            SysMgr.printErr(\
                "wrong -%s option because of redundant use" % opt[0])
            sys.exit(0)



    @staticmethod
    def findOption(option):
        if not "ISMAIN" in os.environ:
            return

        if len(sys.argv) <= 2 and not SysMgr.optionList:
            return False

        SysMgr.parseOption()

        for item in SysMgr.optionList:
            if item == '':
                pass
            elif item[0] == option:
                return True

        return False



    @staticmethod
    def getOption(option):
        if not "ISMAIN" in os.environ:
            return

        if len(sys.argv) <= 2 and not SysMgr.optionList:
            return None

        SysMgr.parseOption()

        for item in SysMgr.optionList:
            if item == '':
                pass
            elif item[0] == option and len(item[1:]) > 0:
                return item[1:]

        return None



    @staticmethod
    def parseRuntimeOption(value):
        SysMgr.countEnable = True
        convertNum = UtilMgr.convNum
        convTime = UtilMgr.convUnit2Time

        # split params #
        if value:
            repeatParams = value.split(':')

        if not value:
            SysMgr.intervalEnable = 1
            SysMgr.repeatCount = 1
            repeatParams = None
        elif len(repeatParams) == 2 or len(repeatParams) == 3:
            try:
                # get interval #
                interval = SysMgr.getOption('i')
                if interval:
                    interval = long(interval)
                else:
                    interval = convTime(repeatParams[0])

                SysMgr.intervalEnable = interval
                SysMgr.repeatInterval = interval

                # get count #
                if repeatParams[1] == '':
                    SysMgr.repeatCount = sys.maxsize
                else:
                    SysMgr.repeatCount = \
                        long(convTime(repeatParams[1]) / interval)
            except:
                SysMgr.printErr((\
                    "wrong option value with -R because %s, "
                    "input integer values") % SysMgr.getErrMsg())
                sys.exit(0)
        elif len(repeatParams) == 1:
            try:
                interval = long(convTime(repeatParams[0]))

                # top mode #
                if SysMgr.isTopMode():
                    ival = SysMgr.getOption('i')
                    if ival:
                        ival = long(ival)
                        interval = long(interval / ival)
                        SysMgr.repeatCount = interval
                        SysMgr.repeatInterval = interval
                        SysMgr.intervalEnable = ival
                    else:
                        SysMgr.repeatCount = interval
                        SysMgr.repeatInterval = interval
                        SysMgr.intervalEnable = 1
                # record mode #
                else:
                    SysMgr.repeatCount = 1
                    SysMgr.repeatInterval = interval
                    SysMgr.intervalEnable = interval
            except:
                SysMgr.printErr((\
                    "wrong option value with -R because %s, "
                    "input integer values") % SysMgr.getErrMsg())
                sys.exit(0)
        else:
            SysMgr.printErr((\
                "wrong option value with -R because %s, "
                "input in the format INTERVAL:REPEAT") % \
                    SysMgr.getErrMsg())
            sys.exit(0)

        # check variables #
        if not SysMgr.intervalEnable or \
            SysMgr.intervalEnable < 1 or \
            SysMgr.repeatCount < 1:
            SysMgr.printErr(\
                "wrong option value with -R, input values bigger than 0")
            sys.exit(0)

        # get termination flag #
        if repeatParams and len(repeatParams) == 3:
            SysMgr.termFlag = False
            SysMgr.printInfo(\
                "run every %s sec %s time" % \
                (convertNum(SysMgr.intervalEnable), \
                convertNum(SysMgr.repeatCount)))
        else:
            interval = SysMgr.intervalEnable
            repeat = SysMgr.repeatCount
            totalSec = convertNum(interval)
            totalCnt = convertNum(repeat)
            totalTime = convertNum(long(interval * repeat))
            SysMgr.printInfo(\
                "run only %s times in %s sec for a total of %s sec" %
                    (totalCnt, totalSec, totalTime))



    @staticmethod
    def reloadFileBuffer(path=None):
        if path:
            try:
                fd = open(path, 'r')
            except:
                SysMgr.printOpenErr(path)
                sys.exit(0)
        else:
            fd = SysMgr.fileForPrint

        try:
            fd.seek(0, 0)
            SysMgr.procBuffer = \
                fd.read().replace('\n\n', 'NEWSTAT\n\n')
            SysMgr.procBuffer = \
                SysMgr.procBuffer.split('NEWSTAT')
            fd.seek(0, 0)
            fd.truncate()
        except:
            return



    @staticmethod
    def applySaveOption(value=None):
        # apply default path #
        if value == '':
            value = '.'

        # change output path #
        try:
            if SysMgr.isWritable(value):
                if os.path.isdir(value):
                    SysMgr.outputFile = \
                        '%s/guider.dat' % value
                else:
                    SysMgr.outputFile = value
            else:
                raise Exception()
        except:
            SysMgr.printErr(\
                "wrong path %s with -s option because of permission" % value)
            sys.exit(0)

        # remove double slashs #
        SysMgr.outputFile = \
            os.path.normpath(SysMgr.outputFile)

        # support no-report record mode #
        if SysMgr.isFileRecordMode() or \
            SysMgr.findOption('F') or \
            SysMgr.isGeneralRecordMode() or \
            SysMgr.findOption('y'):
            if SysMgr.outputFile.endswith('.dat'):
                SysMgr.printFile = '%s.out' % \
                    os.path.splitext(SysMgr.outputFile)[0]
            else:
                SysMgr.printFile = \
                    SysMgr.outputFile



    @staticmethod
    def removeOptionArgs():
        if len(sys.argv) < 3:
            return

        # find first option args #
        firstOptIdx = None
        for idx, item in enumerate(sys.argv):
            if item.startswith('-'):
                firstOptIdx = idx
                break

        # update args #
        if firstOptIdx:
            sys.argv = sys.argv[:firstOptIdx]



    @staticmethod
    def parseAnalOption(option=None):
        if not "ISMAIN" in os.environ:
            return

        # check call history #
        if not option and SysMgr.parsedAnalOption:
            return
        else:
            SysMgr.parsedAnalOption = True

        # set default processor option #
        if SysMgr.isTopMode():
            if SysMgr.findOption('a') or \
                SysMgr.isDrawMode():
                SysMgr.cpuEnable = True
                SysMgr.gpuEnable = True
            else:
                SysMgr.cpuEnable = False

        # check argument count #
        if option:
            optionList = option.split()
        elif len(sys.argv) <= 2:
            return
        else:
            optionList = None

        SysMgr.parseOption(optionList)

        for item in SysMgr.optionList:
            if item == '':
                continue

            option = item[0]
            value = item[1:]

            if option == 'i':
                # set default interval #
                if len(value) == 0:
                    SysMgr.intervalEnable = 1
                    continue

                try:
                    SysMgr.intervalEnable = long(value)

                    if SysMgr.intervalEnable <= 0:
                        SysMgr.printErr(\
                            "wrong option value with -i option, "
                            "input number bigger than 0")
                        sys.exit(0)
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printErr(\
                        "wrong option value with -i option, "
                        "input number in integer format")
                    sys.exit(0)

            elif option == 'o':
                # apply default path #
                if value == '':
                    value = '.'

                # check writable access #
                if not SysMgr.isWritable(value):
                    SysMgr.printErr((\
                        "wrong path %s with -o option "
                        "because of permission") % value)
                    sys.exit(0)

                SysMgr.printFile = os.path.normpath(value)

            elif option == 'I':
                SysMgr.inputParam = value

            elif option == 'f':
                SysMgr.forceEnable = True

            elif option == 'C':
                if not ConfigMgr.confData:
                    if not value:
                        value = SysMgr.confFileName
                    ret = SysMgr.loadConfig(value)
                    if not ret:
                        sys.exit(0)

            elif option == 'L':
                SysMgr.layout = value
                if len(value) == 0:
                    SysMgr.printErr("no option value with -L option")
                    sys.exit(0)

            elif option == 'w':
                SysMgr.rcmdList = \
                    SysMgr.parseCustomRecordCmd(value)

            elif option == 'a':
                SysMgr.showAll = True

            elif option == 'D':
                SysMgr.depEnable = True

            elif option == 'P':
                pfilter = SysMgr.getOption('g')
                if not pfilter:
                    SysMgr.printErr((\
                        "wrong option with -P, "
                        "use -g option to group threads in a same process"))
                    sys.exit(0)

                SysMgr.groupProcEnable = True

            elif option == 'p':
                if not SysMgr.isThreadRecordMode():
                    pass
                elif SysMgr.findOption('i'):
                    SysMgr.printErr(\
                        "wrong option with -p, -i option is already used")
                    sys.exit(0)
                elif SysMgr.findOption('g'):
                    SysMgr.printErr(\
                        "wrong option with -p, -g option is already used")
                    sys.exit(0)
                else:
                    SysMgr.preemptGroup = value.split(',')
                    SysMgr.preemptGroup = \
                        SysMgr.clearList(SysMgr.preemptGroup)

                    if len(SysMgr.preemptGroup) == 0:
                        SysMgr.printErr((\
                            "No specific thread targeted, "
                            "input TID with -p option"))
                        sys.exit(0)

            elif option == 'Y':
                if not SysMgr.prio:
                    SysMgr.parsePriorityOption(value)

            elif option == 'z':
                SysMgr.parseAffinityOption(value.split(','))

            elif option == 'J':
                SysMgr.jsonOutputEnable = True

            elif option == 'k':
                if not SysMgr.isKillMode():
                    SysMgr.parseKillOption(value)

            elif option == 'd':
                options = value

                if 'p' in options:
                    SysMgr.printEnable = False

                if 'u' in options:
                    SysMgr.userEnable = False

                if 'c' in options:
                    SysMgr.cpuEnable = False

                if 't' in options:
                    SysMgr.truncEnable = False

                if 'e' in options:
                    SysMgr.encodeEnable = False

                if 'a' in options:
                    SysMgr.freeMemEnable = True

                if 'G' in options:
                    SysMgr.gpuEnable = False

                if 'A' in options:
                    SysMgr.cpuAvrEnable = False

                if 'L' in options:
                    SysMgr.logEnable = False

                if 'T' in options:
                    SysMgr.taskEnable = False

            elif option == 'c':
                itemList = UtilMgr.parseInputString(value)

                # set union option #
                if SysMgr.isTraceMode():
                    union = False
                else:
                    union = True

                SysMgr.customCmd = SysMgr.clearList(itemList, union=union)

            elif option == 'g':
                itemList = UtilMgr.parseInputString(value)
                SysMgr.filterGroup = SysMgr.clearList(itemList)

            elif option == 'A':
                SysMgr.archOption = value
                SysMgr.setArch(value)

            elif option == 'E':
                SysMgr.cacheDirPath = value
                SysMgr.printInfo(\
                    "use %s as cache directory" % value)

            elif option == 's':
                SysMgr.applySaveOption(value)

            elif option == 'e':
                options = value

                if 'g' in options:
                    SysMgr.graphEnable = True

                if 't' in options:
                    SysMgr.processEnable = False

                if 'D' in options:
                    SysMgr.loggingEnable = True
                    SysMgr.dltEnable = True

                if 'k' in options:
                    SysMgr.loggingEnable = True
                    SysMgr.kmsgEnable = True

                if 'j' in options:
                    SysMgr.loggingEnable = True
                    SysMgr.journalEnable = True

                if 'H' in options:
                    if not SysMgr.isThreadTopMode():
                        SysMgr.printErr(\
                            "sched option is supported only in thread mode")
                        sys.exit(0)
                    SysMgr.schedEnable = True

                if 'y' in options:
                    SysMgr.loggingEnable = True
                    SysMgr.syslogEnable = True

                if 'Y' in options:
                    SysMgr.delayEnable = True

                # no more options except for top mode #
                if not SysMgr.isTopMode():
                    continue

                if 'c' in options:
                    SysMgr.cpuEnable = True

                if 'p' in options:
                    SysMgr.pipeEnable = True

                if 'P' in options:
                    SysMgr.perfEnable = True
                    if SysMgr.findOption('g'):
                        SysMgr.perfGroupEnable = True

                if 'i' in options:
                    SysMgr.irqEnable = True

                if 'b' in options:
                    if SysMgr.checkDiskTopCond():
                        SysMgr.blockEnable = True
                    else:
                        sys.exit(0)

                if 's' in options:
                    if SysMgr.checkStackTopCond():
                        SysMgr.stackEnable = True
                    else:
                        sys.exit(0)

                if 'S' in options:
                    SysMgr.checkPerm()
                    SysMgr.pssEnable = True
                    SysMgr.sort = 'm'

                if 'u' in options:
                    SysMgr.checkPerm()
                    SysMgr.ussEnable = True
                    SysMgr.sort = 'm'

                if 'L' in options:
                    SysMgr.cmdlineEnable = True

                # check last field #
                if 'a' in options:
                    ThreadAnalyzer.setLastField('affinity')
                elif 'o' in options:
                    ThreadAnalyzer.setLastField('oom')
                elif 'W' in options:
                    ThreadAnalyzer.setLastField('wchan')
                elif 'h' in options:
                    ThreadAnalyzer.setLastField('signal')

                if 'f' in options:
                    SysMgr.floatEnable = True

                    # set default interval to 3 for accuracy #
                    if not SysMgr.findOption('i') and \
                        not SysMgr.findOption('R'):
                        SysMgr.intervalEnable = 3

                if 'F' in options:
                    SysMgr.wfcEnable = True

                if 'R' in options:
                    SysMgr.reportEnable = True
                    SysMgr.reportFileEnable = True

                if 'e' in options:
                    SysMgr.encodeEnable = True

                if 'm' in options:
                    if SysMgr.checkMemTopCond():
                        SysMgr.memEnable = True
                    else:
                        sys.exit(0)

                if 'w' in options:
                    if SysMgr.checkWssTopCond():
                        SysMgr.memEnable = True
                        SysMgr.wssEnable = True
                        SysMgr.sort = 'm'
                    else:
                        sys.exit(0)

                if 'n' in options:
                    SysMgr.networkEnable = True

                if 'N' in options:
                    SysMgr.nsEnable = True

                if 'P' in options:
                    if SysMgr.checkPerfTopCond():
                        SysMgr.perfEnable = True
                        if SysMgr.findOption('g'):
                            SysMgr.perfGroupEnable = True
                    else:
                        sys.exit(0)

                if 'r' in options:
                    SysMgr.reportEnable = True

                if 'd' in options:
                    SysMgr.diskEnable = True

                if 'E' in options:
                    SysMgr.reportEnable = True
                    SysMgr.elasticEnable = True

                if 'C' in options:
                    SysMgr.cgroupEnable = True

                if 'q' in options:
                    SysMgr.exitFlag = True

                if not SysMgr.isEffectiveEnableOption(options):
                    SysMgr.printErr(\
                        "unrecognized option -%s to enable" % options)
                    sys.exit(0)

            elif SysMgr.isFunctionMode():
                SysMgr.functionEnable = True

            elif option == 'l':
                if SysMgr.isDrawMode():
                    SysMgr.boundaryLine = value.split(',')
                    SysMgr.printInfo(\
                        "set %s as a boundary line" % \
                        ', '.join(SysMgr.boundaryLine))
                elif SysMgr.isKillMode():
                    pass
                else:
                    SysMgr.addr2linePath = value.split(',')

                    SysMgr.printInfo(\
                        "use %s as addr2line path" % \
                        ', '.join(SysMgr.addr2linePath))

            elif option == 'r':
                SysMgr.rootPath = value

            elif option == 'T':
                if SysMgr.isConvertMode():
                    if not value:
                        SysMgr.printErr(\
                            "wrong option value with -T option, "
                            "input path for font")
                        sys.exit(0)
                    SysMgr.fontPath = value
                elif SysMgr.isDrawMode():
                    try:
                        SysMgr.nrTop = long(value)
                    except:
                        SysMgr.printErr(\
                            "wrong option value with -T option, "
                            "input number in integer format")
                        sys.exit(0)

            elif option == 'O':
                SysMgr.perCoreList = value.split(',')
                SysMgr.perCoreList = \
                    SysMgr.clearList(SysMgr.perCoreList)
                if len(SysMgr.perCoreList) == 0:
                    SysMgr.printErr(\
                        "Input value for filter with -O option")
                    sys.exit(0)

                for item in SysMgr.perCoreList:
                    if not item.isdigit():
                        SysMgr.printErr(\
                            "wrong option value with -O option, "
                            "input number in integer format")
                        sys.exit(0)

                SysMgr.printInfo(\
                    "only specific cores [ %s ] are shown" % \
                    ', '.join(SysMgr.perCoreList))

                SysMgr.perCoreList = \
                    list(map(long, SysMgr.perCoreList))

            elif option == 't' and \
                not SysMgr.isRecordMode() and \
                not SysMgr.isDrawMode():
                SysMgr.syscallList = value.split(',')
                SysMgr.syscallList = \
                    SysMgr.clearList(SysMgr.syscallList)
                enabledSyscall = []

                for val in SysMgr.syscallList:
                    try:
                        if val[0:4] == 'sys_':
                            nrSyscall = ConfigMgr.sysList.index(val)
                        else:
                            nrSyscall = \
                                ConfigMgr.sysList.index('sys_%s' % val)

                        enabledSyscall.append(ConfigMgr.sysList[nrSyscall])
                        sidx = SysMgr.syscallList.index(val)
                        SysMgr.syscallList[sidx] = nrSyscall
                    except SystemExit:
                        sys.exit(0)
                    except:
                        SysMgr.printErr(\
                            "No %s syscall in %s ABI" % \
                            (val, SysMgr.arch))
                        sys.exit(0)

                if len(enabledSyscall) == 0:
                    SysMgr.printInfo("enabled syscall list [ ALL ]")
                else:
                    SysMgr.printInfo(\
                        "enabled syscall list [ %s ]" % \
                        ', '.join(enabledSyscall))

            elif option == 'm':
                try:
                    SysMgr.ttyEnable = True

                    if len(value) == 0:
                        SysMgr.setTtyAuto()
                    else:
                        rows = cols = long(0)
                        term = value.split(':')
                        if len(term) == 2:
                            if term[0].isdigit():
                                rows = long(term[0])
                            if term[1].isdigit():
                                cols = long(term[1])
                            SysMgr.setTty(rows, cols)
                        else:
                            raise Exception()
                except:
                    SysMgr.printErr(\
                        "wrong option value with -m option, "
                        "input number in COLS:ROWS format")
                    sys.exit(0)

            elif option == 'b' and \
                not SysMgr.isRecordMode():
                try:
                    bsize = long(value)
                    if bsize >= 0:
                        SysMgr.bufferSize = str(value)

                        if bsize == 0:
                            SysMgr.printInfo(\
                                "set buffer size to unlimited")
                        else:
                            SysMgr.printInfo(\
                                "set buffer size to %sKB" % bsize)
                    else:
                        SysMgr.printErr(\
                            "wrong option value with -b option, "
                            "input number bigger than 0")
                        sys.exit(0)
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printErr(\
                            "wrong option value with -b option, "
                            "input number in integer format")
                    sys.exit(0)

            elif option == 'N':
                networkList = value.split(',')
                networkList = SysMgr.clearList(networkList)
                for item in networkList:
                    service, ip, port = NetworkMgr.parseAddr(item)
                    NetworkMgr.setRemoteNetwork(service, ip, port)

            elif option == 'j':
                if not SysMgr.checkReportTopCond(value):
                    sys.exit(0)

            elif option == 'x':
                service, ip, port = NetworkMgr.parseAddr(value)

                NetworkMgr.setServerNetwork(ip, port)

            elif option == 'X':
                if not SysMgr.findOption('x'):
                    service, ip, port = NetworkMgr.parseAddr(value)
                    NetworkMgr.setServerNetwork(None, None)

                NetworkMgr.setRemoteServer(value)

            elif option == 'S':
                if not SysMgr.setSortValue(value):
                    sys.exit(0)

            elif option == 'u':
                SysMgr.runBackgroundMode()

            elif option == 'Q':
                SysMgr.printStreamEnable = True

            elif option == 'H':
                try:
                    if not value:
                        SysMgr.funcDepth = 32
                    else:
                        SysMgr.funcDepth = long(value)

                    if SysMgr.funcDepth < 0:
                        raise Exception()
                except:
                    SysMgr.printErr(\
                        "wrong option value with -H option, "
                        "input an unsigned integer value")
                    sys.exit(0)

            elif option == 'R':
                SysMgr.parseRuntimeOption(value)

            # Ignore options #
            elif SysMgr.isEffectiveOption(option):
                continue

            else:
                SysMgr.printErr(\
                    "unrecognized option -%s for analysis" % option)
                sys.exit(0)

    @staticmethod
    def parseRecordOption():
        if not "ISMAIN" in os.environ:
            return

        if len(sys.argv) <= 2:
            return

        SysMgr.parseOption()

        for item in SysMgr.optionList:
            try:
                option = item[0]
                value = item[1:]
            except:
                continue

            if option == 'b':
                try:
                    bsize = long(value)
                    if bsize > 0:
                        SysMgr.bufferSize = str(value)

                        SysMgr.printInfo(\
                            "set buffer size to %sKB" % bsize)
                    else:
                        SysMgr.printErr(\
                            "wrong option value with -b option, "
                            "input number bigger than 0")
                        sys.exit(0)
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printErr(\
                        "wrong option value with -b option, "
                        "input number in integer format")
                    sys.exit(0)

            elif option == 'Y':
                SysMgr.parsePriorityOption(value)

            elif option == 'z':
                SysMgr.parseAffinityOption(value.split(','))

            elif option == 'f':
                SysMgr.forceEnable = True

            elif option == 'u':
                SysMgr.runBackgroundMode()

            elif option == 'y':
                SysMgr.systemEnable = True

            elif option == 'A':
                SysMgr.archOption = value
                SysMgr.setArch(value)

            elif option == 'C':
                if not value:
                    value = SysMgr.confFileName
                ret = SysMgr.loadConfig(value)
                if not ret:
                    sys.exit(0)

            elif option == 'E':
                SysMgr.cacheDirPath = value
                SysMgr.printInfo(\
                    "use %s as cache directory" % value)

            elif option == 'e':
                options = value
                if 'i' in options:
                    SysMgr.irqEnable = True

                if 'm' in options:
                    SysMgr.memEnable = True

                if 'n' in options:
                    SysMgr.networkEnable = True

                if 'h' in options:
                    SysMgr.heapEnable = True

                if 'b' in options:
                    SysMgr.blockEnable = True

                if 'p' in options:
                    SysMgr.pipeEnable = True

                if 'P' in options:
                    SysMgr.powerEnable = True

                if 'r' in options:
                    SysMgr.resetEnable = True

                if 'g' in options:
                    SysMgr.graphEnable = True

                if 'L' in options:
                    SysMgr.lockEnable = True

                if 'c' in options:
                    SysMgr.cgroupEnable = True

                if not SysMgr.isEffectiveEnableOption(options):
                    SysMgr.printErr(\
                        "unrecognized option -%s to enable" % options)
                    sys.exit(0)

            elif option == 'g':
                itemList = UtilMgr.parseInputString(value)
                SysMgr.filterGroup = SysMgr.clearList(itemList)
                if len(SysMgr.filterGroup) == 0:
                    SysMgr.printErr(\
                        "Input value for filter with -g option")
                    sys.exit(0)

                SysMgr.printInfo(\
                    "only specific threads [ %s ] are recorded" % \
                    ', '.join(SysMgr.filterGroup))

            elif option == 's':
                SysMgr.applySaveOption(value)

            elif option == 'D':
                SysMgr.depEnable = True

            elif option == 'Q':
                SysMgr.printStreamEnable = True

            elif option == 'H':
                try:
                    if not value:
                        SysMgr.funcDepth = 32
                    else:
                        SysMgr.funcDepth = long(value)

                    if SysMgr.funcDepth < 0:
                        raise Exception()
                except:
                    SysMgr.printErr(\
                        "wrong option value with -H option, "
                        "input an unsigned integer value")
                    sys.exit(0)

            elif option == 'W':
                SysMgr.waitEnable = True

            elif option == 'w':
                SysMgr.rcmdList = \
                    SysMgr.parseCustomRecordCmd(value)

            elif option == 'U':
                SysMgr.ueventEnable = True
                itemList = UtilMgr.parseInputString(value)
                SysMgr.userCmd = SysMgr.clearList(itemList)

            elif option == 'K':
                SysMgr.keventEnable = True
                itemList = UtilMgr.parseInputString(value)
                SysMgr.kernelCmd = SysMgr.clearList(itemList)

            elif option == 'M':
                SysMgr.objdumpPath = value

                SysMgr.printInfo(\
                    "use %s as objdump path" % SysMgr.objdumpPath)

            elif option == 'F':
                SysMgr.fileEnable = True

            elif option == 'B':
                # get output path #
                if len(value) == 0:
                    value = SysMgr.cmdFileName

                # change output path #
                try:
                    if SysMgr.isWritable(value):
                        if os.path.isdir(value):
                            SysMgr.cmdEnable = \
                                '%s/%s' % (value, SysMgr.cmdFileName)
                        else:
                            SysMgr.cmdEnable = value
                    else:
                        raise Exception()
                except:
                    SysMgr.printErr(\
                        "wrong option value %s with -B option" % value)
                    sys.exit(0)

                # remove double slashs #
                SysMgr.cmdEnable = \
                    os.path.normpath(SysMgr.cmdEnable)

            elif option == 't':
                SysMgr.sysEnable = True
                SysMgr.syscallList = value.split(',')
                SysMgr.syscallList = \
                    SysMgr.clearList(SysMgr.syscallList)
                enabledSyscall = []

                for val in SysMgr.syscallList:
                    try:
                        if val[0:4] == 'sys_':
                            nrSyscall = ConfigMgr.sysList.index(val)
                        else:
                            nrSyscall = \
                                ConfigMgr.sysList.index('sys_%s' % val)

                        enabledSyscall.append(\
                            ConfigMgr.sysList[nrSyscall])
                        sidx = SysMgr.syscallList.index(val)
                        SysMgr.syscallList[sidx] = nrSyscall
                    except SystemExit:
                        sys.exit(0)
                    except:
                        SysMgr.printErr(\
                            "No %s syscall in %s ABI" % \
                            (val, SysMgr.arch))
                        sys.exit(0)

                if len(enabledSyscall) == 0:
                    SysMgr.printInfo("enabled syscall list [ ALL ]")
                else:
                    SysMgr.printInfo(\
                        "enabled syscall list [ %s ]" % \
                        ', '.join(enabledSyscall))

            elif option == 'R':
                SysMgr.parseRuntimeOption(value)

            elif option == 'o':
                # apply default path #
                if value == '':
                    value = '.'

                SysMgr.printFile = str(value)
                if len(SysMgr.printFile) == 0:
                    SysMgr.printErr(\
                        "No option value with -o option")
                    sys.exit(0)

            elif option == 'c':
                itemList = UtilMgr.parseInputString(value)
                SysMgr.customCmd = SysMgr.clearList(itemList)
                if len(SysMgr.customCmd) == 0:
                    SysMgr.printErr(\
                        "Fail to recognize custom events")
                    sys.exit(0)

            elif option == 'd':
                options = value

                if 'c' in options:
                    SysMgr.cpuEnable = False
                    SysMgr.latEnable = False

                if 'm' in options:
                    SysMgr.memEnable = False

                if 'h' in options:
                    SysMgr.heapEnable = False

                if 'b' in options:
                    SysMgr.blockEnable = False

                if 'u' in options:
                    SysMgr.userEnable = False

                if 'p' in options:
                    SysMgr.printEnable = False

                if 'l' in options:
                    SysMgr.latEnable = False

                if 'L' in options:
                    SysMgr.logEnable = False

                if 'a' in options:
                    SysMgr.disableAll = True

                if 'C' in options:
                    SysMgr.compressEnable = False

            # Ignore options #
            elif SysMgr.isEffectiveOption(option):
                continue

            else:
                SysMgr.printErr(\
                    "unrecognized option -%s for recording" % option)
                sys.exit(0)



    @staticmethod
    def makeKerSymTable(symbol):
        restPath = '%s/sys/kernel/kptr_restrict' % SysMgr.procPath
        try:
            with open(restPath, 'w+') as fd:
                fd.write('0')
        except:
            pass

        symPath = '%s/kallsyms' % SysMgr.procPath
        try:
            f = open(symPath, 'r')
        except IOError:
            SysMgr.printOpenWarn(symPath)

        ret = None
        startPos = len(SysMgr.kerSymTable)
        curPos = long(0)

        while 1:
            line = f.readline()
            curPos += 1

            if startPos > curPos:
                continue

            # Cache address and symbol #
            line = line.split()
            SysMgr.kerSymTable[line[2]] = line[0]

            if line[2] == symbol:
                ret = line[0]
                break

        f.close()
        return ret



    @staticmethod
    def getKerAddr(symbol):
        try:
            return SysMgr.kerSymTable[symbol]
        except:
            return SysMgr.makeKerSymTable(symbol)



    @staticmethod
    def isRecordMode():
        if SysMgr.isThreadRecordMode() or \
            SysMgr.isFuncRecordMode() or \
            SysMgr.isFileRecordMode() or \
            SysMgr.isSyscallRecordMode() or \
            SysMgr.isGeneralRecordMode():
            return True
        else:
            return False



    @staticmethod
    def isThreadRecordMode():
        if len(sys.argv) > 1 and \
            (sys.argv[1] == 'record' or \
            sys.argv[1] == 'rec'):
            return True
        else:
            return False



    @staticmethod
    def isFuncRecordMode():
        if len(sys.argv) > 1 and \
            (sys.argv[1] == 'funcrecord' or \
            sys.argv[1] == 'funcrec'):
            return True
        else:
            return False



    @staticmethod
    def isFileRecordMode():
        if len(sys.argv) > 1 and \
            (sys.argv[1] == 'filerecord' or \
            sys.argv[1] == 'filerec'):
            return True
        else:
            return False



    @staticmethod
    def isSyscallRecordMode():
        if len(sys.argv) > 1 and \
            (sys.argv[1] == 'sysrecord' or \
            sys.argv[1] == 'sysrec'):
            return True
        else:
            return False



    @staticmethod
    def isGeneralRecordMode():
        if len(sys.argv) > 1 and \
            (sys.argv[1] == 'genrecord' or \
            sys.argv[1] == 'genrec'):
            return True
        else:
            return False



    @staticmethod
    def isStartMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'start':
            return True
        else:
            return False


    @staticmethod
    def isServerMode():
        if len(sys.argv) > 1 and \
            (sys.argv[1] == 'server' or \
            sys.argv[1] == 'serv'):
            return True
        else:
            return False



    @staticmethod
    def isHelpMode():
        if '-help' in sys.argv or \
            '--help' in sys.argv or \
            '-h' in sys.argv or \
            (len(sys.argv) > 1 and sys.argv[1] == 'help'):
            return True
        else:
            return False



    @staticmethod
    def isClientMode():
        if len(sys.argv) > 1 and \
            (sys.argv[1] == 'client' or \
            sys.argv[1] == 'cli'):
            return True
        else:
            return False



    @staticmethod
    def isListMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'list':
            return True
        else:
            return False



    @staticmethod
    def isStopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'stop':
            return True
        else:
            return False



    @staticmethod
    def isTkillMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'tkill':
            return True
        else:
            return False



    @staticmethod
    def isKillMode():
        if len(sys.argv) < 2:
            return False
        elif sys.argv[1] == 'kill' or \
            sys.argv[1] == 'send' or \
            SysMgr.isTkillMode():
            return True
        else:
            return False



    @staticmethod
    def isCpuTestMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'cputest':
            return True
        else:
            return False



    @staticmethod
    def isIoTestMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'iotest':
            return True
        else:
            return False



    @staticmethod
    def isNetTestMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'nettest':
            return True
        else:
            return False



    @staticmethod
    def isMemTestMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'memtest':
            return True
        else:
            return False



    @staticmethod
    def isSetSchedMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'setsched':
            return True
        else:
            return False



    @staticmethod
    def isConvertMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'convert':
            return True
        else:
            return False



    @staticmethod
    def isStraceMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'strace':
            return True
        else:
            return False



    @staticmethod
    def isUtraceMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'utrace':
            return True
        else:
            return False



    @staticmethod
    def isRemoteMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'remote':
            return True
        else:
            return False



    @staticmethod
    def isBtraceMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'btrace':
            return True
        else:
            return False



    @staticmethod
    def isSigtraceMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'sigtrace':
            return True
        else:
            return False



    @staticmethod
    def isPrintEnvMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'printenv':
            return True
        else:
            return False



    @staticmethod
    def isPrintNsMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'printns':
            return True
        else:
            return False



    @staticmethod
    def isPrintSvcMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'printsvc':
            return True
        else:
            return False



    @staticmethod
    def isPrintInfoMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'printinfo':
            return True
        else:
            return False



    @staticmethod
    def isSetAffinityMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'setafnt':
            return True
        else:
            return False



    @staticmethod
    def isGetAffinityMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'getafnt':
            return True
        else:
            return False



    @staticmethod
    def isPstreeMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'pstree':
            return True
        else:
            return False



    @staticmethod
    def isSystatMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'systat':
            return True
        else:
            return False



    @staticmethod
    def isLimitCpuMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'limitcpu':
            return True
        else:
            return False



    @staticmethod
    def isSetCpuMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'setcpu':
            return True
        else:
            return False



    @staticmethod
    def isPerfTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'perftop':
            return True
        else:
            return False



    @staticmethod
    def isMemTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'memtop':
            return True
        else:
            return False



    @staticmethod
    def isWssTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'wsstop':
            return True
        else:
            return False



    @staticmethod
    def isBgTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'bgtop':
            return True
        else:
            return False



    @staticmethod
    def isSystemTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'smtop':
            return True
        else:
            return False



    @staticmethod
    def isDiskTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'disktop':
            return True
        else:
            return False



    @staticmethod
    def isDltTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'dlttop':
            return True
        else:
            return False



    @staticmethod
    def isDbusTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'dbustop':
            return True
        else:
            return False



    @staticmethod
    def isUserTopMode():
        if len(sys.argv) > 1 and \
            (sys.argv[1] == 'usertop' or sys.argv[1] == 'utop'):
            return True
        else:
            return False



    @staticmethod
    def isBrkTopMode():
        if len(sys.argv) > 1 and \
            (sys.argv[1] == 'brktop' or sys.argv[1] == 'btop'):
            return True
        else:
            return False



    @staticmethod
    def isSysTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'systop':
            return True
        else:
            return False



    @staticmethod
    def isNetTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'nettop':
            return True
        else:
            return False



    @staticmethod
    def isStackTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'stacktop':
            return True
        else:
            return False



    @staticmethod
    def isFileTopMode():
        if len(sys.argv) > 1 and \
            (sys.argv[1] == 'filetop' or \
            sys.argv[1] == 'ftop'):
            return True
        else:
            return False



    @staticmethod
    def isReportTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'reptop':
            return True
        else:
            return False



    @staticmethod
    def isProcTopMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'top':
            return True
        else:
            return False



    @staticmethod
    def isThreadTopMode():
        if len(sys.argv) > 1 and \
            (sys.argv[1] == 'threadtop' or \
            sys.argv[1] == 'ttop'):
            return True
        else:
            return False



    @staticmethod
    def isWritable(value):
        # file exist #
        if os.access(value, os.F_OK):
            if not os.access(value, os.W_OK):
                return False
        # no file exist #
        else:
            dirPath = os.path.dirname(value)
            if not dirPath:
                dirPath = '.'

            # no dir exist #
            if not os.path.isdir(dirPath):
                return False
            # dir is not writable #
            elif not os.access(dirPath, os.W_OK):
                return False

        return True



    @staticmethod
    def isReportMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'report':
            return True
        else:
            return False



    @staticmethod
    def isTopMode():
        if SysMgr.isProcTopMode() or \
            SysMgr.isFileTopMode() or \
            SysMgr.isThreadTopMode() or \
            SysMgr.isStackTopMode() or \
            SysMgr.isPerfTopMode() or \
            SysMgr.isMemTopMode() or \
            SysMgr.isWssTopMode() or \
            SysMgr.isReportTopMode() or \
            SysMgr.isBgTopMode() or \
            SysMgr.isSystemTopMode() or \
            SysMgr.isNetTopMode() or \
            SysMgr.isUserTopMode() or \
            SysMgr.isBrkTopMode() or \
            SysMgr.isSysTopMode() or \
            SysMgr.isDltTopMode() or \
            SysMgr.isDbusTopMode() or \
            SysMgr.isDiskTopMode():
            return True
        else:
            return False



    @staticmethod
    def isTraceMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'trace':
            return True
        elif SysMgr.isStraceMode() or \
            SysMgr.isUtraceMode() or \
            SysMgr.isBtraceMode() or \
            SysMgr.isRemoteMode() or \
            SysMgr.isSigtraceMode():
            return True
        else:
            return False



    @staticmethod
    def isRuntimeMode():
        if SysMgr.isRecordMode() or \
            SysMgr.isTopMode() or \
            SysMgr.isTraceMode():
            return True

        return False



    @staticmethod
    def checkCmdMode():
        # parse options #
        SysMgr.parseAnalOption()

        # LIST MODE #
        if SysMgr.isListMode():
            SysMgr.printBgProcs()

        # SERVER MODE #
        elif SysMgr.isServerMode():
            SysMgr.runServerMode()

        # CLIENT MODE #
        elif SysMgr.isClientMode():
            SysMgr.runClientMode()

        # START / STOP MODE #
        elif SysMgr.isStartMode() or \
            SysMgr.isStopMode():
            # make list of arguments #
            if len(sys.argv) > 2:
                argList = sys.argv[2:]
            else:
                argList = None

            SysMgr.sendSignalProcs(signal.SIGINT, argList)

        # KILL MODE #
        elif SysMgr.isKillMode():
            # make list of arguments #
            if len(sys.argv) > 2:
                argList = sys.argv[2:]
            else:
                argList = [' ']

            # print signal list #
            if SysMgr.findOption('l'):
                for idx, sig in enumerate(ConfigMgr.SIG_LIST):
                    if idx == 0:
                        continue
                    elif idx % 5 == 0:
                        newline = True
                    else:
                        newline = False
                    SysMgr.printPipe(\
                        "{0:>2}) {1:<12}".format(idx, sig), newline=newline)
                sys.exit(0)

            if SysMgr.isTkillMode():
                SysMgr.sendSignalArgs(argList, isThread=True)
            else:
                SysMgr.sendSignalArgs(argList)

        # TOPDIFF MODE #
        elif SysMgr.isTopDiffMode():
            # remove option args #
            SysMgr.removeOptionArgs()

            # make list of arguments #
            if len(sys.argv) > 2:
                argList = sys.argv[2:]
            else:
                argList = None

            SysMgr.printLogo(big=True, onlyFile=True)

            ThreadAnalyzer.doDiffReports(argList)

        # TOPSUM MODE #
        elif SysMgr.isTopSumMode():
            # remove option args #
            SysMgr.removeOptionArgs()

            # make list of arguments #
            if len(sys.argv) > 2:
                fname = sys.argv[2]
            else:
                fname = SysMgr.outFileName

            SysMgr.printLogo(big=True, onlyFile=True)

            ThreadAnalyzer.doSumReport(fname)

        # PAUSE MODE #
        elif SysMgr.isPauseMode():
            # convert comm to pid #
            targetList = []
            withSibling = SysMgr.groupProcEnable
            for item in SysMgr.filterGroup:
                targetList += SysMgr.getPids(item, withSibling=withSibling)
            targetList = list(set(targetList))

            Debugger.pauseThreads(targetList)

        # READELF MODE #
        elif SysMgr.isReadelfMode():
            SysMgr.printLogo(big=True, onlyFile=True)

            path = SysMgr.inputParam
            if not path:
                SysMgr.printErr(\
                    "No PATH with -I")
                sys.exit(0)

            # set debug flag #
            if SysMgr.jsonOutputEnable:
                debug = False
            else:
                debug = True

            # run ELF analyzer #
            try:
                if path == 'vdso':
                    obj = SysMgr.getVdso(debug=debug)
                else:
                    obj = ElfAnalyzer(path, debug, incArg=True)

                if SysMgr.jsonOutputEnable:
                    jsonStr = UtilMgr.convDict2Str(obj.attr)
                    SysMgr.printPipe(jsonStr)
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "Fail to analyze %s" % path, True)

        # LEAKTRACE MODE #
        elif SysMgr.isLeaktraceMode():
            SysMgr.doLeaktrace()

        # ADDR2SYM MODE #
        elif SysMgr.isAddr2symMode():
            SysMgr.doAddr2sym()

        # SYM2ADDR MODE #
        elif SysMgr.isSym2addrMode():
            SysMgr.doSym2addr()

        # PRINTDIR MODE #
        elif SysMgr.isPrintDirMode():
            SysMgr.printLogo(big=True, onlyFile=True)

            if not SysMgr.inputParam:
                root = '.'
            else:
                root = SysMgr.inputParam

            if not SysMgr.funcDepth:
                maxLevel = -1
            else:
                maxLevel = SysMgr.funcDepth

            SysMgr.printDirs(root, maxLevel)

        # PRINTCGROUP MODE #
        elif SysMgr.isPrintCgroupMode():
            SysMgr.cgroupEnable = True
            SysMgr().printCgroupInfo(printTitle=False)
            SysMgr.printInfoBuffer()

        # LOGJRL MODE #
        elif SysMgr.isLogJournalMode():
            SysMgr.doLogMode('journal')

        # LOGDLT MODE #
        elif SysMgr.isLogDltMode():
            SysMgr.doLogMode('dlt')

        # LOGKMSG MODE #
        elif SysMgr.isLogKmsgMode():
            SysMgr.doLogMode('kmsg')

        # LOGSYS MODE #
        elif SysMgr.isLogSysMode():
            SysMgr.doLogMode('syslog')

        # PRINTDLT MODE #
        elif SysMgr.isPrintDltMode():
            # set console info #
            SysMgr.ttyCols = long(0)
            SysMgr.printStreamEnable = True

            SysMgr.printLogo(big=True, onlyFile=True)

            DltAnalyzer.runDltReceiver(mode='print')

        # PRINTDBUS MODE #
        elif SysMgr.isPrintDbusMode():
            # set console info #
            SysMgr.ttyCols = long(0)
            SysMgr.printStreamEnable = True

            SysMgr.printLogo(big=True, onlyFile=True)

            DbusAnalyzer.runDbusSnooper(mode='print')

        # PRINTSIG MODE #
        elif SysMgr.isPrintSigMode():
            SysMgr.printLogo(big=True, onlyFile=True)

            DbusAnalyzer.runDbusSnooper(mode='signal')

        # PRINTSYSLOG MODE #
        elif SysMgr.isPrintSyslogMode():
            # set console info #
            SysMgr.ttyCols = long(0)
            SysMgr.printStreamEnable = True

            SysMgr.printLogo(big=True, onlyFile=True)

            LogMgr.printSyslog()

        # PRINTKMSG MODE #
        elif SysMgr.isPrintKmsgMode():
            # set console info #
            SysMgr.ttyCols = long(0)
            SysMgr.printStreamEnable = True

            SysMgr.printLogo(big=True, onlyFile=True)

            LogMgr.printKmsg()

        # PRINTJRL MODE #
        elif SysMgr.isPrintJournalMode():
            # set console info #
            SysMgr.ttyCols = long(0)
            SysMgr.printStreamEnable = True

            SysMgr.printLogo(big=True, onlyFile=True)

            LogMgr.printJournal()

        # PAGE MODE #
        elif SysMgr.isMemMode():
            SysMgr.printLogo(big=True, onlyFile=True)

            PageAnalyzer.getPageInfo(\
                SysMgr.filterGroup, SysMgr.inputParam)

        # LIMIT MODE #
        elif SysMgr.isLimitMode():
            # change priority of process #
            if not SysMgr.prio:
                SysMgr.setPriority(SysMgr.pid, 'C', -20)

            if SysMgr.isLimitCpuMode():
                limitInfo = SysMgr.getLimitCpuInfo(\
                    SysMgr.filterGroup)

                SysMgr.doLimitCpu(\
                    limitInfo, SysMgr.processEnable)

        # PSTREE MODE #
        elif SysMgr.isPstreeMode():
            SysMgr.doPstree()

        # PS MODE #
        elif SysMgr.isSystatMode():
            SysMgr.doSystat()

        # CPUTEST MODE #
        elif SysMgr.isCpuTestMode():
            SysMgr.printStreamEnable = True

            SysMgr.doCpuTest()

        # IOTEST MODE #
        elif SysMgr.isIoTestMode():
            SysMgr.doIoTest()

        # NETTEST MODE #
        elif SysMgr.isNetTestMode():
            SysMgr.doNetTest()

        # MEMTEST MODE #
        elif SysMgr.isMemTestMode():
            # remove option args #
            SysMgr.removeOptionArgs()

            SysMgr.ttyCols = 0
            SysMgr.printStreamEnable = True

            SysMgr.doMemTest()

        # SETCPU MODE #
        elif SysMgr.isSetCpuMode():
            # remove option args #
            SysMgr.removeOptionArgs()

            SysMgr.doSetCpu()

        # SETSCHED MODE #
        elif SysMgr.isSetSchedMode():
            SysMgr.doSetSched()

        # CONVERT MODE #
        elif SysMgr.isConvertMode():
            SysMgr.doConvert()

        # STRACE MODE #
        elif SysMgr.isStraceMode():
            SysMgr.doTrace('syscall')

        # UTRACE MODE #
        elif SysMgr.isUtraceMode():
            SysMgr.doTrace('usercall')

        # REMOTE MODE #
        elif SysMgr.isRemoteMode():
            SysMgr.doTrace('remote')

        # BTRACE MODE #
        elif SysMgr.isBtraceMode():
            # check background processes #
            SysMgr.checkBgProcs()

            SysMgr.doTrace('breakcall')

        # SIGTRACE MODE #
        elif SysMgr.isSigtraceMode():
            # check background processes #
            SysMgr.checkBgProcs()

            SysMgr.doTrace('signal')

        # PRINTENV MODE #
        elif SysMgr.isPrintEnvMode():
            SysMgr.doPrintEnv()

        # PRINTNS MODE #
        elif SysMgr.isPrintNsMode():
            SysMgr.doPrintNs()

        # PRINTSVC MODE #
        elif SysMgr.isPrintSvcMode():
            SysMgr.doPrintSvc()

        # PRINTINFO MODE #
        elif SysMgr.isPrintInfoMode():
            SysMgr.doPrintInfo()

        # AFFINITY MODE #
        elif SysMgr.isSetAffinityMode():
            SysMgr.doSetAffinity()

        elif SysMgr.isGetAffinityMode():
            SysMgr.doGetAffinity()

        # EVENT MODE #
        elif SysMgr.isEventMode():
            SysMgr.handleEventInput()
        else:
            return

        sys.exit(0)



    @staticmethod
    def isLimitMode():
        if SysMgr.isLimitCpuMode():
            return True
        else:
            return False



    @staticmethod
    def isEventMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'event':
            return True
        else:
            return False



    @staticmethod
    def isCpuDrawMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'cpudraw':
            return True
        else:
            return False



    @staticmethod
    def isMemDrawMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'memdraw':
            return True
        else:
            return False



    @staticmethod
    def isVssDrawMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'vssdraw':
            return True
        else:
            return False



    @staticmethod
    def isRssDrawMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'rssdraw':
            return True
        else:
            return False



    @staticmethod
    def isLeakDrawMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'leakdraw':
            return True
        else:
            return False



    @staticmethod
    def isIoDrawMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'iodraw':
            return True
        else:
            return False



    @staticmethod
    def isTopDiffMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'topdiff':
            return True
        else:
            return False



    @staticmethod
    def isTopSumMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'topsum':
            return True
        else:
            return False



    @staticmethod
    def isDrawMode():
        orig = SysMgr.drawMode
        SysMgr.drawMode = True

        if len(sys.argv) == 1:
            return False
        elif sys.argv[1] == 'draw' or orig:
            return True
        elif SysMgr.isCpuDrawMode():
            return True
        elif SysMgr.isMemDrawMode():
            return True
        elif SysMgr.isVssDrawMode():
            return True
        elif SysMgr.isRssDrawMode():
            return True
        elif SysMgr.isLeakDrawMode():
            return True
        elif SysMgr.isIoDrawMode():
            return True
        else:
            SysMgr.drawMode = orig
            return False



    @staticmethod
    def isPauseMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'pause':
            return True
        else:
            return False



    @staticmethod
    def isReadelfMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'readelf':
            return True
        else:
            return False



    @staticmethod
    def isAddr2symMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'addr2sym':
            return True
        else:
            return False



    @staticmethod
    def isSym2addrMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'sym2addr':
            return True
        else:
            return False



    @staticmethod
    def isPrintCgroupMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'printcrp':
            return True
        else:
            return False



    @staticmethod
    def isPrintDirMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'printdir':
            return True
        else:
            return False



    @staticmethod
    def isPrintDltMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'printdlt':
            return True
        else:
            return False



    @staticmethod
    def isPrintDbusMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'printdbus':
            return True
        else:
            return False



    @staticmethod
    def isPrintSigMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'printsig':
            return True
        else:
            return False



    @staticmethod
    def isPrintKmsgMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'printkmsg':
            return True
        else:
            return False



    @staticmethod
    def isPrintJournalMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'printjrl':
            return True
        else:
            return False



    @staticmethod
    def isPrintSyslogMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'printsys':
            return True
        else:
            return False



    @staticmethod
    def isLogDltMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'logdlt':
            return True
        else:
            return False



    @staticmethod
    def isLogKmsgMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'logkmsg':
            return True
        else:
            return False



    @staticmethod
    def isLogSysMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'logsys':
            return True
        else:
            return False



    @staticmethod
    def isLogJournalMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'logjrl':
            return True
        else:
            return False



    @staticmethod
    def isLeaktraceMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'leaktrace':
            return True
        else:
            return False



    @staticmethod
    def isMemMode():
        if len(sys.argv) > 1 and sys.argv[1] == 'mem':
            return True
        else:
            return False



    @staticmethod
    def checkPerfTopCond():
        if not SysMgr.isRoot():
            SysMgr.printErr(\
                "Fail to get root permission to use PMU")
            return False
        elif not os.path.isfile('%s/sys/kernel/perf_event_paranoid' % \
            SysMgr.procPath):
            SysMgr.printErr(\
                "Fail to use PMU, please check kernel configuration")
            return False
        else:
            return True



    @staticmethod
    def checkMemTopCond():
        if not SysMgr.isRoot():
            SysMgr.printErr(\
                "Fail to get root permission to analyze memory details")
            return False
        else:
            return True



    @staticmethod
    def checkBgTopCond():
        if SysMgr.printFile:
            return True

        logPath = '/var/log'
        tmpPath = '/tmp'

        if os.path.isdir(logPath) and os.access(logPath, os.W_OK):
            SysMgr.printFile = logPath
            return True
        elif os.path.isdir(tmpPath) and os.access(tmpPath, os.W_OK):
            SysMgr.printFile = tmpPath
            return True
        else:
            SysMgr.printErr(\
                "Fail to get path to save output, use -o option")
            return False



    @staticmethod
    def checkReportTopCond(val=None):
        # check whether report option is already enabled #
        if SysMgr.reportEnable:
            return True

        if not val:
            reportPath = SysMgr.getOption('j')
        else:
            reportPath = val

        # check report path #
        if not reportPath or len(reportPath) == 0:
            tmpPath = '/tmp'
            reportPath = tmpPath

        # directory path #
        if os.path.isdir(reportPath) == False:
            upDirPos = reportPath.rfind('/')
            if upDirPos > 0 and \
                not os.path.isdir(reportPath[:upDirPos]):
                SysMgr.printErr(\
                    "wrong path %s with -j option to report stats" % \
                    reportPath)
                return False
        # file path #
        else:
            reportPath = '%s/guider.report' % reportPath

        # remove redundant slashes and save it as the global report path #
        reportPath = os.path.normpath(reportPath)

        # backup a exist output file #
        if os.path.isfile(reportPath):
            backupFile = '%s.old' % reportPath

            try:
                os.rename(reportPath, backupFile)
                SysMgr.printInfo('%s is renamed to %s' % \
                    (reportPath, backupFile))
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "Fail to backup %s to %s" % \
                        (reportPath, backupFile), True)

        # open report file #
        try:
            if SysMgr.truncEnable:
                perm = 'w'
            else:
                perm = 'a'

            SysMgr.reportObject = open(reportPath, perm)
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printOpenErr(reportPath)
            sys.exit(0)

        SysMgr.reportEnable = True

        SysMgr.printInfo(\
            "start writing JSON format report to %s" % reportPath)

        return True



    @staticmethod
    def checkWssTopCond():
        if not SysMgr.getOption('g'):
            SysMgr.printErr(\
                "wrong option for wss monitoring, "
                "use also -g option to track memory working set")
            return False
        elif not SysMgr.isRoot():
            SysMgr.printErr(\
                "Fail to get root permission to clear refcnts")
            return False
        else:
            return True



    @staticmethod
    def checkDiskTopCond():
        procPath = SysMgr.procPath
        if not SysMgr.isRoot():
            SysMgr.printErr(\
                "Fail to get root permission to analyze block I/O")
            return False
        elif not os.path.isfile('%s/self/io' % procPath):
            SysMgr.printErr(\
                "Fail to use bio event, please check kernel configuration")
            return False
        else:
            return True



    @staticmethod
    def checkStackTopCond():
        if not SysMgr.isRoot():
            SysMgr.printErr(\
                "Fail to get root permission to sample stack")
            return False
        elif not SysMgr.getOption('g'):
            SysMgr.printErr(\
                "wrong option for stack monitoring, "
                "use also -g option to show stacks")
            return False
        elif not os.path.isfile('%s/self/stack' % SysMgr.procPath):
            SysMgr.printErr(\
                "Fail to sample stack, please check kernel configuration")
            return False
        else:
            return True



    @staticmethod
    def convertCIDR(addr):
        addrList = []
        splitAddr = [addr[i:i+2] for i in range(0, len(addr), 2)]
        for num in reversed(splitAddr):
            addrList.append(str(long(num, base=16)))
        return '.'.join(addrList)



    @staticmethod
    def getSocketPathList(addrList):
        pathList = {}
        inodeIdx = ConfigMgr.UDS_ATTR.index('Inode')
        pathIdx = ConfigMgr.UDS_ATTR.index('Path')

        UDS_ATTR = SysMgr.getUdsList()
        for uds in UDS_ATTR:
            try:
                if uds[inodeIdx] in addrList:
                    pathList[uds[pathIdx]] = None
            except:
                pass

        return list(pathList.keys())



    @staticmethod
    def mountDebugfs(mp=None):
        if not mp:
            mp = SysMgr.debugfsPath

        # mount debugfs #
        SysMgr.mountCmd =\
            "mount -t debugfs nodev %s" % mp
        os.system(SysMgr.mountCmd)

        SysMgr.mountPath = SysMgr.getDebugfsPath()
        if not SysMgr.mountPath:
            SysMgr.printErr(\
                "Fail to mount debugfs to trace events")
            sys.exit(0)



    @staticmethod
    def handleEventInput():
        pids = []

        # mount debug fs #
        SysMgr.mountPath = SysMgr.getDebugfsPath()
        if not SysMgr.mountPath:
            SysMgr.printWarn(\
                "Fail to get debugfs mount point", True)

        while 1:
            SysMgr.printStat(\
                "input event name... [ STOP(Ctrl+c) ]")

            if len(sys.argv) <= 2:
                try:
                    event = sys.stdin.readline()
                except SystemExit:
                    sys.exit(0)
                except:
                    pass

                if len(event.strip()) == 0:
                    SysMgr.writeEvent("EVENT_USER")
                    pids = SysMgr.broadcastEvent('EVENT', pids)
                else:
                    SysMgr.writeEvent("EVENT_%s" % event[:-1])
                    pids = SysMgr.broadcastEvent(event[:-1], pids)
            else:
                event = ' '.join(sys.argv[2:])
                SysMgr.writeEvent("EVENT_%s" % event)
                SysMgr.broadcastEvent(event)
                return



    @staticmethod
    def getSocketAddrList(addrList):
        portList = {}
        stIdx = ConfigMgr.UDP_ATTR.index('st')
        inodeIdx = ConfigMgr.UDP_ATTR.index('inode')
        addrIdx = ConfigMgr.UDP_ATTR.index('local_address')

        # get udp list #
        udpList = SysMgr.getUdpList()
        for udp in udpList:
            try:
                if udp[inodeIdx] in addrList:
                    ip, port = udp[addrIdx].split(':')

                    # convert ip address and port #
                    ip = SysMgr.convertCIDR(ip)

                    portList["UDP:%s:%s" % (ip, long(port, base=16))] = None
            except:
                pass

        # get tcp list #
        tcpList = SysMgr.getTcpList()
        for tcp in tcpList:
            try:
                if tcp[inodeIdx] in addrList:
                    ip, port = tcp[addrIdx].split(':')

                    # convert ip address and port #
                    ip = SysMgr.convertCIDR(ip)

                    try:
                        stat = '/%s' % \
                            ConfigMgr.TCP_STAT[long(tcp[stIdx], 16)]
                    except:
                        stat = ''

                    item = "TCP:%s:%s%s" % (ip, long(port, base=16), stat)
                    portList[item] = None
            except:
                pass

        return list(portList.keys())



    @staticmethod
    def getProcSocketObjs(pid):
        socketAddrList = []
        fdlistPath = "%s/%s/fd" % (SysMgr.procPath, pid)

        # save file info per process #
        try:
            fdlist = os.listdir(fdlistPath)
        except:
            SysMgr.printOpenWarn(fdlistPath)
            return socketAddrList

        # save fd info of process #
        for fd in fdlist:
            try:
                long(fd)
            except:
                continue

            try:
                # add file info into fdList #
                fdPath = "%s/%s" % (fdlistPath, fd)
                filename = os.readlink(fdPath)

                if filename.startswith('socket'):
                    socketAddrList.append(filename.split('[')[1][:-1])
            except:
                SysMgr.printOpenWarn(fdPath)

        return socketAddrList



    @staticmethod
    def getProcAddrs(name):
        if not SysMgr.isLinux or not name:
            return None

        # get pids #
        pids = SysMgr.getProcPids(name)
        if len(pids) == 1:
            # get socket objects #
            objs = SysMgr.getProcSocketObjs(pids[0])

            # get bind address #
            addrs = SysMgr.getSocketAddrList(objs)
            if len(addrs) == 0:
                SysMgr.printWarn(\
                    "Fail to get socket attribute of server", True)
                return None

            # get server address #
            addr = addrs[0]

            return addr[addr.find(':')+1:]

        if len(pids) > 1:
            SysMgr.printWarn(\
                "Found multiple running %s processes" % name, True)
        else:
            SysMgr.printWarn(\
                "Fail to find %s process" % name, True)

        return None



    @staticmethod
    def getProcPids(name):
        pidList = []
        myPid = str(SysMgr.pid)
        compLen = len(name)

        pids = os.listdir(SysMgr.procPath)
        for pid in pids:
            if myPid == pid:
                continue

            try:
                long(pid)
            except:
                continue

            # check comm #
            comm = SysMgr.getComm(pid)
            if comm and comm.startswith(name):
                pidList.append(long(pid))

        return pidList



    @staticmethod
    def getRuntime(isSec=False):
        uptime = long(SysMgr.getUptime())
        runtime = uptime - long(SysMgr.startRunTime)
        if isSec:
            return runtime
        return UtilMgr.convTime(runtime)



    @staticmethod
    def getUptime():
        try:
            SysMgr.uptimeFd.seek(0)
            return float(SysMgr.uptimeFd.readlines()[0].split()[0])
        except:
            try:
                uptimePath = "%s/%s" % (SysMgr.procPath, 'uptime')
                SysMgr.uptimeFd = open(uptimePath, 'r')
                return float(SysMgr.uptimeFd.readlines()[0].split()[0])
            except:
                SysMgr.printOpenWarn(uptimePath)
                return -1



    @staticmethod
    def updateUptime():
        SysMgr.prevUptime = SysMgr.uptime
        SysMgr.uptime = SysMgr.getUptime()
        SysMgr.uptimeDiff = \
            SysMgr.uptime - SysMgr.prevUptime
        return SysMgr.uptime



    @staticmethod
    def broadcastEvent(event, pids=[]):
        # convert event name #
        if not event.startswith('EVENT_'):
            event = 'EVENT_%s' % event

        if len(pids) == 0:
            # get pid list of Guider processes #
            pids = SysMgr.getProcPids(__module__)
            if len(pids) == 0:
                if SysMgr.isEventMode():
                    print("\nno running process in the background\n")
                else:
                    SysMgr.printWarn(\
                        "Failed to find running %s process to send event" % \
                        __module__)
                return []

        # update uptime #
        SysMgr.updateUptime()

        # get socket inode address list of Guider processes #
        for pid in pids:
            # get udp port list of Guider processes #
            objs = SysMgr.getProcSocketObjs(pid)
            addrs = SysMgr.getSocketAddrList(objs)

            for addr in addrs:
                try:
                    attr, ip, port = addr.split(':')
                except:
                    SysMgr.printWarn(\
                        "Failed to use %s as remote address" % (addr))
                    continue

                networkObject = NetworkMgr('client', ip, long(port))
                ip = networkObject.ip
                port = networkObject.port

                if not networkObject.ip or not networkObject.port:
                    SysMgr.printWarn(\
                        "Failed to use %s:%s as remote address" % (ip, port))
                    continue

                try:
                    networkObject.request = event
                    networkObject.send('%s@%s' % (event, SysMgr.uptime))
                    SysMgr.printInfo(\
                        "sent event '%s' to %s:%s address of %s process" % \
                        (event, ip, port, pid))
                except:
                    SysMgr.printWarn((\
                        "Failed to send event '%s' "
                        "to %s:%s address of %s process") % \
                        (event, ip, port, pid))

        return pids



    @staticmethod
    def updateBgProcs(cache=False):
        if SysMgr.bgProcList and cache:
            return

        SysMgr.bgProcList = SysMgr.getBgProcList()



    @staticmethod
    def checkBgProcs():
        if not SysMgr.isLinux:
            return

        SysMgr.updateBgProcs()

        if len(SysMgr.bgProcList) > 0:
            ppid = os.getppid()
            myComm = SysMgr.getComm(SysMgr.pid)
            parentComm = SysMgr.getComm(ppid)
            if myComm == parentComm:
                bgList = SysMgr.bgProcList.split('\n')
                tempBgList = list(bgList)
                for idx, line in enumerate(tempBgList):
                    if len(line) == 0:
                        continue
                    pid = long(line.split()[0])
                    if pid == ppid:
                        bgList.pop(idx)
                SysMgr.bgProcList = '\n'.join(bgList)

        if len(SysMgr.bgProcList) > 0:
            SysMgr.printWarn(\
                SysMgr.getBgProcString(), True)



    @staticmethod
    def getBgProcCount(cache=False):
        SysMgr.updateBgProcs(cache)

        return SysMgr.bgProcList.count('\n')



    @staticmethod
    def getBgProcString():
        if not SysMgr.bgProcList or \
            len(SysMgr.bgProcList) == 0:
            return ''

        procList = SysMgr.bgProcList

        bgStr = '\n[Running Process] [TOTAL: %s]\n' % procList.count('\n')
        bgStr = '%s%s\n%6s\t%6s\t%16s\t%8s\t%5s\t%14s\t%s\n%s\n' % \
            (bgStr, twoLine, "PID", "PPID", "COMM", \
                "STATE", "RSS", "RUNTIME", "COMMAND", oneLine)
        bgStr = '%s%s%s' % (bgStr, procList, oneLine)

        return bgStr



    @staticmethod
    def printBgProcs(cache=False, pager=False):
        if SysMgr.jsonOutputEnable:
            result = (SysMgr.getBgProcList(isJson=True))
            jsonResult = UtilMgr.convDict2Str(result)
            SysMgr.printPipe(jsonResult)
            return

        SysMgr.updateBgProcs(cache)

        procList = SysMgr.bgProcList

        if procList == '':
            SysMgr.printPipe(\
                "\nno running process in the background\n", pager=False)
        else:
            SysMgr.printPipe(SysMgr.getBgProcString(), pager=False)



    @staticmethod
    def getPids(name, isThread=True, withSibling=False, withMain=False):
        pidList = []

        # tid #
        if UtilMgr.isNumber(name) and \
            os.path.isdir('%s/%s' % (SysMgr.procPath, name)):
            if withSibling:
                path = '%s/%s/task' % (SysMgr.procPath, name)
                pids = os.listdir(path)
                for pid in pids:
                    if pid.isdigit():
                        pidList.append(pid)
                return pidList
            elif withMain:
                return list(set([name, SysMgr.getTgid(name)]))
            else:
                return [name]

        # comm #
        pids = os.listdir(SysMgr.procPath)
        for pid in pids:
            if not pid.isdigit():
                continue

            # process #
            if not isThread:
                # get comm #
                comm = SysMgr.getComm(pid)
                if comm == name:
                    pidList.append(pid)
                continue

            # thread #
            try:
                threadPath = "%s/%s/task" % (SysMgr.procPath, pid)
                tids = os.listdir(threadPath)
            except:
                continue

            for tid in tids:
                if not tid.isdigit():
                    continue

                # get comm #
                comm = SysMgr.getComm(tid)
                if comm != name:
                    continue

                # include all siblings #
                if withSibling:
                    pidList += tids
                    break

                # include the main thread #
                if withMain:
                    pidList.append(pid)

                # include a thread #
                pidList.append(tid)

        return list(set(pidList))



    @staticmethod
    def getBgProcList(checkCmdline=False, isJson=False):
        nrProc = long(0)
        printBuf = ''
        printDict = {}
        myPid = str(SysMgr.pid)
        gstatList = ConfigMgr.STAT_ATTR
        commIdx = ConfigMgr.STAT_ATTR.index("COMM")

        # update uptime #
        SysMgr.updateUptime()

        # get my comm #
        myComm = SysMgr.getComm(SysMgr.pid)

        # get my cmdline #
        myCmdline = SysMgr.getCmdline(SysMgr.pid, True)

        pids = os.listdir(SysMgr.procPath)
        for pid in pids:
            if myPid == pid or not pid.isdigit():
                continue

            # check comm #
            comm = SysMgr.getComm(pid)
            if not comm or not comm.startswith(myComm):
                continue

            # check cmdline again #
            if myComm != __module__ and checkCmdline:
                cmdlineList = SysMgr.getCmdline(pid, True)
                if len(cmdlineList) > 2 and myCmdline[:2] != cmdlineList[:2]:
                    continue

            runtime = '?'

            # comm #
            try:
                statPath = "%s/%s/stat" % (SysMgr.procPath, pid)
                with open(statPath, 'r') as fd:
                    statList = fd.readlines()[0].split()

                statList = SysMgr.updateStatList(statList, commIdx)

                # runtime #
                procStart = \
                    float(statList[gstatList.index("STARTTIME")]) / 100
                runtime = long(SysMgr.uptime - procStart)

                # ppid #
                ppid = statList[gstatList.index("PPID")]

                # state #
                try:
                    state = ConfigMgr.PROC_STAT_TYPE[\
                        statList[gstatList.index("STATE")]]
                except:
                    state = 'N/A'

                # rss #
                rss = long(statList[gstatList.index("RSS")])
                rss = UtilMgr.convSize2Unit(rss << 12, True)
            except:
                pass

            # runtime #
            if runtime != '?':
                runtime = UtilMgr.convTime(runtime)

            # socket #
            try:
                objs = SysMgr.getProcSocketObjs(pid)
                addrs = SysMgr.getSocketAddrList(objs)

                # merge address #
                netDict = {}
                for item in addrs:
                    ret = item.split('/')
                    if len(ret) == 2:
                        addr, stat = ret
                    else:
                        addr = ret[0]
                        stat = None

                    if not addr in netDict:
                        netDict[addr] = list()

                    if stat:
                        netDict[addr].append(stat)

                # build string #
                netList = ''
                for addr, stat in netDict.items():
                    if stat:
                        netList = '%s%s/%s,' % (netList, addr, '/'.join(stat))
                    else:
                        netList = '%s%s,' % (netList, addr)
                if len(netList) > 0:
                    network = '(%s)' % netList[:-1]
                else:
                    network = ''
            except:
                network = ''

            # cmdline #
            try:
                cmdline = SysMgr.getCmdline(pid)
            except:
                cmdline = '?'

            # build #
            if isJson:
                printDict[pid] = {
                    'comm': comm,
                    'ppid': ppid,
                    'state': state,
                    'rss': rss,
                    'runtime': runtime,
                    'cmdline': cmdline,
                    'network': network
                }
            else:
                printBuf = '%s%6s\t%6s\t%16s\t%8s\t%5s\t%14s\t%s %s\n' % \
                    (printBuf, pid, ppid, comm, \
                        state, rss, runtime, cmdline, network)

        if isJson:
            return printDict
        else:
            return printBuf



    @staticmethod
    def waitUserInput(wait=0, msg=None, newline=True):
        # check condition #
        if SysMgr.printFile or \
            SysMgr.bgStatus or \
            SysMgr.isReportTopMode() or \
            SysMgr.isBrkTopMode() or \
            not SysMgr.selectEnable or \
            'REMOTERUN' in os.environ:
            return

        # get select object #
        selectObj = SysMgr.getPkg('select', False)
        if not selectObj:
            SysMgr.selectEnable = False
            return

        # set default message #
        if not msg:
            msg = "Input command... ( Help / Quit )"

        # wait for user input #
        try:
            SysMgr.inWaitStatus = True

            if newline:
                suffix = '\n'
            else:
                suffix = ''

            # there was user input #
            if selectObj.select(\
                [sys.stdin], [], [], wait) == ([sys.stdin], [], []):
                sys.stdout.write('\b' * SysMgr.ttyCols)
                sys.stdout.write(msg + suffix)
                sys.stdout.flush()

                # flush buffered enter key #
                sys.stdin.readline()

                sys.stdout.write('=> ')
                sys.stdout.flush()

                # process user input #
                SysMgr.procUserInput(sys.stdin.readline())
            elif wait == 0:
                sys.stdout.write(msg + suffix)
                sys.stdout.flush()
                sys.stdin.readline()
                sys.stdout.write("\033[F")
        except SystemExit:
            sys.exit(0)
        except:
            pass
        finally:
            SysMgr.inWaitStatus = False

        return True



    @staticmethod
    def procUserInput(uinput):
        def printHelp():
            SysMgr.printPipe()

            SysMgr.printPipe("[Filter]   {COMM|PID}")
            SysMgr.printPipe("  exam) f init, 1234\n")

            SysMgr.printPipe("[Sched]    {SCHED:PRIO:COMM|PID}")
            SysMgr.printPipe("  exam) s r:1:123, c:-1:1234\n")

            SysMgr.printPipe("[Kill]     {-SIGNAL} {COMM|PID}")
            SysMgr.printPipe("  exam) k -stop 123, a.out\n")

            SysMgr.printPipe("[Affinity] {MASK} {COMM|PID}")
            SysMgr.printPipe("  exam) a f 123, a.out\n")

            SysMgr.printPipe("[Sort]     {VAL}")
            SysMgr.printPipe("  exam) S p\n")

            SysMgr.printPipe("[Option]   {VAL}")
            SysMgr.printPipe("  exam) o -e bs -g task\n")

            SysMgr.printPipe("[Run]      {COMMAND}")
            SysMgr.printPipe("  exam) r usertop -g task\n")

        ulist = uinput.split()
        if len(ulist) == 0:
            return

        # help #
        if ulist[0].upper() == 'HELP' or \
            ulist[0].upper() == 'H':
            printHelp()
        # kill #
        elif ulist[0].upper() == 'KILL' or \
            ulist[0] == 'k':
            if len(ulist) > 1:
                SysMgr.sendSignalArgs(ulist[1:])
            else:
                printHelp()
        # sched #
        elif ulist[0].upper() == 'SCHED' or \
            ulist[0] == 's':
            if len(ulist) > 1:
                SysMgr.parsePriorityOption((' '.join(ulist[1:])))
            else:
                printHelp()
        # sort #
        elif ulist[0].upper() == 'SORT' or \
            ulist[0] == 'S':
            if len(ulist) > 1:
                SysMgr.setSortValue(ulist[1])
            else:
                printHelp()
        # affinity #
        elif ulist[0].upper() == 'AFFINITY' or \
            ulist[0] == 'a':
            if len(ulist) > 2:
                pids = (' '.join(ulist[2:])).split(',')
                pids = SysMgr.convertPidList(pids, isThread=True)
                SysMgr.setAffinity(ulist[1], pids)
            else:
                printHelp()
        # filter #
        elif ulist[0].upper() == 'FILTER' or \
            ulist[0] == 'f':
            if len(ulist) == 1:
                SysMgr.filterGroup = []
            else:
                SysMgr.filterGroup = (' '.join(ulist[1:])).split(',')

            SysMgr.filterGroup = \
                SysMgr.clearList(SysMgr.filterGroup)

            if SysMgr.isThreadMode():
                mode = 'threads'
            else:
                mode = 'processes'

            SysMgr.printInfo(\
                "only specific %s [ %s ] are shown" % \
                (mode, ', '.join(SysMgr.filterGroup)))
        # option #
        elif ulist[0].upper() == 'OPTION' or \
            ulist[0] == 'o':
            if len(ulist) > 1:
                SysMgr.parseAnalOption(uinput[1:].strip())
            else:
                printHelp()
        # run #
        elif ulist[0].upper() == 'RUN' or \
            ulist[0] == 'r':
            if len(ulist) > 1:
                cmd = SysMgr.getExeCmd(SysMgr.pid)
                cmd.extend(ulist[1:])

                # launch new command #
                pid = SysMgr.createProcess(cmd)
                if pid < 0:
                    sys.exit(0)

                # ignore signals and wait for child #
                SysMgr.setIgnoreSignal()
                os.wait()
                SysMgr.setNormalSignal()
            else:
                printHelp()
        # quit #
        elif ulist[0].upper() == 'QUIT' or \
            ulist[0].upper() == 'Q':
            sys.exit(0)

        SysMgr.printPipe("Input ENTER to continue...")
        sys.stdin.readline()



    @staticmethod
    def getLimitCpuInfo(limitInfo):
        if len(limitInfo) == 0:
            SysMgr.printErr(\
                "Fail to get task info to limit cpu, "
                "input {tid:percentage} with -g option")
            sys.exit(0)

        SysMgr.checkPerm()

        limitList = {}
        try:
            for item in limitInfo:
                (tid,per) = item.split(':')

                # get id for tasks #
                if tid.isdigit():
                    limitList[tid] = long(per)
                else:
                    tidList = SysMgr.getPids(tid)
                    for tid in tidList:
                        limitList[tid] = long(per)
        except:
            SysMgr.printErr(\
                "Fail to get task info to limit cpu, "
                "input {tid:percentage} with -g option")
            sys.exit(0)

        return limitList



    @staticmethod
    def executeProcess(cmd=None, mute=False, closeAll=True):
        try:
            SysMgr.resetFileTable(mute, closeAll)

            os.execvp(cmd[0], cmd)
        except:
            SysMgr.printErr(\
                "Fail to execute '%s'" % ' '.join(cmd), True)
            return -1



    @staticmethod
    def initEnvironment():
        # save original args #
        SysMgr.origArgs = deepcopy(sys.argv)

        # register exit handler #
        atexit.register(SysMgr.doExit)

        # print logo #
        SysMgr.printLogo(big=True, pager=False)

        # check environment #
        SysMgr.checkEnv()

        # print help #
        SysMgr.printHelp()

        # set default io #
        SysMgr.inputFile = sys.argv[1]
        SysMgr.outputFile = None

        # check log level #
        SysMgr.warnEnable = SysMgr.findOption('v')

        # set error logger #
        SysMgr.setErrorLogger()

        # import Guider native module #
        SysMgr.importNative()

        # set comm #
        SysMgr.setComm(__module__)

        # create shared memory #
        SysMgr.shmObj = SysMgr.createShm()

        # set oom_adj #
        SysMgr.setOOMAdj()

        # set pid #
        SysMgr.getMaxPid()
        SysMgr.pid = os.getpid()

        # set arch #
        SysMgr.setArch(SysMgr.getArch())

        # set default signal #
        SysMgr.setSimpleSignal()

        # shrink heap #
        SysMgr.shrinkHeap()



    @staticmethod
    def getOutput(fd, retLine=False, progress=False):
        # get select object #
        selectObj = SysMgr.getPkg('select')

        output = ''

        while 1:
            # wait for event #
            [read, write, error] = \
                selectObj.select([fd], [], [])

            if progress:
                UtilMgr.printProgress()

            if read:
                line = read[0].readline()
                if retLine:
                    return line
                elif line == '':
                    return output

                output = '%s%s' % (output, line)



    @staticmethod
    def launchGuider(\
        cmd, log=False, mute=False, pipe=True, stderr=False, wait=False):
        # check mute #
        if mute:
            pipe = False

        # create pipe #
        if pipe:
            rd, wr = os.pipe()

            # set SIGPIPE handler #
            SysMgr.setPipeHandler()
        else:
            rd = wr = None

        # create a new process #
        pid = SysMgr.createProcess(mute=mute)

        # parent #
        if pid > 0:
            if pipe:
                os.close(wr)
                rdFd = os.fdopen(rd)
            else:
                rdFd = None

            # wait for child temrination #
            if wait:
                SysMgr.waitChild(pid)
                return None

            return (pid, rdFd)

        # child #
        elif pid == 0:
            # set main environment #
            os.environ["ISMAIN"] = "True"

            # disable pager #
            SysMgr.logEnable = False
            SysMgr.printStreamEnable = True
            SysMgr.printFile = SysMgr.fileForPrint = None

            # disable logs #
            if not log:
                SysMgr.encodeEnable = False

            # change standard I/O #
            if pipe:
                os.dup2(wr,1)
                os.close(wr)
                os.close(rd)

            # close stderr #
            if not stderr:
                sys.stderr.close()

            # launch Guider command #
            main(cmd)

            sys.exit(0)

        # error #
        else:
            SysMgr.printErr(\
                "Fail to launch Guider because of process creation fail")



    @staticmethod
    def waitChild(pid=None, hang=True):
        # wait for all childs #
        if not pid:
            while 1:
                try:
                    os.waitpid(-1, 0)
                except:
                    pass

                if SysMgr.condExit:
                    break

                # check childs #
                SysMgr.updateChilds()
                if SysMgr.isNoChild():
                    break
            return

        # set blocking flag #
        if hang:
            flag = 0
        else:
            flag = os.WNOHANG

        # wait for a specific child #
        try:
            return os.waitpid(pid, flag)
        except:
            SysMgr.printWarn(\
                "Fail to wait %s task" % pid, reason=True)



    @staticmethod
    def createProcess(\
        cmd=None, isDaemon=False, mute=False, chPgid=False, chMid=False):
        # flush print buffer before fork #
        SysMgr.flushAllForPrint()

        # create a new process #
        pid = os.fork()

        # parent #
        if pid > 0:
            if not isDaemon:
                SysMgr.childList[pid] = True

            return pid
        # child #
        elif pid == 0:
            # initialize child list #
            SysMgr.clearChildList()

            if chPgid:
                os.setpgid(0, 0)

            if SysMgr.fileForPrint:
                try:
                    SysMgr.fileForPrint.close()
                except SystemExit:
                    sys.exit(0)
                except:
                    pass
                SysMgr.fileForPrint = None

            # Guider #
            if not cmd:
                # update master pid #
                if chMid:
                    SysMgr.masterPid = SysMgr.pid

                # update pid #
                SysMgr.fileSuffix = SysMgr.pid = os.getpid()

                if mute:
                    SysMgr.closeStdFds(stderr=False)

                return 0

            # split command #
            if UtilMgr.isString(cmd):
                cmd = cmd.split()

            # execute #
            SysMgr.executeProcess(cmd, mute)

            # execute fail #
            os._exit(0)
        # fail #
        else:
            SysMgr.printErr(\
                "Fail to create process")
            return -1



    @staticmethod
    def closeStdFds(stdin=True, stdout=True, stderr=True):
        if not SysMgr.nullFd:
            SysMgr.nullFd = open('/dev/null', 'w')

        # get null fd #
        nullFd = SysMgr.nullFd.fileno()

        # redirect stds to null #
        if stdin:
            os.dup2(nullFd, sys.stdin.fileno())
        if stdout:
            os.dup2(nullFd, sys.stdout.fileno())
        if stderr:
            os.dup2(nullFd, sys.stderr.fileno())



    @staticmethod
    def resetFileTable(mute=True, closeAll=True):
        # redirect stdout and stderr to null #
        if mute:
            try:
                SysMgr.closeStdFds(stderr=False)
            except:
                pass

        # close all fds without standard #
        if closeAll:
            for fd in range(3, SysMgr.maxFd):
                try:
                    os.close(fd)
                except:
                    pass



    @staticmethod
    def runBackgroundMode():
        pid = SysMgr.createProcess(isDaemon=True)

        if pid > 0:
            # wait a minute for child message #
            time.sleep(0.1)

            # terminate parent process #
            sys.exit(0)
        else:
            SysMgr.bgStatus = True

            # continue child process #
            SysMgr.printStat(\
                "run %s(%s) in background" % \
                    (SysMgr.getComm(SysMgr.pid), SysMgr.pid))



    @staticmethod
    def setDefaultSignal():
        if not SysMgr.isLinux:
            return

        signal.signal(signal.SIGINT, signal.SIG_DFL)
        signal.signal(signal.SIGQUIT, signal.SIG_DFL)
        signal.signal(signal.SIGCHLD, signal.SIG_DFL)
        signal.signal(signal.SIGPIPE, signal.SIG_DFL)



    @staticmethod
    def setSimpleSignal():
        if not SysMgr.isLinux:
            return

        SysMgr.setCommonSignal()

        signal.signal(signal.SIGINT, SysMgr.exitHandler)
        signal.signal(signal.SIGQUIT, SysMgr.exitHandler)
        signal.signal(signal.SIGPIPE, signal.SIG_IGN)
        signal.signal(signal.SIGHUP, signal.SIG_IGN)



    @staticmethod
    def setPipeHandler():
        if not SysMgr.isLinux:
            return

        signal.signal(signal.SIGPIPE, SysMgr.exitHandler)



    @staticmethod
    def setCommonSignal():
        if not SysMgr.isLinux:
            return

        signal.signal(signal.SIGCHLD, SysMgr.chldHandler)
        signal.signal(signal.SIGWINCH, SysMgr.winchHandler)
        signal.signal(signal.SIGCONT, SysMgr.fgHandler)
        signal.signal(signal.SIGTSTP, SysMgr.bgHandler)
        #signal.signal(signal.SIGTTIN, SysMgr.bgHandler)
        #signal.signal(signal.SIGTTOU, SysMgr.bgHandler)



    @staticmethod
    def setIgnoreSignal():
        if not SysMgr.isLinux:
            return

        signal.signal(signal.SIGALRM, signal.SIG_IGN)
        signal.signal(signal.SIGINT, signal.SIG_IGN)
        signal.signal(signal.SIGQUIT, signal.SIG_IGN)
        signal.signal(signal.SIGPIPE, signal.SIG_IGN)



    @staticmethod
    def blockSignal(sig, act='block', wait=False):
        if not SysMgr.libcObj:
            if not SysMgr.loadLibcObj():
                return False

        if not SysMgr.sigsetObj:
            NWORDS = long(1024 / (8 * sizeof(c_uint)))

            class sigset_t(Structure):
                _fields_ = [
                    ('__sigbits', c_uint * NWORDS),
                ]

            SysMgr.sigsetObj = sigset_t()
            SysMgr.sigsetOldObj = sigset_t()

        sigset = SysMgr.sigsetObj
        sigsetold = SysMgr.sigsetOldObj

        # check act #
        if act == 'block':
            atype = SIG_BLOCK = 0
        elif act == 'unblock':
            atype = SIG_UNBLOCK = 1
        else:
            SysMgr.printErr(\
                "No supported '%s' for blocking signal" % act)
            return

        SysMgr.libcObj.memset(\
            byref(sigset), 0, sizeof(sigset))

        if type(sig) is not list:
            sig = [sig]

        for sigbit in sig:
            if hasattr(SysMgr.libcObj, 'sigaddset'):
                SysMgr.libcObj.sigaddset(byref(sigset), sigbit)

        SysMgr.libcObj.sigprocmask(atype, byref(sigset), byref(sigsetold))

        if wait:
            if hasattr(SysMgr.libcObj, 'sigsuspend'):
                SysMgr.libcObj.sigsuspend(byref(sigsetold))

        return True



    @staticmethod
    def pendingSignal(sig):
        if not SysMgr.libcObj:
            if not SysMgr.loadLibcObj():
                return False

        if not SysMgr.sigsetObj:
            return False

        sigset = SysMgr.sigsetObj

        pendingList = SysMgr.libcObj.sigpending(byref(sigset))

        if type(sig) is not list:
            sig = [sig]

        pendList = []
        for item in sig:
            if SysMgr.libcObj.sigismember(byref(sigset), item):
                pendList.append(item)

        return set(list(pendList))



    @staticmethod
    def setNormalSignal():
        if not SysMgr.isLinux:
            return

        SysMgr.setCommonSignal()

        signal.signal(signal.SIGALRM, SysMgr.alarmHandler)
        signal.signal(signal.SIGINT, SysMgr.stopHandler)
        signal.signal(signal.SIGQUIT, SysMgr.newHandler)
        signal.signal(signal.SIGPIPE, signal.SIG_IGN)



    @staticmethod
    def runServerMode():
        def sendErrMsg(netObj, message):
            message = 'ERROR|%s:%s:%s' % \
                (message, netObj.ip, netObj.port)
            netObj.send(message)

        def onDownload(netObj, value, response):
            # pick path #
            try:
                src, des = value.split(',')
            except:
                SysMgr.printWarn(\
                    'Failed to recognize path', True)
                sendErrMsg(netObj,\
                    "wrong format for path, input in the format {SRC,DES}")
                return

            # verify path #
            targetPath = src.strip()
            if not os.path.isfile(targetPath):
                SysMgr.printWarn(\
                    'Failed to find %s to transfer' % targetPath, True)
                sendErrMsg(netObj, "wrong path %s" % targetPath)
                return

            # response from command request #
            netObj.send(response)

            remotePath = des.strip()
            addr = '%s:%s' % (netObj.ip, netObj.port)

            # transfer file #
            try:
                # send file size #
                stat = os.stat(targetPath)
                st_size = '%s' % stat.st_size
                netObj.send(UtilMgr.encodeStr(st_size))

                # read for ACK #
                while 1:
                    ret = netObj.recv(3)
                    if ret is None:
                        continue
                    elif ret is False:
                        sys.exit(0)
                    else:
                        break

                # send file #
                with open(targetPath,'rb') as fd:
                    buf = fd.read(netObj.sendSize)
                    while (buf):
                        netObj.send(buf)
                        buf = fd.read(netObj.sendSize)

                SysMgr.printInfo(\
                    "%s [%s] is uploaded to %s:%s successfully" % \
                        (targetPath, UtilMgr.convSize2Unit(\
                            os.path.getsize(targetPath)), addr, remotePath))
            except:
                SysMgr.printErr(\
                    "Fail to upload %s to %s:%s" % \
                    (targetPath, addr, remotePath), True)
            finally:
                netObj.close()

        def onUpload(netObj, value, response):
            try:
                src, des = value.split(',')
            except:
                SysMgr.printWarn(\
                    'Failed to recognize path', True)
                sendErrMsg(netObj,\
                    "wrong format for path, input in the format {SRC,DES}")
                return

            # response from command request #
            netObj.send(response)

            # get select object #
            selectObj = SysMgr.getPkg('select')

            # get connection info #
            addr = '%s:%s' % (netObj.ip, netObj.port)

            # receive file #
            try:
                curSize = long(0)
                totalSize = None
                origPath = src.strip()
                targetPath = des.strip()

                # receive file size #
                while 1:
                    size = netObj.recv(netObj.recvSize)
                    if not size:
                        continue
                    else:
                        totalSize = long(size.decode())
                        netObj.send('ACK')
                        break

                # receive file #
                with open(targetPath, 'wb') as fd:
                    while 1:
                        [read, write, error] = \
                            selectObj.select([netObj.socket], [], [], 3)

                        buf = netObj.recv(netObj.recvSize)
                        if buf:
                            fd.write(buf)
                            curSize += len(buf)
                        else:
                            break

                        #UtilMgr.printProgress(curSize, totalSize)

                SysMgr.printInfo(\
                    "%s [%s] is downloaded from %s:%s successfully" % \
                    (targetPath, \
                    UtilMgr.convSize2Unit(\
                        os.path.getsize(targetPath)), addr, origPath))
            except:
                SysMgr.printErr(\
                    'Fail to download %s from %s:%s' % \
                        (origPath, addr, targetPath), True)
            finally:
                netObj.close()

        def onRun(connObj, value, response):
            def enableSigPipe():
                signal.signal(signal.SIGPIPE, signal.SIG_DFL)

            # response from command request #
            connObj.send(response)

            # get subprocess object #
            subprocess = SysMgr.getPkg('subprocess')

            # get connection info #
            addr = '%s:%s' % (connObj.ip, connObj.port)

            # convert Guider path #
            if value.startswith('GUIDER '):
                cmd = ' '.join(value.split()[1:])
                path = ' '.join(SysMgr.getExeCmd(SysMgr.pid))
                value = '%s %s' % (path, cmd)

            # run command #
            try:
                # copy environment variables #
                myEnv = deepcopy(os.environ)
                myEnv["REMOTERUN"] = "True"

                # set SIGCHLD #
                signal.signal(signal.SIGCHLD, signal.SIG_DFL)

                # create process to communicate #
                procObj = subprocess.Popen(\
                    value, shell=True, stdout=subprocess.PIPE, \
                    stderr=subprocess.PIPE, env=myEnv, bufsize=0, \
                    preexec_fn=os.setsid)

                SysMgr.printInfo(\
                    "'%s' command is executed for %s" % (value, addr))

                # get select object #
                selectObj = SysMgr.getPkg('select')

                # run mainloop #
                while 1:
                    try:
                        # wait for event #
                        [read, write, error] = \
                            selectObj.select(\
                                [procObj.stdout, connObj.socket], [], [], 1)

                        # read output from pipe #
                        for robj in read:
                            # check connection close #
                            if robj == connObj.socket:
                                raise Exception()

                            # handle data arrived #
                            while 1:
                                output = robj.readline()
                                if output == '\n':
                                    continue
                                elif output and len(output) > 0:
                                    ret = connObj.write(output)
                                    if not ret:
                                        raise Exception()
                                else:
                                    break
                    except:
                        break

                    # check process status #
                    if procObj.poll() != None:
                        break

                SysMgr.printInfo(\
                    "'%s' command is terminated for %s" % (value, addr))
            except:
                SysMgr.printErr(\
                    "Fail to execute '%s' from %s" % (value, addr), True)
            finally:
                try:
                    connObj.close()

                    # send TERM signal first #
                    os.killpg(procObj.pid, signal.SIGINT)

                    time.sleep(SysMgr.waitDelay)

                    # send KILL signal #
                    os.killpg(procObj.pid, signal.SIGKILL)
                except:
                    pass

        def handleConn(connObj, connMan):
            # read command #
            req = connObj.recvfrom()

            # unmarshalling #
            if type(req) is tuple:
                # check garbage value)
                if req[0] == '':
                    return

                try:
                    message = req[0].decode()
                except:
                    message = req[0]

                if req[1] is None:
                    ip = connObj.ip
                    port = connObj.port
                else:
                    try:
                        ip = req[1][0]
                        port = req[1][1]
                    except:
                        SysMgr.printWarn(\
                            "Fail to get address of client from message")
                        return False

                SysMgr.printInfo(\
                    "received request '%s' from %s:%s" % \
                    (message, ip, port))
            else:
                SysMgr.printErr(\
                    "received wrong request '%s'" % req)
                return False

            # get request and value #
            try:
                request, value = message.split(':', 1)
            except:
                request = value = None

            # handle request #
            if not request:
                SysMgr.printWarn(\
                    'Fail to recognize the request', True)
                return False

            # convert request to capital #
            request = request.upper()

            # check request type #
            if request != 'DOWNLOAD' and \
                request != 'UPLOAD' and \
                request != 'RUN' and \
                request != 'PING':
                SysMgr.printWarn(\
                    "Fail to recognize the request '%s'" % message, True)
                sendErrMsg(connObj, "No support request '%s'" % message)

                return False

            # build response data #
            response = '%s|%s' % (request, value)

            # create worker process #
            pid = SysMgr.createProcess()
            if pid > 0:
                return True

            # close listen socket of parent #
            connMan.close()

            # handle request #
            if request == 'DOWNLOAD':
                onDownload(connObj, value, response)

            elif request == 'UPLOAD':
                onUpload(connObj, value, response)

            elif request == 'RUN':
                onRun(connObj, value, response)

            elif request == 'PING':
                try:
                    connObj.send('PONG')
                except:
                    pass

            sys.exit(0)



        # start server mode #
        SysMgr.printInfo("SERVER MODE")

        # import packages #
        SysMgr.getPkg('select')
        socket = SysMgr.getPkg('socket')

        # get ip and port #
        if SysMgr.localServObj:
            ip = SysMgr.localServObj.ip
            port = SysMgr.localServObj.port
            SysMgr.localServObj.close()
        else:
            ip = port = None

        # set address #
        connMan = NetworkMgr.setServerNetwork(\
            ip, port, force=True, blocking=True, tcp=True)
        if not connMan:
            return

        SysMgr.printStat(\
            "run %s(%s) as a server" % \
                (SysMgr.getComm(SysMgr.pid), SysMgr.pid))

        # set SA_RESTART for SIGCHLD #
        signal.siginterrupt(signal.SIGCHLD, False)

        # listen #
        try:
            connMan.listen()
            connMan.timeout()
        except:
            SysMgr.printErr(\
                'Fail to listen to prepare for connection', True)
            sys.exit(0)

        # run mainloop #
        while 1:
            # accept #
            try:
                sock, addr = connMan.accept()
            except SystemExit:
                sys.exit(0)
            except socket.timeout:
                continue
            except:
                SysMgr.printWarn(\
                    'Fail to accept to prepare for connection', reason=True)
                continue

            SysMgr.printInfo(\
                "Connected to client %s:%s" % (addr[0], addr[1]))

            # create a TCP socket #
            connObj = NetworkMgr(\
                'server', addr[0], addr[1], tcp=True, bind=False)
            if not connObj or not connObj.ip:
                continue

            # apply connected socket to object #
            connObj.socket = sock

            # handle request from client #
            if handleConn(connObj, connMan):
                connObj.close()
                SysMgr.printBgProcs()

        sys.exit(0)



    @staticmethod
    def runClientMode():
        def printMenu():
            sys.stdout.write(\
                '\n[Command List]\n'
                '- DOWNLOAD:RemotePath,LocalPath\n'
                '- UPLOAD:LocalPath,RemotePath\n'
                '- RUN:Command\n'
                '- HISTORY\n'
                '- PING\n'
                '- EXIT\n'
                '\n'
            )

        def doPing(uinput):
            # get addrs from string #
            addrs = uinput[4:].strip()
            if addrs and not addrs[0].isdigit():
                addrs = addrs[1:]

            # classify ip and port #
            if addrs:
                service, ip, port = NetworkMgr.parseAddr(addrs)
                if service == ip == port == None:
                    SysMgr.printErr(\
                        "Fail to recognize command %s" % uinput, True)
                    return
                else:
                    NetworkMgr.setRemoteServer(addrs, tcp=True)

            ret = NetworkMgr.requestPing()
            if ret:
                SysMgr.printInfo('server is alive')

        def printHistory(hlist):
            for idx, cmd in enumerate(hlist):
                print('[%0d] %s' % (idx, cmd))

        def getUserInput():
            printMenu()
            sys.stdout.write('Input command to request service...\n=> ')
            sys.stdout.flush()

            return sys.stdin.readline()[:-1]



        # start client mode #
        SysMgr.printInfo("CLIENT MODE")

        # get address info #
        '''
        localAddr = SysMgr.getOption('x')
        remoteAddr = SysMgr.getOption('X')
        local, remote = \
            NetworkMgr.prepareServerConn(localAddr, remoteAddr)
        '''

        if SysMgr.loadLibcObj():
            signal.signal(signal.SIGINT, signal.SIG_IGN)

        # run mainloop #
        hlist = list()
        while 1:
            try:
                isHistory = False

                # get input #
                uinput = getUserInput()
                if uinput.startswith('!') and \
                    len(uinput) > 1 and \
                    uinput[1:].isdigit() and \
                    long(uinput[1:]) < len(hlist):
                    uinput = hlist[long(uinput[1:])]
                    isHistory = True

                # handle local command #
                if not uinput or \
                    uinput == '!' or \
                    uinput.upper() == 'HISTORY':
                    printHistory(hlist)
                    continue
                elif uinput.upper().startswith('PING'):
                    doPing(uinput)
                    continue
                elif uinput.upper() == 'EXIT':
                    break

                # backup command #
                if not isHistory and \
                    (not hlist or hlist[-1] != uinput):
                    hlist.append(uinput)

                # launch remote command #
                pipe = NetworkMgr.execRemoteCmd(uinput)
                if not pipe:
                    SysMgr.printErr(\
                        "Fail to execute remote command")
                    continue

                # block signal #
                SysMgr.blockSignal(signal.SIGINT, act='block')

                while 1:
                    output = pipe.getData()
                    if not output:
                        break

                    dataType = pipe.getDataType(output)

                    print(output[:-1])

                    if SysMgr.pendingSignal(signal.SIGINT):
                        break

                # unblock signal #
                SysMgr.blockSignal(signal.SIGINT, act='unblock')

            except SystemExit:
                return
            except:
                pass



    @staticmethod
    def getNrCore():
        if SysMgr.nrCore > 0:
            return SysMgr.nrCore

        try:
            cpuBuf = None
            SysMgr.statFd.seek(0)
            cpuBuf = SysMgr.statFd.readlines()
        except:
            try:
                cpuPath = "%s/stat" % SysMgr.procPath
                SysMgr.statFd = open(cpuPath, 'r')
                cpuBuf = SysMgr.statFd.readlines()
            except:
                SysMgr.printOpenWarn(cpuPath)

        nrCore = long(0)
        if cpuBuf:
            for line in cpuBuf:
                statList = line.split()
                cpuId = statList[0]
                if cpuId != 'cpu' and cpuId.startswith('cpu'):
                    nrCore += 1

            # set the number of core #
            SysMgr.nrCore = nrCore

        return nrCore



    @staticmethod
    def doConvert():
        # remove option args #
        SysMgr.removeOptionArgs()

        # parse options #
        value = ' '.join(sys.argv[2:])
        if len(value) == 0:
            SysMgr.printErr(\
                ("No path to convert file, "
                "input the path of a text file"))
            sys.exit(0)
        elif not os.path.isfile(value):
            SysMgr.printErr(\
                "wrong path %s to convert file" % value)
            sys.exit(0)

        # set output file name #
        SysMgr.imagePath = os.path.splitext(value)[0]

        # open text file #
        try:
            with open(value, 'r') as fd:
                textBuf = fd.read()
        except:
            SysMgr.printErr(\
                "Fail to read data from %s" % value)
            sys.exit(0)

        # draw image #
        SysMgr.drawText(textBuf)

        sys.exit(0)



    @staticmethod
    def doSetCpu():
        freqPath = '/sys/devices/system/cpu'

        SysMgr.checkPerm()

        if not os.path.isdir(freqPath):
            SysMgr.printErr(\
                "Fail to find CPU node for governor")
            sys.exit(0)
        elif len(SysMgr.filterGroup) == 0:
            SysMgr.printErr(\
                "No core value with -g option")
            sys.exit(0)

        # parse values #
        targetlist = []
        for val in list(SysMgr.filterGroup):
            vals = val.split(':')

            # check error #
            if (len(vals) < 2 or len(vals) > 3) or \
                not vals[0].isdigit() or not vals[1].isdigit():
                SysMgr.printErr(\
                ("wrong option value to set CPU clock, "
                "input in the format CORE:CLOCK(HZ){:GOVERNOR}"))
                sys.exit(0)

            targetlist.append(vals)

        # get available CPU list #
        cpulist = {}
        for f in os.listdir(freqPath):
            if not f.startswith('cpu'):
                continue

            cpu = f.split('cpu')[1]
            if not cpu.isdigit():
                continue

            # set path #
            commonpath = '%s/%s/cpufreq' % (freqPath, f)
            affectpath = '%s/affected_cpus' % commonpath
            govpath = '%s/scaling_available_governors' % commonpath
            curgovpath = '%s/scaling_governor' % commonpath
            availfreqpath = '%s/scaling_available_frequencies' % commonpath
            curfreqpath = '%s/scaling_cur_freq' % commonpath
            minfreqpath = '%s/scaling_min_freq' % commonpath
            maxfreqpath = '%s/scaling_max_freq' % commonpath

            cpulist[cpu] = dict()

            # affected_cpus #
            try:
                with open(affectpath, 'r') as fd:
                    cpulist[cpu]['affect'] = fd.readlines()[0].split()
            except:
                pass

            # available_governors #
            try:
                with open(govpath, 'r') as fd:
                    cpulist[cpu]['governors'] = fd.readlines()[0].split()
            except:
                pass

            # available_freq #
            try:
                with open(availfreqpath, 'r') as fd:
                    cpulist[cpu]['avail'] = \
                        list(map(long, fd.readlines()[0].split()))
                    cpulist[cpu]['avail'].sort()
                    cpulist[cpu]['avail'] = \
                        list(map(str, cpulist[cpu]['avail']))
            except:
                pass

            # freq #
            try:
                with open(minfreqpath, 'r') as fd:
                    cpulist[cpu]['min'] = fd.readlines()[0]
                with open(maxfreqpath, 'r') as fd:
                    cpulist[cpu]['max'] = fd.readlines()[0]
            except:
                cpulist.pop(cpu, None)

        # set CPU clock #
        for vals in targetlist:
            if len(vals) == 2:
                core, clock = vals
                gov = None
            elif len(vals) == 3:
                core, clock, gov = vals

            # check support #
            if not core in cpulist:
                SysMgr.printErr((\
                    "Fail to set cpu[%s] clock because "
                    "it doesn't support governor") % core)
                sys.exit(0)

            # check available clock #
            elif ('avail' in cpulist[core] and \
                long(clock) > 0 and not clock in cpulist[core]['avail']) or \
                (gov and not gov in cpulist[core]['governors']):

                avail = ' '.join(cpulist[core]['avail'])
                governors = ' '.join(cpulist[core]['governors'])
                SysMgr.printErr((\
                    "Fail to set cpu[%s] clock because it only supports \n\t"
                    "[%s] clock list \n\t[%s] governor list") % \
                        (core, avail, governors))
                sys.exit(0)

            # set path #
            commonpath = '%s/cpu%s/cpufreq' % (freqPath, core)
            curgovpath = '%s/scaling_governor' % commonpath
            minfreqpath = '%s/scaling_min_freq' % commonpath
            maxfreqpath = '%s/scaling_max_freq' % commonpath


            # set clock range #
            try:
                minres = maxres = govres = False

                if long(clock) > 0:
                    with open(minfreqpath, 'w') as fd:
                        fd.write(clock)
                    with open(maxfreqpath, 'w') as fd:
                        fd.write(clock)
                if gov:
                    with open(curgovpath, 'w') as fd:
                        fd.write(gov)
            except:
                if not minres:
                    res = 'min clock'
                elif not maxres:
                    res = 'max clock'
                elif not govres:
                    res = 'governor'

                SysMgr.printErr(\
                    "Fail to set %s of cpu[%s]" % (res, core), True)
                sys.exit(0)

            # cur_governor #
            try:
                with open(curgovpath, 'r') as fd:
                    curgovernor = fd.readlines()[0].split()[0]
            except:
                curgovernor = '?'

            # get affected CPU list #
            if 'affect' in cpulist[core] and len(cpulist[core]['affect']) > 1:
                affectstring = 'and it also affects CPU [%s]' % \
                    ', '.join(cpulist[core]['affect'])
            else:
                affectstring = ''

            SysMgr.printInfo(\
                "the clock speed of cpu[%s](%s) is set to %s successfuly %s" %
                    (core, curgovernor, clock, affectstring))

        sys.exit(0)



    @staticmethod
    def doSetSched():
        isProcess = False
        SysMgr.warnEnable = True

        # parse options #
        value = ','.join(SysMgr.filterGroup)
        if len(value) == 0:
            SysMgr.printErr(\
                ("wrong option value to set priority, "
                "input in the format POLICY:PRIORITY|TIME:PID"))
            sys.exit(0)

        SysMgr.parsePriorityOption(value)

        sys.exit(0)



    @staticmethod
    def doPrintEnv():
        SysMgr.printLogo(big=True, onlyFile=True)

        SysMgr.checkPerm()

        if len(SysMgr.filterGroup) == 0:
            SysMgr.filterGroup.append(SysMgr.pid)
            sys.exit(0)

        pids = SysMgr.convertPidList(SysMgr.filterGroup, exceptMe=True)
        if not pids:
            SysMgr.printErr("Fail to find %s process" % \
                ', '.join(SysMgr.filterGroup))
            sys.exit(0)

        for pid in pids:
            SysMgr.printPipe(\
                '\n[ %s(%s) ]' % (SysMgr.getComm(pid), pid))

            envs = SysMgr.getEnv(pid)
            if not envs:
                sys.exit(0)

            SysMgr.printPipe()

            for env in envs:
                SysMgr.printPipe(env)

        SysMgr.printPipe('\n')

        sys.exit(0)



    @staticmethod
    def initNetlink():
        if SysMgr.netlinkObj:
            return

        array = SysMgr.getPkg('array', False)
        if not array:
            return

        # create netlink socket #
        sockObj = SysMgr.netlinkObj = \
            NetworkMgr('server', ip=0, port=0, \
                anyPort=True, netlink=True, blocking=False)

        NLM_F_REQUEST = 1

        CTRL_CMD_UNSPEC         = 0
        CTRL_CMD_NEWFAMILY      = 1
        CTRL_CMD_DELFAMILY      = 2
        CTRL_CMD_GETFAMILY      = 3
        CTRL_CMD_NEWOPS         = 4
        CTRL_CMD_DELOPS         = 5
        CTRL_CMD_GETOPS         = 6

        CTRL_ATTR_UNSPEC        = 0
        CTRL_ATTR_FAMILY_ID     = 1
        CTRL_ATTR_FAMILY_NAME   = 2
        CTRL_ATTR_VERSION       = 3
        CTRL_ATTR_HDRSIZE       = 4
        CTRL_ATTR_MAXATTR       = 5
        CTRL_ATTR_OPS           = 6

        GEAttrStruct = [
                9,          # 0 CTRL_ATTR_UNSPEC
                '''=H''',   # 1 U16(skb, CTRL_ATTR_FAMILY_ID
                0,          # 2 STRING(skb, CTRL_ATTR_FAMILY_NAME
                '''=I''',   # 3 U32(skb, CTRL_ATTR_VERSION
                '''=I''',   # 4 U32(skb, CTRL_ATTR_HDRSIZE
                '''=I''',   # 5 U32(skb, CTRL_ATTR_MAXATTR
                '''=I''',   # 6 U32(skb, CTRL_ATTR_OP_ID
                '''=I''',   # 7 U32(skb, CTRL_ATTR_OP_FLAGS
                '''=I''',   # 8 U32(skb, CTRL_ATTR_MCAST_GRP_ID
                9           # 9 STRING(skb, CTRL_ATTR_MCAST_GRP_NAME
        ]

        cmd = 'TASKSTATS\0'
        msgLen = len(cmd) + 4

        # build request packet #
        msg = array.array(str('B'))

        # check version #
        if sys.version_info < (3, 0, 0):
            conv = msg.fromstring
        else:
            conv = msg.frombytes

        conv(struct.pack("BBxx", CTRL_CMD_GETFAMILY, 0))
        conv(struct.pack("HH", msgLen, CTRL_ATTR_FAMILY_NAME))
        conv(cmd.encode())
        conv(b'\0' * ((4 - (len(cmd) % 4)) & 0x3))

        nlmsghdr = array.array(\
            str('B'), struct.pack(str('=IHHII'), len(msg)+16, \
            ConfigMgr.NETLINK_TYPE['NETLINK_GENERIC'], NLM_F_REQUEST, 0, 0))
        nlmsghdr.extend(msg)

        # send GETFAMILY command #
        sockObj.send(nlmsghdr)

        # recv result #
        data = sockObj.recv()
        if not data:
            return

        (size, type, flags, seq, pid) = struct.unpack(str('=IHHII'), data[:16])
        data = data[16:size]

        cmd, version = struct.unpack(str('=BBxx'), data[:4])
        data = data[4:]

        while len(data) > 0:
            length, typ = struct.unpack(str('=HH'), data[:4])
            length = length & 0x7fff

            if GEAttrStruct[typ] == 0:
               SysMgr.GEAttr[typ] = data[4:length-1]
            elif GEAttrStruct[typ] == 9:
               pass
            elif typ > 5:
               pass
            else:
               SysMgr.GEAttr[typ] = \
                   struct.unpack(GEAttrStruct[typ], data[4:length])[0]

            data = data[((((length +3 ))) & ~0x3):]



    @staticmethod
    def getTaskstats(target):
        if SysMgr.isAndroid:
            return None

        sockObj = SysMgr.netlinkObj
        GEAttr = SysMgr.GEAttr

        if not sockObj:
            SysMgr.printErr("Not initialized netlink socket yet")
            return None

        NLMSG_MIN_TYPE  = 0x10
        GENL_ID_CTRL = NLMSG_MIN_TYPE
        ACK_REQUEST = (4 | 1)

        TASKSTATS_CMD_ATTR_PID = 1
        TASKSTATS_CMD_ATTR_TGID = 2
        TASKSTATS_CMD_GET = 1 # user -> kernel request/get-response
        TASKSTATS_CMD_NEW = 2 # kernel -> user event

        TASKSTATS_TYPE_PID = 1 # Process id
        TASKSTATS_TYPE_TGID = 2 # Thread group id
        TASKSTATS_TYPE_STATS = 3 # taskstats structure
        TASKSTATS_TYPE_AGGR_PID = 4 # contains pid + stats
        TASKSTATS_TYPE_AGGR_TGID = 5 # contains tgid + stats

        NLMSG_NOOP      =        0x1
        NLMSG_ERROR     =        0x2
        NLMSG_DONE      =        0x3
        NLMSG_OVERRUN   =        0x4

        CTRL_ATTR_UNSPEC        = 0
        CTRL_ATTR_FAMILY_ID     = 1
        CTRL_ATTR_FAMILY_NAME   = 2
        CTRL_ATTR_VERSION       = 3
        CTRL_ATTR_HDRSIZE       = 4
        CTRL_ATTR_MAXATTR       = 5
        CTRL_ATTR_OPS           = 6

        TASKSTATS_STRUCT = 'HIBBQQQQQQQQ32sIxxxIIIIIQQQQQQQQQQQQQQQQQQQQQQQ'
        TASKSTATS_FIELD = [
         'version', 'ac_exitcode',
         'ac_flag', 'ac_nice',
         'cpu_count', 'cpu_delay_total',
         'blkio_count', 'blkio_delay_total',
         'swapin_count', 'swapin_delay_total',
         'cpu_run_real_total', 'cpu_run_virtual_total',
         'ac_comm', 'ac_sched',
         'ac_uid', 'ac_gid', 'ac_pid', 'ac_ppid',
         'ac_btime', 'ac_etime', 'ac_utime', 'ac_stime',
         'ac_minflt', 'ac_majflt',
         'coremem', 'virtmem',
         'hiwater_rss', 'hiwater_vm',
         'read_char', 'write_char', 'read_syscalls', 'write_syscalls',
         'read_bytes', 'write_bytes', 'cancelled_write_bytes',
         'nvcsw', 'nivcsw',
         'utimescaled', 'stimescaled', 'cpu_scaled_run_real_total',
         'freepages_count', 'freepages_delay_total'
        ]

        array = SysMgr.getPkg('array', False)
        if not array:
            return None

        # request #
        msg = array.array(str('B'))

        # check version #
        if sys.version_info < (3, 0, 0):
            conv = msg.fromstring
        else:
            conv = msg.frombytes

        conv(struct.pack("BBxx", TASKSTATS_CMD_GET, 0))

        cmd = struct.pack('=I', int(target))
        msgLen = len(cmd) + 4

        conv(struct.pack("HH", msgLen, TASKSTATS_CMD_ATTR_PID))
        conv(cmd.encode())
        conv(b'\0' * ((4 - (len(cmd) % 4)) & 0x3))

        pid = sockObj.socket.getsockname()[0]
        nlmsghdr = array.array(\
            str('B'),struct.pack(str('=IHHII'), len(msg) + 16, \
            GEAttr[CTRL_ATTR_FAMILY_ID], ACK_REQUEST, 1, pid))
        nlmsghdr.extend(msg)

        sockObj.send(nlmsghdr)

        cnt = 0
        while 1:
            data = sockObj.recv()
            if type(data) is bytes and len(data) >= 328:
                break

            cnt += 1
            if cnt > 3:
                return None

        (size, ftype, flags, seq, pid) = struct.unpack(str('=IHHII'), data[:16])
        data = data[16:size]

        cmd, version = struct.unpack(str('=BBxx'), data[:4])
        data = data[4:]

        attrs = dict(\
            zip(TASKSTATS_FIELD, struct.unpack(TASKSTATS_STRUCT, data[16:344])))
        attrs['ac_comm'] = attrs['ac_comm'].decode().rstrip('\0')

        return attrs



    @staticmethod
    def doPrintSvc():
        def getAttr(fpath):
            try:
                fd = open(fpath, 'r')
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printOpenErr(fpath)
                return

            lines = fd.readlines()

            attrList = dict()
            for line in lines:
                try:
                    if line == '\n' or \
                        line.startswith('#') or \
                        line.startswith('['):
                        continue

                    name, value = line[:-1].split('=', 1)
                    attrList[name.strip()] = value.strip()
                except:
                    SysMgr.printWarn(\
                        "Fail to parse line '%s'" % line[:-1], reason=True)

            return attrList

        SysMgr.printLogo(big=True, onlyFile=True)

        # set dir path #
        if SysMgr.inputParam:
            systemdPathList = SysMgr.inputParam.split(',')
            for d in systemdPathList:
                if not os.path.isdir(d):
                    SysMgr.printErr(\
                        "%s is not an accessable directory" % d)
                    sys.exit(0)
        else:
            systemdPathList = [\
                '/etc/systemd/system',
                '/lib/systemd/system',
            ]

        cv = UtilMgr.convNum

        busServiceList = {}
        filteredList = {}

        SysMgr.cmdlineEnable = True
        obj = ThreadAnalyzer(onlyInstance=True)
        obj.saveSystemStat()

        # parse service files #
        for spath in systemdPathList:
            for items in os.walk(spath):
                for node in items[2]:
                    if not node.endswith('.service'):
                        continue
                    elif node in busServiceList:
                        continue
                    elif not UtilMgr.isEffectiveStr(node, ignCap=True):
                        continue

                    fpath = os.path.join(items[0], node)
                    if os.path.islink(fpath):
                        continue

                    busServiceList[node] = getAttr(fpath)
                    busServiceList[node]["path"] = fpath

        # parse filter #
        attrList = []
        valList = []
        for item in SysMgr.customCmd:
            args = item.split(':', 1)
            if len(args) == 1:
                attrList.append(args[0])
            else:
                valList.append(args[1])

        # print service files #
        if len(busServiceList) > 0:
            SysMgr.printPipe(\
                'Target Service [ NrItems: %s ]\n%s' % \
                    (cv(len(busServiceList)), twoLine))
            nrItems = 0
            for node, value in sorted(busServiceList.items(), key=lambda e:e[0]):
                cnt = 0
                for attr, val in sorted(value.items()):
                    if not UtilMgr.isEffectiveStr(attr, attrList, ignCap=True):
                        continue
                    elif not UtilMgr.isEffectiveStr(val, valList, ignCap=True):
                        continue

                    SysMgr.addPrint(\
                        '{0:32} {1:1} = {2:1}\n'.format(' ', attr, val))
                    cnt += 1

                if cnt > 0:
                    SysMgr.printPipe('[ %s ]' % node)
                    SysMgr.doPrint(clear=True)
                    nrItems += 1
                else:
                    SysMgr.clearPrint()
                    filteredList[node] = value

            if nrItems == 0:
                SysMgr.printPipe('\tNone')
            SysMgr.printPipe('%s\n' % oneLine)

        # print filtered list #
        if len(filteredList) > 0:
            SysMgr.printPipe(\
                'Exceptional Service [ NrItems: %s ]\n%s' % \
                    (cv(len(filteredList)), twoLine))
            for node, value in sorted(filteredList.items()):
                SysMgr.printPipe('[ %s ]' % node)
                for attr, val in sorted(value.items()):
                    SysMgr.printPipe(\
                        '{0:32} {1:1} = {2:1}'.format(' ', attr, val))
                SysMgr.printPipe()
            SysMgr.printPipe('%s\n' % oneLine)

        sys.exit(0)



    @staticmethod
    def doPrintNs():
        SysMgr.printLogo(big=True, onlyFile=True)

        SysMgr.checkPerm()

        SysMgr.nsEnable = True

        obj = ThreadAnalyzer(onlyInstance=True)
        obj.saveSystemStat()

        cv = UtilMgr.convNum
        for ns, val in sorted(obj.nsData.items(), key=lambda e: e[0]):
            SysMgr.printPipe(\
                '[%s] (Total: %s)\n%s' % (ns, cv(len(val)), twoLine))
            cnt = 1
            for key, tids in sorted(val.items(), key=lambda e:e[0]):
                tid = sorted(list(tids.keys()), key=lambda e:long(e))[0]
                comm = obj.procData[tid]['stat'][obj.commIdx][1:-1]
                subStr = '{ %s(%s)' % (comm, tid)
                if len(tids) == 1:
                    subStr += ' }'
                else:
                    subStr += ', ... }'

                nsStr = '(%3s) %s [Total: %s] %s' % \
                    (cnt, key, len(tids), subStr)
                SysMgr.printPipe(nsStr)
                cnt += 1
                indentStr = ' ' * long(len(nsStr) / 2)

                if not SysMgr.showAll:
                    continue

                for tid in sorted(tids.keys(), key=lambda e:long(e)):
                    comm = obj.procData[tid]['stat'][obj.commIdx][1:-1]
                    SysMgr.printPipe('%s - %s(%s)' % (indentStr, comm, tid))
            SysMgr.printPipe('%s\n' % oneLine)

        sys.exit(0)



    @staticmethod
    def doPrintInfo():
        SysMgr.printLogo(big=True, onlyFile=True)

        SysMgr()
        SysMgr.sysInstance.saveSysStat()

        if SysMgr.jsonOutputEnable:
            # convert dict data to JSON-type string #
            jsonObj = UtilMgr.convDict2Str(SysMgr.jsonData)
            if not jsonObj:
                SysMgr.printWarn(\
                    "Fail to convert report data to JSON type")
            else:
                SysMgr.printPipe(jsonObj)
        else:
            SysMgr.printInfoBuffer()

        sys.exit(0)



    @staticmethod
    def doTrace(mode):
        def doCommonJobs(pids, procList):
            # get pid list #
            for tid in pids:
                try:
                    pid = SysMgr.getTgid(tid)
                    procList.setdefault(pid, list())
                    procList[pid].append(tid)
                except SystemExit:
                    sys.exit(0)
                except:
                    pass
            pidList = list(map(long, procList.keys()))

            # merge map files #
            mapList = []
            for pid in pidList:
                mapList += FileAnalyzer.getProcMapInfo(pid, onlyExec=True).keys()
            mapList = list(set(mapList))

            # load symbol caches at once #
            for item in mapList:
                try:
                    eobj = ElfAnalyzer.getObject(item)
                    if len(pidList) == 1 and eobj:
                        eobj.mergeSymTable()
                except SystemExit:
                    sys.exit(0)
                except:
                    pass

            if mode != 'breakcall':
                return

            # save original data to be injected for multi-threaded process #
            for pid in pidList:
                # stop a process #
                os.kill(pid, signal.SIGSTOP)

                # register signal sender for resume #
                SysMgr.addExitFunc(\
                    SysMgr.sendSignalProcs, \
                    [signal.SIGCONT, [pid], False, False])

                bpList.setdefault(pid, dict())
                exceptBpList.setdefault(pid, dict())
                targetBpList.setdefault(pid, dict())
                targetBpFileList.setdefault(pid, dict())

                # create object #
                procObj = Debugger(pid=pid, execCmd=execCmd, mode='break')
                if not procObj:
                    continue

                # load common ELF cache files #
                if procObj.loadSymbols():
                    procObj.updateBpList()

                # save per-process breakpoint info #
                bpList[pid] = \
                    deepcopy(procObj.bpList)
                exceptBpList[pid] = \
                    deepcopy(procObj.exceptBpList)
                targetBpList[pid] = \
                    deepcopy(procObj.targetBpList)
                targetBpFileList[pid] = \
                    deepcopy(procObj.targetBpFileList)

                # create a lock for a target multi-threaded process #
                if SysMgr.getPids(pid, withSibling=True):
                    lockList[pid] = \
                        Debugger.getGlobalLock(pid, len(bpList[pid]))

                procObj.detach()
                del procObj

                # remove signal sender #
                SysMgr.removeExitFunc(\
                    SysMgr.sendSignalProcs, \
                    [signal.SIGCONT, [pid], False, False])

        SysMgr.printLogo(big=True, onlyFile=True)

        # no use pager #
        if not SysMgr.isTopMode():
            SysMgr.printStreamEnable = True

        # define wait syscall #
        wait = None
        multi = False
        execCmd = None
        lockObj = None
        procList = {}
        bpList = {}
        lockList = {}
        exceptBpList = {}
        targetBpList = {}
        targetBpFileList = {}

        # check input #
        if len(SysMgr.filterGroup) == 0 and \
            not SysMgr.inputParam:
            SysMgr.printErr(\
                "Input value for target with -g or -I option")
            sys.exit(0)

        # check command #
        if mode == 'remote':
            if not SysMgr.customCmd:
                SysMgr.printErr("Fail to get remote command")
                sys.exit(0)
            elif SysMgr.inputParam:
                SysMgr.printErr("Executing a program is not supported")
                sys.exit(0)

        # set priority #
        if not SysMgr.prio:
            SysMgr.setPriority(SysMgr.pid, 'C', -20)

        # get input path #
        if SysMgr.inputParam:
            inputParam = str(SysMgr.inputParam)
        else:
            inputParam = None

        # convert comm to pid #
        pids = SysMgr.convertPidList(\
            SysMgr.filterGroup, isThread=True, \
                withSibling=SysMgr.groupProcEnable)

        # get pids of process groups #
        if mode == 'breakcall':
            allpids = SysMgr.convertPidList(\
                SysMgr.filterGroup, isThread=True, withSibling=True)
        else:
            allpids = pids

        # create event memory #
        Debugger.globalEvent = SysMgr.createShm()

        needSymbol = (mode == 'sample' or mode == 'breakcall' or \
            mode == 'usercall' or SysMgr.funcDepth > 0)

        # check tid #
        if inputParam:
            pid = None
            execCmd = inputParam.split()
        # check error #
        elif not SysMgr.isRoot():
            SysMgr.printErr(\
                "Fail to get root permission to trace %s" % mode)
            sys.exit(0)
        elif not pids or len(pids) == 0:
            if SysMgr.filterGroup:
                SysMgr.printErr(\
                    "No thread related to %s" % \
                    ', '.join(SysMgr.filterGroup))
            elif not inputParam:
                SysMgr.printErr(\
                    "No TID with -g option or command with -I option")
            else:
                SysMgr.printErr("No TID with -g option")

            SysMgr.printFile = SysMgr.fileForPrint = None

            sys.exit(0)
        elif len(allpids) > 1 or mode == 'breakcall':
            parent = SysMgr.pid

            # set multi-task attributes #
            if len(pids) > 1:
                multi = True
                if not SysMgr.printFile:
                    SysMgr.printStreamEnable = True

                SysMgr.printWarn(\
                    "multiple tasks [ %s ] are traced" % \
                        SysMgr.getCommList(pids), True)

            # load symbol caches #
            if needSymbol:
                doCommonJobs(pids, procList)

            # create new worker processes #
            try:
                isFinished = True
                for tid in allpids:
                    ret = SysMgr.createProcess(chPgid=True, chMid=True)
                    if ret == 0:
                        if not tid in pids:
                            SysMgr.printEnable = False

                            # mute tasks except for targets #
                            if not SysMgr.warnEnable and \
                                SysMgr.getTgid(tid) != tid:
                                SysMgr.logEnable = False

                        pid = long(tid)
                        break
            except:
                isFinished = False

            # wait for child tracers as their parent #
            if SysMgr.pid == parent:
                if isFinished:
                    while 1:
                        SysMgr.waitEvent(ignChldSig=False)
                        if SysMgr.condExit:
                            break

                        # check childs #
                        SysMgr.updateChilds()
                        if SysMgr.isNoChild():
                            break

                # disable printing to file #
                SysMgr.printFile = SysMgr.fileForPrint = None

                # broadcast termination signal to childs #
                SysMgr.killChilds(\
                    sig=signal.SIGINT, wait=True, group=True)

                # remove all progress files #
                if mode == 'breakcall':
                    for pid in list(procList.keys()):
                        try:
                            progressFile = \
                                '%s/task_%s.done' % (SysMgr.cacheDirPath, pid)
                            os.remove(progressFile)
                        except:
                            pass

                # continue a process #
                SysMgr.sendSignalProcs(\
                    signal.SIGCONT, list(procList.keys()), verbose=False)

                sys.exit(0)
        else:
            # load symbol caches #
            if needSymbol:
                doCommonJobs(pids, procList)

            pid = long(pids[0])

        # recover SIGCHLD #
        signal.signal(signal.SIGCHLD, signal.SIG_DFL)

        # start tracing #
        try:
            if mode == 'syscall':
                Debugger(pid=pid, execCmd=execCmd).\
                    trace(wait=wait, multi=multi)
            elif mode == 'usercall':
                # tracing #
                if SysMgr.isTraceMode():
                    Debugger(pid=pid, execCmd=execCmd).\
                        trace(mode='inst', wait=wait, multi=multi)
                # monitoring #
                else:
                    Debugger(pid=pid, execCmd=execCmd).\
                        trace(mode='sample', wait=wait, multi=multi)
            elif mode == 'breakcall':
                if pid:
                    ppid = long(SysMgr.getTgid(pid))

                    # set per-process convert breakpoint list #
                    if ppid in bpList:
                        bpList = bpList[ppid]
                    if ppid in exceptBpList:
                        exceptBpList = exceptBpList[ppid]
                    if ppid in targetBpList:
                        targetBpList = targetBpList[ppid]
                    if ppid in targetBpFileList:
                        targetBpFileList = targetBpFileList[ppid]
                    if ppid in lockList:
                        lockObj = lockList[ppid]
                else:
                    ppid = SysMgr.pid

                Debugger(pid=pid, execCmd=execCmd).\
                    trace(mode='break', wait=wait, multi=multi, \
                        bpList=bpList, exceptBpList = exceptBpList, \
                        lock=lockObj, targetBpList=targetBpList, \
                        targetBpFileList=targetBpFileList)
            elif mode == 'signal':
                Debugger(pid=pid, execCmd=execCmd).\
                    trace(mode='signal', wait=wait, multi=multi)
            elif mode == 'remote':
                Debugger(pid=pid, execCmd=execCmd).\
                    trace(mode='remote', wait=wait, multi=multi)
            else:
                pass
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Stopped to trace %s" % mode, True)

        sys.exit(0)



    @staticmethod
    def doAddr2sym():
        SysMgr.printLogo(big=True, onlyFile=True)

        SysMgr.warnEnable = True

        # check input #
        if not SysMgr.inputParam:
            SysMgr.printErr("No PATH with -I")
            sys.exit(0)

        # check symbol #
        if len(SysMgr.filterGroup) == 0:
            SysMgr.printErr(\
                "No offset with -g")
            sys.exit(0)
        else:
            addrList = list()
            for idx, addr in enumerate(SysMgr.filterGroup):
                if not UtilMgr.isNumber(addr):
                    SysMgr.printErr(\
                        "Fail to recognize '%s' as a number" % addr)
                    sys.exit(0)

                try:
                    addrList.append(long(addr, 16))
                except:
                    addrList.append(long(addr))

        resInfo = {}
        inputArg = str(SysMgr.inputParam)

        # get pid list #
        pids = SysMgr.getPids(inputArg)
        taskList = []
        for tid in pids:
            taskList.append(SysMgr.getTgid(tid))
        pids = list(set(taskList))

        # a file #
        if len(pids) == 0:
            # check file #
            if os.path.isfile(inputArg):
                filePath = inputArg

                # create ELF object #
                try:
                    binObj = ElfAnalyzer.getObject(filePath, True)
                    if not binObj:
                        err = SysMgr.getErrMsg()
                        raise Exception(err)
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printErr(\
                        "Fail to load %s as an ELF object" % filePath, True)
                    sys.exit(0)

                for addr in addrList:
                    try:
                        resInfo[addr] = [binObj.getSymbolByOffset(addr), filePath]
                    except SystemExit:
                        sys.exit(0)
                    except:
                        resInfo[addr] = ['??', filePath]
            else:
                SysMgr.printErr(\
                    "Fail to recognize %s as a file or a process" % inputArg)
                sys.exit(0)
        # multiple process #
        elif len(pids) > 1:
            SysMgr.printErr((\
                "Fail to find a unique process because "
                "multiple processes [ %s ] are found") % ', '.join(pids))
            sys.exit(0)
        # single process #
        else:
            pid = pids[0]

            try:
                dobj = Debugger(pid=pid, attach=False)
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr("Fail to analyze %s process" % pid)
                sys.exit(0)

            for addr in addrList:
                ret = dobj.getSymbolInfo(addr)
                if not ret:
                    SysMgr.printErr("Fail to analyze %s process" % pid)
                    sys.exit(0)
                elif type(ret) is list:
                    resInfo[addr] = [ret[0], ret[1]]
                else:
                    resInfo[addr] = ['??', '??']

        SysMgr.printPipe("\n[Address Info]\n%s" % twoLine)
        SysMgr.printPipe(\
            "{0:<18} {1:<52} {2:<1}\n{3:1}".format(\
                'Address', 'Symbol', 'File', twoLine))

        # print symbols from offset list #
        for addr, val in resInfo.items():
            SysMgr.printPipe(\
                "{0:<18} {1:<52} {2:<1}".format(\
                    hex(addr).rstrip('L'), val[0], val[1]))

        if len(resInfo) == 0:
            SysMgr.printPipe('\tNone')

        SysMgr.printPipe(oneLine + '\n')



    @staticmethod
    def printDirs(path='.', maxLevel=-1):
        def getDirs(result, parentPath, level, maxLevel):
            fileList = os.listdir(parentPath)
            parentAbsPath = "%s" % (os.path.abspath(parentPath))

            if len(fileList) == 0 or \
                    (maxLevel != -1 and maxLevel <= level):
                return (0, 0, 0)

            totalSize = long(0)
            totalFile = long(0)
            totalDir = long(0)

            # sort by size #
            if SysMgr.showAll:
                fileList.sort( \
                    key=lambda name: os.path.getsize( \
                        '%s/%s' % (parentPath, name)), reverse=True)
            # sort by type #
            else:
                fileList.sort( \
                    key=lambda f: os.path.isfile(os.path.join(parentPath, f)))

            for idx, subPath in enumerate(fileList):

                fullPath = os.path.join(parentPath, subPath)

                if os.path.islink(fullPath):
                    continue

                subAbsPath = "%s" % (os.path.abspath(fullPath))

                if os.path.isdir(fullPath):
                    totalDir += 1
                    if SysMgr.showAll:
                        info = dict(subDirs=dict(), subFiles=dict())
                    else:
                        info = dict(subDirs=dict())
                    result[parentAbsPath]['subDirs'][subAbsPath] = info
                    totalInfo = \
                        getDirs(result[parentAbsPath]['subDirs'], \
                            fullPath, level + 1, maxLevel)

                    totalSize += totalInfo[0]
                    totalDir += totalInfo[1]
                    totalFile += totalInfo[2]

                elif os.path.isfile(fullPath):
                    totalFile += 1
                    size = os.stat(fullPath).st_size
                    totalSize += size

                    if not SysMgr.showAll:
                        continue

                    if 'subFiles' not in result[parentAbsPath]:
                        result[parentAbsPath]['subFiles'] = dict()
                    result[parentAbsPath]['subFiles'][subAbsPath] = \
                        dict(size=UtilMgr.convSize2Unit(size), type='file')

            result[parentAbsPath]['size'] = UtilMgr.convSize2Unit(totalSize)
            result[parentAbsPath]['nrDir'] = UtilMgr.convNum(totalDir)
            result[parentAbsPath]['nrFile'] = UtilMgr.convNum(totalFile)

            return (totalSize, totalDir, totalFile)

        def recurse(parentPath, fileList, prefix, result, level, maxLevel):
            totalSize = long(0)
            totalFile = long(0)
            totalDir = long(0)

            if len(fileList) == 0 or \
                    (maxLevel != -1 and maxLevel <= level):
                return (0, 0, 0)

            # sort by size #
            if SysMgr.showAll:
                fileList.sort( \
                    key=lambda name: os.path.getsize( \
                        '%s/%s' % (parentPath, name)), reverse=True)
            # sort by type #
            else:
                fileList.sort( \
                    key=lambda f: os.path.isfile(os.path.join(parentPath, f)))

            for idx, subPath in enumerate(fileList):
                idc = "|-"

                fullPath = os.path.join(parentPath, subPath)

                # check link #
                if os.path.islink(fullPath):
                    pass

                # check dir #
                if os.path.isdir(fullPath):
                    totalDir += 1

                    string = "%s%s[%s]" % (prefix, idc, subPath)
                    result.append(string)

                    # update prefix #
                    tmpPrefix = prefix + "|  "

                    subdirs = os.listdir(fullPath)

                    rlist = recurse( \
                        fullPath, subdirs, tmpPrefix, \
                            result, level + 1, maxLevel)

                    totalSize += rlist[0]
                    totalDir += rlist[1]
                    totalFile += rlist[2]
                # check file #
                elif os.path.isfile(fullPath):
                    totalFile += 1

                    try:
                        size = os.stat(fullPath).st_size
                        totalSize += size
                        size = ' <%s>' % \
                               UtilMgr.convSize2Unit(size)
                    except:
                        SysMgr.printWarn( \
                            'Fail to get size of %s' % fullPath, reason=True)
                        size = ''

                    if not SysMgr.showAll:
                        continue

                    string = "%s%s%s%s" % (prefix, idc, subPath, size)
                    result.append(string)

            if totalSize:
                tsize = 'SIZE: %s, ' % \
                        UtilMgr.convSize2Unit(totalSize)
            else:
                tsize = ''

            summary = " <%sFILE: %s, DIR: %s>" % \
                      (tsize, UtilMgr.convNum(totalFile),
                       UtilMgr.convNum(totalDir))

            # add summary by reverse traverse #
            if level == 0:
                result[0] += summary
            else:
                tprefix = '%s-[%s]' % \
                          (prefix[:-2], os.path.basename(parentPath))
                for i, val in enumerate(reversed(result)):
                    if not val.startswith(tprefix):
                        continue
                    result[-(i)-1] += summary
                    break

            return (totalSize, totalDir, totalFile)

        # print start path #
        if SysMgr.jsonOutputEnable:
            result = dict()
            if SysMgr.showAll:
                result[os.path.abspath(path)] = \
                    dict(subDirs=dict(), subFiles=dict())
            else:
                result[os.path.abspath(path)] = dict(subDirs=dict())
            getDirs(result, path, 0, -1)
            jsonResult = UtilMgr.convDict2Str(result)
            SysMgr.printPipe(jsonResult)
        else:
            abspath = "[%s]" % (os.path.abspath(path))
            result = [abspath]
            recurse(path, os.listdir(path), "  ", result, 0, maxLevel)
            output = "\n%s\n" % "\n".join(result)
            SysMgr.printStat( \
                r"start traversing dirs from %s..." % abspath)
            SysMgr.printPipe(output)



    @staticmethod
    def doSym2addr():
        SysMgr.printLogo(big=True, onlyFile=True)

        SysMgr.warnEnable = True

        # check input #
        if not SysMgr.inputParam:
            SysMgr.printErr(\
                "No PATH or COMM or PID with -I")
            sys.exit(0)

        # check symbol #
        if len(SysMgr.filterGroup) == 0:
            SysMgr.filterGroup.append('**')

        resInfo = {}
        inputArg = str(SysMgr.inputParam)

        # get pid list #
        pids = SysMgr.getPids(inputArg)
        taskList = []
        for tid in pids:
            taskList.append(SysMgr.getTgid(tid))
        pids = list(set(taskList))

        # a file #
        if len(pids) == 0:
            # check file #
            if os.path.isfile(inputArg):
                filePath = inputArg
                for sym in SysMgr.filterGroup:
                    # create ELF object #
                    try:
                        offset = ElfAnalyzer.getSymOffset(sym, inputArg)
                        if not offset:
                            continue

                        for item in offset:
                            resInfo['%s|%s' % (item[1], filePath)] = \
                                (hex(item[0]), filePath, None)
                    except SystemExit:
                        sys.exit(0)
                    except:
                        SysMgr.printErr(\
                            "Fail to get '%s' info" % sym, True)
                        sys.exit(0)
            else:
                SysMgr.printErr(\
                    "Fail to recognize %s as a file or a process" % inputArg)
                sys.exit(0)
        # multiple process #
        elif len(pids) > 1:
            SysMgr.printErr((\
                "Fail to find a unique process because "
                "multiple processes [ %s ] are found") % ', '.join(pids))
            sys.exit(0)
        # single process #
        else:
            pid = pids[0]

            # get file list on memorymap #
            fileList = FileAnalyzer.getProcMapInfo(pid, onlyExec=True)
            if not fileList:
                SysMgr.printErr("Fail to analyze %s process" % pid)
                sys.exit(0)

            for filePath, attr in fileList.items():
                for sym in SysMgr.filterGroup:
                    # create ELF object #
                    try:
                        res = ElfAnalyzer.getSymOffset(sym, filePath)
                        if not res:
                            continue

                        for item in res:
                            addr = hex(attr['vstart'] + long(item[0]))
                            resInfo['%s|%s' % (item[1], filePath)] = \
                                (hex(item[0]), filePath, addr)
                    except SystemExit:
                        sys.exit(0)
                    except:
                        SysMgr.printWarn(\
                            "Fail to save offset info", True, reason=True)

        SysMgr.printPipe("\n[Symbol Info]\n%s" % twoLine)
        SysMgr.printPipe(\
            "{0:<48} {1:<52} {2:<18} {3:<18}\n{4:1}".format(\
                'Symbol', 'PATH', 'Offset', 'Address', twoLine))

        # print symbols from offset list #
        for sym, val in sorted(resInfo.items()):
            symbol = sym.split('|')[0]
            offset, filePath, addr = val

            if offset is None:
                offset = 'N/A'

            if addr is None:
                addr = 'N/A'

            SysMgr.printPipe(\
                "{0:<48} {1:<52} {2:<18} {3:<18}".format(\
                    symbol, filePath, offset.rstrip('L'), addr.rstrip('L')))

        if len(resInfo) == 0:
            SysMgr.printPipe('\tNone')

        SysMgr.printPipe(oneLine + '\n')



    @staticmethod
    def doLeaktrace():
        def waitAndKill(pid, comm, cond, sig, purpose):
            # define RSS index #
            rssIdx = ConfigMgr.STATM_TYPE.index("RSS")
            condUnit = UtilMgr.convSize2Unit(cond)

            # wait for RSS #
            previous = None
            while 1:
                mlist = SysMgr.getMemStat(pid)
                if not mlist:
                    if not SysMgr.isAlive(pid):
                        SysMgr.printErr(\
                            "%s(%s) is terminated" % (comm, pid))
                    else:
                        SysMgr.printErr(\
                            "Fail to get RSS of %s(%s)" % (comm, pid))
                    sys.exit(0)

                current = long(mlist[rssIdx]) << 12
                currentUnit = UtilMgr.convSize2Unit(current)
                if previous != currentUnit:
                    SysMgr.printInfo(\
                        '%s(%s)\'s RSS for %s: current(%s) / dest(%s)' % \
                            (comm, pid, purpose, currentUnit, condUnit))
                previous = currentUnit

                if cond <= current:
                    break
                time.sleep(1)

            # send signal #
            try:
                os.kill(long(pid), sig)
                SysMgr.printStat(\
                    'sent %s to %s(%s) to %s profiling' % \
                        (ConfigMgr.SIG_LIST[sig], comm, pid, purpose))
            except:
                SysMgr.printErr(\
                    "Fail to send signal %s to %s profiling" % \
                        (ConfigMgr.SIG_LIST[startSig], purpose), reason=True)
                sys.exit(0)

        if not SysMgr.inputParam:
            SysMgr.printErr("No PATH with -I")
            sys.exit(0)

        targetList = SysMgr.filterGroup
        if len(targetList) == 0:
            SysMgr.printErr(\
                "No PID or COMM with -g")
            sys.exit(0)
        elif len(targetList) > 1:
            SysMgr.printErr(\
                "Input only one PID or COMM")
            sys.exit(0)

        # convert comm to pid #
        pids = SysMgr.convertPidList(targetList, exceptMe=True)

        if len(pids) == 0:
            SysMgr.printErr("No %s process" % \
                ', '.join(targetList))
            sys.exit(0)
        elif len(pids) > 1:
            SysMgr.printErr((\
                "Fail to select a target process because "
                "multiple %s processes exist with PID [ %s ]") \
                    % (', '.join(targetList), ', '.join(pids)))
            sys.exit(0)
        else:
            pid = pids[0]
            comm = SysMgr.getComm(pid)

        # create a task object #
        tobj = ThreadAnalyzer(None, onlyInstance=True)

        # check preload result #
        ret = FileAnalyzer.getMapFilePath(pid, 'libleaktracer')
        if ret:
            SysMgr.printStat(\
                '%s is preloaded to %s(%s)' % (ret, comm, pid))
        if not ret:
            envList = SysMgr.getEnv(pid)
            envDict = {}
            for item in envList:
                envset = item.split('=', 1)
                if len(envset) > 1:
                    envDict[envset[0]] = envset[1]
            if not 'LD_PRELOAD' in envDict or \
                not 'libleaktracer' in envDict['LD_PRELOAD']:
                SysMgr.printErr(\
                    'Fail to find libleaktracer.so on memory map '
                    'because the library is not preloaded')
                sys.exit(0)

            SysMgr.printErr(\
                'Fail to find libleaktracer.so on memory map '
                'because the library is not preloaded\n'
                '\tIf the target process is on secure-execution mode,\n'
                '\tlibleaktracer.so should be in standard search directories'
                'specified in /etc/ld.so.conf,\n'
                '\tAnd all slashes in it\'s preload path will be ignored.')
            sys.exit(0)

        # get signals #
        if SysMgr.killFilter:
            sigList = SysMgr.killFilter

            if len(sigList) >= 2:
                startSig = SysMgr.getSigNum(sigList[0][0])
                if not startSig:
                    SysMgr.printErr(\
                        "wrong signal %s for start" % sigList[0][0])
                    sys.exit(0)

                stopSig = SysMgr.getSigNum(sigList[1][0])
                if not stopSig:
                    SysMgr.printErr(\
                        "wrong signal %s for stop" % sigList[1][0])
                    sys.exit(0)
            else:
                startSig = None
                stopSig = SysMgr.getSigNum(sigList[0][0])
                if not stopSig:
                    SysMgr.printErr("wrong signal %s for stop" % sigList[0][0])
                    sys.exit(0)
        else:
            startSig = stopSig = None

        # START #
        startSize = endSize =  0
        if SysMgr.customCmd:
            if len(SysMgr.customCmd) >= 2:
                startSize = UtilMgr.convUnit2Size(SysMgr.customCmd[0])
                endSize = UtilMgr.convUnit2Size(SysMgr.customCmd[1])
            else:
                endSize = UtilMgr.convUnit2Size(SysMgr.customCmd[0])

            if startSize > 0:
                waitAndKill(pid, comm, startSize, startSig, 'start')
        elif startSig:
            try:
                os.kill(long(pid), startSig)
                SysMgr.printStat(\
                    'sent %s to %s(%s) to start profiling' % \
                        (ConfigMgr.SIG_LIST[startSig], comm, pid))
            except:
                SysMgr.printErr(\
                    "Fail to send signal %s to start profiling" % \
                        ConfigMgr.SIG_LIST[startSig], reason=True)
                sys.exit(0)

        # STOP #
        if endSize > 0:
            waitAndKill(pid, comm, endSize, stopSig, 'stop')
        elif stopSig:
            try:
                os.kill(long(pid), stopSig)
                SysMgr.printStat(\
                    'sent %s to %s(%s) to stop profiling' % \
                        (ConfigMgr.SIG_LIST[stopSig], comm, pid))
            except:
                SysMgr.printErr(\
                    "Fail to send signal %s to stop profiling" % \
                        ConfigMgr.SIG_LIST[stopSig], reason=True)
                sys.exit(0)

        SysMgr.printStat('wait for %s' % SysMgr.inputParam)

        # wait for the output file is closed #
        while 1:
            tobj.saveFileStat([[pid], []])
            if not SysMgr.inputParam in tobj.fileData:
                break
            time.sleep(1)
            tobj.reinitStats()

        # wait for the output file is written #
        while not os.path.exists(SysMgr.inputParam) or \
            os.stat(SysMgr.inputParam).st_size == 0:
            time.sleep(1)

        # create leaktracer parser #
        try:
            lt = LeakAnalyzer(SysMgr.inputParam, pid)
            lt.printLeakage()
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Fail to analyze leak", True)



    @staticmethod
    def doNetTest():
        workload = []
        msg = '*' * 4096
        msg = msg.encode()

        def iotask(val):
            prot = val[0].lower()
            if prot == 'tcp':
                tcp = True
                SysMgr.printErr(\
                    "TCP protocol is not supported yet")
                sys.exit(0)
            elif prot == 'udp':
                tcp = False
            else:
                SysMgr.printErr(\
                    "%s protocol is not supported" % prot)
                sys.exit(0)

            gObj = SysMgr.localServObj
            networkObject = NetworkMgr(\
                'client', ip=gObj.ip, port=gObj.port, tcp=tcp)

            while 1:
                networkObject.sendto(msg, val[1], val[2])

            sys.exit(0)

        # set network configuration #
        value = SysMgr.getOption('x')
        if not value:
            NetworkMgr.setServerNetwork(None, None)
        else:
            service, ip, port = NetworkMgr.parseAddr(value)
            NetworkMgr.setServerNetwork(ip, port)

        # get tasks #
        try:
            prot = 'udp'
            ip = '0.0.0.0'
            port = 55555

            jobs = SysMgr.getOption('I')
            if jobs:
                for item in jobs.split(','):
                    task = item.split(':')
                    if len(task) == 1:
                        prot = task[0]
                    elif len(task) == 2:
                        prot = task[0]
                        port = long(task[1])
                    elif len(task) == 3:
                        prot = task[0]
                        ip = task[1]
                        port = long(task[2])
                    else:
                        raise Exception('too many values')

                    workload.append([prot, ip, port])
            else:
                workload.append([prot, ip, port])
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "wrong option value", True)
            sys.exit(0)

        # run tasks #
        ioTasks = dict()
        for idx, item in enumerate(workload):
            try:
                pid = SysMgr.createProcess()
                if pid == 0:
                    iotask(workload[idx])
                else:
                    ioTasks[pid] = workload[idx]
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "Failed to create process", True)
                sys.exit(0)

        # set alarm #
        signal.signal(signal.SIGALRM, SysMgr.onAlarm)
        signal.alarm(SysMgr.intervalEnable)

        # wait for childs #
        while 1:
            if len(ioTasks) == 0:
                break
            SysMgr.waitEvent(ignChldSig=False, exit=True)
            SysMgr.updateChilds()
            if SysMgr.isNoChild():
                break



    @staticmethod
    def doIoTest():
        # gather system info including mount #
        SysMgr()

        workload = []
        writeData = b'0' * 4096

        def flushCache(verb=False):
            try:
                if SysMgr.checkPerm(exit=False, verb=False):
                    dropCachePath = \
                        '%s/sys/vm/drop_caches' % SysMgr.procPath
                    with open(dropCachePath, 'w') as fd:
                        if verb:
                            SysMgr.printInfo(\
                                'start flushing system cache... ', suffix=False)
                        ret = fd.write('3')
                        if verb:
                            SysMgr.printInfo("[Done]", prefix=False, notitle=True)
                else:
                    raise Exception('no root permission')
            except:
                SysMgr.printWarn(\
                    'Fali to flush system cache', reason=True)

        def iotask(num, load):
            def readChunk(fobj, size=4096):
                while 1:
                    ret = os.read(fobj, size)
                    yield ret

            def writeChunk(fobj, sync=False, size=4096):
                while 1:
                    ret = os.write(fobj, writeData[:size])
                    if sync:
                        os.fsync(fobj)
                    yield ret

            SysMgr.setDefaultSignal()

            op = load['op']
            path = load['path']
            flag = os.O_RDWR | os.O_CREAT | os.O_TRUNC

            # set operation #
            if op == 'read':
                opFunc = readChunk
            elif op == 'write':
                opFunc = writeChunk
            else:
                SysMgr.printErr(\
                    "Failed to recognize operation %s" % op)
                sys.exit(0)

            # set direction #
            if op == 'write':
                direct = 'to'
            elif op == 'read':
                direct = 'from'

            # check I/O type #
            if os.path.isfile(path) or \
                SysMgr.isBlkDev(path):
                target = 'file'
            elif os.path.isdir(path):
                if op == 'write':
                    path = os.path.join(path, 'WRTEST')
                else:
                    target = 'dir'
            elif op == 'write' and \
                SysMgr.isWritable(path):
                target = 'file'
            else:
                SysMgr.printErr(\
                    "Failed to access '%s'" % path)
                return

            SysMgr.printInfo(\
                "created a new process to %s %s '%s'" % \
                    (op, direct, path))

            # run loop #
            while 1:
                flushCache()

                totalSize = 0

                if target == 'file':
                    try:
                        fd = os.open(path, flag)
                        for piece in opFunc(fd):
                            if not piece:
                                return
                    except:
                        SysMgr.printErr(SysMgr.getErrMsg())
                        break
                elif target == 'dir':
                    targetList = os.walk(path)

                    for r, d, f in targetList:
                        for item in f:
                            try:
                                fpath = os.path.join(r, item)
                                if not os.path.isfile(fpath):
                                    continue

                                fd = os.open(path, flag)
                                for piece in opFunc(fd):
                                    if not piece:
                                        break
                            except:
                                SysMgr.printWarn(SysMgr.getErrMsg())

        # get tasks #
        try:
            if SysMgr.filterGroup:
                for item in list(SysMgr.filterGroup):
                    item = item.split(':')
                    if len(item) == 1:
                        op = 'read'
                        path = item[0]
                    else:
                        op, path = item

                    if op != 'write' and \
                        not os.path.exists(path):
                        SysMgr.printErr(\
                            "Fail to access %s" % path)
                        sys.exit(0)

                    workload.append(\
                        {'op': op, 'path': path})

            elif SysMgr.showAll:
                for path, value in SysMgr.sysInstance.mountInfo.items():
                    if path.startswith('/dev/') and \
                        not 'loop' in path:

                        stat = os.statvfs(value['path'])
                        size = (stat.f_bsize * stat.f_blocks)

                        workload.append(\
                            {'op': 'read', 'path': path, 'size': size})
            else:
                # get device id #
                fstat = os.lstat('.')
                major = str(os.major(fstat.st_dev))
                minor = str(os.minor(fstat.st_dev))

                # get mount point #
                mountPoint = None
                for path, value in SysMgr.sysInstance.mountInfo.items():
                    if value['major'] == major and \
                        value['minor'] == minor:
                        mountPoint = value['path']
                        break

                if not mountPoint:
                    mountPoint = '.'

                if not os.path.exists(mountPoint):
                    SysMgr.printErr(\
                        "Fail to access %s" % mountPoint)
                    sys.exit(0)

                workload.append(\
                    {'op': 'read', 'path': mountPoint})

        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "wrong option value", True)
            sys.exit(0)

        # drop cache #
        flushCache(verb=True)

        # run tasks #
        ioTasks = dict()
        for cnt in range(0, 1):
            for idx in range(0, len(workload)):
                try:
                    pid = SysMgr.createProcess()
                    if pid == 0:
                        iotask(idx, workload[idx])
                    else:
                        ioTasks[pid] = workload[idx]
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printErr(\
                        "Failed to create process", True)
                    sys.exit(0)

        # set alarm #
        signal.signal(signal.SIGALRM, SysMgr.onAlarm)
        signal.alarm(SysMgr.intervalEnable)

        # wait for childs #
        while 1:
            if len(ioTasks) == 0:
                break
            SysMgr.waitEvent(ignChldSig=False, exit=True)
            SysMgr.updateChilds()
            if SysMgr.isNoChild():
                break



    @staticmethod
    def getGpuInfo():
        def ConvertSMVer2Cores(major, minor):
            # Returns the number of CUDA cores per multiprocessor for a given
            # Compute Capability version. There is no way to retrieve that via
            # the API, so it needs to be hard-coded.
            # See _ConvertSMVer2Cores in helper_cuda.h in NVIDIA's CUDA Samples.
            return {
                # Tesla
                (1, 0):   8,      # SM 1.0
                (1, 1):   8,      # SM 1.1
                (1, 2):   8,      # SM 1.2
                (1, 3):   8,      # SM 1.3
                # Fermi
                (2, 0):  32,      # SM 2.0: GF100 class
                (2, 1):  48,      # SM 2.1: GF10x class
                # Kepler
                (3, 0): 192,      # SM 3.0: GK10x class
                (3, 2): 192,      # SM 3.2: GK10x class
                (3, 5): 192,      # SM 3.5: GK11x class
                (3, 7): 192,      # SM 3.7: GK21x class
                # Maxwell
                (5, 0): 128,      # SM 5.0: GM10x class
                (5, 2): 128,      # SM 5.2: GM20x class
                (5, 3): 128,      # SM 5.3: GM20x class
                # Pascal
                (6, 0):  64,      # SM 6.0: GP100 class
                (6, 1): 128,      # SM 6.1: GP10x class
                (6, 2): 128,      # SM 6.2: GP10x class
                # Volta
                (7, 0):  64,      # SM 7.0: GV100 class
                (7, 2):  64,      # SM 7.2: GV11b class
                # Turing
                (7, 5):  64,      # SM 7.5: TU10x class
            }.get((major, minor), 64)   # unknown architecture, return a default value

        CUDA_SUCCESS = 0
        CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT = 16
        CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_MULTIPROCESSOR = 39
        CU_DEVICE_ATTRIBUTE_CLOCK_RATE = 13
        CU_DEVICE_ATTRIBUTE_MEMORY_CLOCK_RATE = 36

        if not SysMgr.importPkgItems('ctypes', False):
            return None

        nGpus = c_int()
        name = b' ' * 100
        cc_major = c_int()
        cc_minor = c_int()
        cores = c_int()
        threads_per_core = c_int()
        clockrate = c_int()
        freeMem = c_size_t()
        totalMem = c_size_t()

        result = c_int()
        device = c_int()
        context = c_void_p()
        error_str = c_char_p()

        try:
            cuda = SysMgr.loadLib('libcuda.so')
        except:
            return None

        result = cuda.cuInit(0)
        if result != CUDA_SUCCESS:
            return None

        result = cuda.cuDeviceGetCount(byref(nGpus))
        if result != CUDA_SUCCESS:
            return None

        gpuInfo = {}

        for i in range(nGpus.value):
            result = cuda.cuDeviceGet(byref(device), i)
            if result != CUDA_SUCCESS:
                return None

            gpuInfo[i] = dict()

            if cuda.cuDeviceGetName(c_char_p(name), len(name), device) == CUDA_SUCCESS:
                gpuInfo[i]['name'] = name.split(b'\0', 1)[0].decode()

            if cuda.cuDeviceComputeCapability(\
                byref(cc_major), byref(cc_minor), device) == CUDA_SUCCESS:
                gpuInfo[i]['capa'] = "%d.%d" % (cc_major.value, cc_minor.value)

            if cuda.cuDeviceGetAttribute(\
                byref(cores), CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT, device) == CUDA_SUCCESS:
                gpuInfo[i]['processor'] = cores.value
                gpuInfo[i]['core'] = cores.value * \
                    ConvertSMVer2Cores(cc_major.value, cc_minor.value)

                if cuda.cuDeviceGetAttribute(\
                    byref(threads_per_core), \
                    CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_MULTIPROCESSOR, device) == CUDA_SUCCESS:
                    gpuInfo[i]['threads'] = cores.value * threads_per_core.value

            if cuda.cuDeviceGetAttribute(\
                byref(clockrate), CU_DEVICE_ATTRIBUTE_CLOCK_RATE, device) == CUDA_SUCCESS:
                gpuInfo[i]['gpuClock(MHz)'] = clockrate.value / 1000.

            if cuda.cuDeviceGetAttribute(\
                byref(clockrate), CU_DEVICE_ATTRIBUTE_MEMORY_CLOCK_RATE, device) == CUDA_SUCCESS:
                gpuInfo[i]['memClock(MHz)'] = clockrate.value / 1000.

            result = cuda.cuCtxCreate(byref(context), 0, device)
            if result == CUDA_SUCCESS:
                result = cuda.cuMemGetInfo(byref(freeMem), byref(totalMem))
                if result == CUDA_SUCCESS:
                    gpuInfo[i]['totalMem(MB)'] = totalMem.value / 1024**2
                    gpuInfo[i]['freeMem(MB)'] = freeMem.value / 1024**2

                cuda.cuCtxDetach(context)

        return gpuInfo



    @staticmethod
    def doGpuTest():
        pass



    @staticmethod
    def doCpuTest():
        random = SysMgr.getPkg('random')

        def cputask(num, load):
            SysMgr.setDefaultSignal()

            # run loop #
            while 1:
                sorted([random.random() for i in range(1<<10)])

        # get the number of task and load #
        try:
            if len(sys.argv) < 3:
                raise Exception("no value")

            # parse values #
            value = sys.argv[2].split(':')
            if len(value) > 2:
                raise Exception()
            elif len(value) == 2:
                totalLoad, nrTask = list(map(long, value))
                if nrTask == 0:
                    nrTask = 1
                load = totalLoad / nrTask
            else:
                totalLoad = long(value[0])
                nrTask = totalLoad / 100
                modLoad = totalLoad % 100

                if modLoad > 0:
                    nrTask += 1

                load = long(totalLoad / nrTask)

            nrTask = long(nrTask)
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                ("wrong option value because %s, "
                    "input integer number in the format LOAD{:NRTASK}") % \
                        SysMgr.getErrMsg())
            sys.exit(0)

        if nrTask > 1:
            taskstr = '%d processes' % nrTask
        else:
            taskstr = 'a process'

        # run tasks #
        limitInfo = dict()
        for idx in range(0, nrTask):
            try:
                pid = SysMgr.createProcess()
                if pid == 0:
                    cputask(idx, load)
                else:
                    limitInfo[pid] = load
            except SystemExit:
                pass
            except:
                SysMgr.printErr(\
                    "Failed to create process", True)
                sys.exit(0)

        if len(limitInfo) > 1:
            taskstr = '%d processes' % len(limitInfo)
        else:
            taskstr = 'a process'

        SysMgr.printInfo((\
            "created %s and limited them to use CPU a total of %d%% " \
            "and %d%% respectively") % \
                (taskstr, totalLoad, load))

        # set affinity #
        for pid in list(limitInfo.keys()):
            for item in SysMgr.affinityFilter:
                SysMgr.setAffinity(item[0], [pid])

        # set alarm #
        signal.signal(signal.SIGALRM, SysMgr.onAlarm)
        signal.alarm(SysMgr.intervalEnable)

        # ignore SIGCHLD #
        signal.signal(signal.SIGCHLD, signal.SIG_DFL)

        # limit CPU usage of tasks #
        SysMgr.doLimitCpu(limitInfo, verbose=False)



    @staticmethod
    def doMemTest():
        def getMeminfo():
            # save mem info #
            try:
                memBuf = None
                SysMgr.memFd.seek(0)
                memBuf = SysMgr.memFd.readlines()
            except:
                try:
                    memPath = "%s/%s" % (SysMgr.procPath, 'meminfo')
                    SysMgr.memFd = open(memPath, 'r')

                    memBuf = SysMgr.memFd.readlines()
                except:
                    SysMgr.printOpenWarn(memPath)

            if not memBuf:
                return ''

            memData = {}

            for line in memBuf:
                memList = line.split()
                memData[memList[0][:-1]] = long(memList[1])

            conv = UtilMgr.convSize2Unit
            memTotal = conv(memData['MemTotal'] << 10)
            memFree = conv(memData['MemFree'] << 10)
            memFreePer = \
                (memData['MemFree'] / float(memData['MemTotal'])) * 100
            try:
                memAvail = conv(memData['MemAvailable'] << 10)
                memAvailPer = \
                    (memData['MemAvailable'] / float(memData['MemTotal'])) * 100
                memAvailPer = '%.1f%%' % memAvailPer
            except:
                memAvail = memAvailPer = '-'
            memCache = conv(memData['Cached'] << 10)
            swapTotal = conv(memData['SwapTotal'] << 10)
            swapFree = conv(memData['SwapFree'] << 10)
            if swapTotal == '0':
                swapFreePer = 100.0
            else:
                swapFreePer = \
                    (memData['SwapFree'] / float(memData['SwapTotal'])) * 100

            memstr = ('\n[%9s] MemTotal: %s, MemFree: %s(%.1f%%), '
                'MemAvail: %s(%s), Cached: %s, SwapTotal: %s, '
                'SwapFree: %s(%.1f%%)') % \
                    ('TOTAL', memTotal, memFree, memFreePer, memAvail, \
                        memAvailPer, memCache, swapTotal, swapFree, swapFreePer)

            return memstr

        def getVminfo():
            # save mem info #
            try:
                vmBuf = None
                SysMgr.vmstatFd.seek(0)
                vmBuf = SysMgr.vmstatFd.readlines()
            except:
                try:
                    vmstatPath = "%s/%s" % (SysMgr.procPath, 'vmstat')
                    SysMgr.vmstatFd = open(vmstatPath, 'r')
                    vmBuf = SysMgr.vmstatFd.readlines()
                except:
                    SysMgr.printOpenWarn(vmstatPath)

            if not vmBuf:
                return ''

            vmData = {}

            zonestr = '\n'
            conv = UtilMgr.convSize2Unit
            for line in vmBuf:
                vmList = line.split()
                item = vmList[0]
                if item.startswith('pgscan_') or \
                    item.startswith('pgstreal_') or \
                    item.startswith('kswapd_') or \
                    item.startswith('compact_') or \
                    item.startswith('oom_') or \
                    item.startswith('pswin'):
                    vmData[item] = long(vmList[1])

            cnt = 1
            vmstr = '\n[%9s] ' % 'VMSTAT'
            for vm, item in sorted(vmData.items()):
                vmstr += '%s: %s, ' % (vm, conv(item << 12))
                if cnt % 4 == 0 and cnt != len(vmData):
                    vmstr += '\n[%9s] ' % 'VMSTAT'
                cnt += 1

            return vmstr[:-2]

        def getZoneinfo():
            # save zone info #
            try:
                memBuf = None
                SysMgr.zoneFd.seek(0)
                memBuf = SysMgr.zoneFd.readlines()
            except:
                try:
                    memPath = "%s/%s" % (SysMgr.procPath, 'zoneinfo')
                    SysMgr.zoneFd = open(memPath, 'r')

                    memBuf = SysMgr.zoneFd.readlines()
                except:
                    SysMgr.printOpenWarn(memPath)

            if not memBuf:
                return ''

            memData = {}
            conv = UtilMgr.convSize2Unit

            zone = None
            for line in memBuf:
                zl = line.split()
                item = zl[0]
                if item  == 'Node':
                    zone = '%s-%s' % (zl[1][:-1], zl[3])
                    memData[zone] = dict()
                elif item == 'pages' and zl[1] == 'free':
                    memData[zone]['free'] = long(zl[2])
                elif item == 'min' or item == 'low' or item == 'high' or \
                    item == 'spanned' or item == 'present' or item == 'managed':
                    memData[zone][item] = long(zl[1])
                elif item == 'protection:':
                    values = []
                    for item in zl[1:]:
                        if item.startswith('('):
                            item = item[1:]
                        if item.endswith(',') or \
                            item.endswith(')'):
                            item = item[:-1]
                        values.append(item)

                    values = list(map(lambda x: conv(long(x) << 12), values))
                    memData[zone]['protection'] = values
                else:
                    continue

            zonestr = '\n'
            for zone, items in sorted(memData.items()):
                zonestr += '[%9s] ' % zone
                for name, val in sorted(items.items(), \
                    key=lambda e: long(e[1]) if type(e[1]) != list else sys.maxsize):
                    if name != 'protection':
                        zonestr += "%s:%7s, " % (name, conv(val << 12))

                if 'protection' in items:
                    zonestr += "%s: %7s" % ('protection', ', '.join(items['protection']))
                    zonestr += ", "

                zonestr = zonestr + '\n'

            return zonestr[:-2]

        def getLMKinfo():
            # save LMK info #
            try:
                memBuf = None
                SysMgr.lmkFd.seek(0)
                memBuf = SysMgr.lmkFd.readline()
            except:
                try:
                    memPath = SysMgr.lmkPath
                    SysMgr.lmkFd = open(memPath, 'r')
                    memBuf = SysMgr.lmkFd.readline()
                except:
                    SysMgr.printOpenWarn(memPath)

            # threshold list #
            threshold = \
                ['FGAPP', 'VISAPP', 'SECSER', 'HIDAPP', 'CONPRO', 'EMPAPP']

            if not memBuf:
                return ''

            stats = memBuf.split(',')
            if stats:
                stats = list(map(long, stats))

            lmkstr = '\n[%9s] ' % 'LMK'

            for idx, item in enumerate(stats):
                lmkstr = '%s%s: %s, ' % \
                    (lmkstr, threshold[idx], \
                        UtilMgr.convSize2Unit(item << 12))

            return '%s' % lmkstr[:-2]

        def allocMemory(size, wrPipe=None, ret=False):
            SysMgr.setDefaultSignal()

            # allocate memory #
            try:
                SysMgr.procBuffer = bytearray(size)
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "Fail to allocate memory", True)
                sys.exit(0)

            if wrPipe:
                os.write(wrPipe, '1'.encode())

            if ret:
                return

            SysMgr.waitEvent()

            sys.exit(0)

        def printUsage(obj, pid, size, alloc=True):
            conv = UtilMgr.convSize2Unit

            # get system stat #
            try:
                memstr = getMeminfo()
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr("Fail to get memory stat", True)
                return

            # get vmstat #
            try:
                vmstr = getVminfo()
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr("Fail to get virtual memory stat", True)
                return

            # get zone stat #
            try:
                zonestr = getZoneinfo()
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr("Fail to get zone memory stat", True)
                return

            # get LMK stat #
            try:
                lmkstr = getLMKinfo()
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printWarn("Fail to get LMK stat", reason=True)

            # get process stat #
            pid = str(pid)
            procPath = '%s/%s' % (SysMgr.procPath, pid)
            obj.saveProcStat()
            if SysMgr.isRoot():
                obj.saveProcSmapsData(procPath, pid)
                ret = obj.getMemDetails(pid, obj.procData[pid]['maps'])
                statstr = "RSS: %s, PSS: %s, USS: %s" % \
                    (conv(ret[1] << 10), conv(ret[2] << 10), conv(ret[3] << 10))
            else:
                # save RSS stat #
                mlist = SysMgr.getMemStat(pid)
                if not mlist:
                    SysMgr.printErr(\
                        "Fail to get memory size of Guider")
                    sys.exit(0)

                # get memory size #
                rssIdx = ConfigMgr.STATM_TYPE.index("RSS")
                statstr = "RSS: %s" % conv(long(mlist[rssIdx]) << 12)

            # get new task #
            newTasks = set(obj.procData.keys()) - set(obj.prevProcData.keys())
            if newTasks:
                newstr = '\n[%9s]' % 'NEW'
                for pid in sorted(newTasks):
                    comm = obj.procData[pid]['stat'][obj.commIdx][1:-1]
                    rss = conv(long(obj.procData[pid]['stat'][obj.rssIdx])<<12)
                    newstr = '%s %s(%s)[%s], ' % (newstr, comm, pid, rss)
                newstr = newstr[:-2]
            else:
                newstr = ''

            # get die task #
            dieTasks =  set(obj.prevProcData.keys()) - set(obj.procData.keys())
            if dieTasks:
                diestr = '\n[%9s]' % 'DIE'
                for pid in sorted(dieTasks):
                    comm = obj.prevProcData[pid]['stat'][obj.commIdx][1:-1]
                    rss = conv(long(obj.prevProcData[pid]['stat'][obj.rssIdx])<<12)
                    diestr = '%s %s(%s)[%s], ' % (diestr, comm, pid, rss)
                diestr = diestr[:-2]
            else:
                diestr = ''

            if alloc:
                allocstr = \
                    '\n[%9s] SIZE: %s, %s' % \
                        ('ALLOC', conv(size, True), statstr)
            else:
                allocstr = '\n[%9s] %s' % ('TIME', SysMgr.updateUptime())

            SysMgr.printPipe('%s%s%s%s%s%s%s' % \
                (allocstr, memstr, vmstr, zonestr, lmkstr, newstr, diestr),
                pager=False)

        # convert time #
        try:
            if len(sys.argv) < 3:
                raise Exception("no value")

            # parse option #
            value = sys.argv[2].split(':')
            if len(value) == 3:
                size, interval, count = value
            elif len(value) == 2:
                size, interval = value
                count = long(0)
            elif len(value) == 1:
                size = value[0]
                interval = count = long(0)
            else:
                raise Exception()

            if interval:
                interval = UtilMgr.convUnit2Time(interval)
            else:
                interval = long(0)

            count = long(count)

            # convert memory size #
            size = UtilMgr.convUnit2Size(size)
            if not size:
                raise Exception()
        except SystemExit:
            sys.exit(0)
        except:
            errMsg = ("wrong option value because %s, "
                "input integer number in the format SIZE{:INTERVAL:COUNT}") % \
                    SysMgr.getErrMsg()
            SysMgr.printErr(errMsg)
            sys.exit(0)

        # set alarm #
        signal.signal(signal.SIGALRM, SysMgr.onAlarm)
        signal.alarm(SysMgr.intervalEnable)

        # create task object #
        obj = ThreadAnalyzer(onlyInstance=True)
        obj.saveProcStat()
        pid = SysMgr.pid

        pidList = list()
        if count > 0:
            for idx in range(0, count):
                try:
                    # create a pipe #
                    rd, wr = os.pipe()

                    pid = SysMgr.createProcess()
                except SystemExit:
                    pass
                except:
                    SysMgr.printErr(\
                        "Failed to start process", True)
                    sys.exit(0)

                if pid == 0:
                    try:
                        allocMemory(size, wr)
                    except SystemExit:
                        sys.exit(0)
                    except:
                        SysMgr.printErr("Fail to alloc memory", True)
                        sys.exit(0)
                else:
                    pidList.append(pid)
                    os.close(wr)

                    os.read(rd, 1)
                    os.close(rd)

                    # print stats #
                    try:
                        printUsage(obj, pid, size)
                    except SystemExit:
                        sys.exit(0)
                    except:
                        SysMgr.printErr(\
                            "Fail to print memory stats", reason=True)

                time.sleep(interval)
        elif interval > 0:
            while 1:
                # create a pipe #
                rd, wr = os.pipe()

                try:
                    pid = SysMgr.createProcess()
                except SystemExit:
                    pass
                except:
                    SysMgr.printErr(\
                        "Failed to start process", True)
                    sys.exit(0)

                if pid == 0:
                    try:
                        allocMemory(size, wr)
                    except SystemExit:
                        sys.exit(0)
                    except:
                        SysMgr.printErr("Fail to alloc memory", True)
                        sys.exit(0)
                else:
                    pidList.append(pid)
                    os.close(wr)

                    os.read(rd, 1)
                    os.close(rd)

                    # print stats #
                    try:
                        printUsage(obj, pid, size)
                    except SystemExit:
                        sys.exit(0)
                    except:
                        SysMgr.printErr(\
                            "Fail to print memory stats", reason=True)

                time.sleep(interval)
        else:
            try:
                interval = 1

                pidList.append(pid)

                allocMemory(size, ret=True)

                # print stats #
                try:
                    printUsage(obj, pid, size)
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printErr(\
                        "Fail to print memory stats", reason=True)

                time.sleep(interval)
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr("Fail to alloc memory", True)
                sys.exit(0)

        # wait for childs #
        if len(pidList) > 0:
            while 1:
                try:
                    printUsage(obj, pid, size, alloc=False)
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printErr(\
                        "Fail to print memory stats", reason=True)

                time.sleep(interval)



    @staticmethod
    def doPstree(isProcess=True):
        SysMgr.printLogo(big=True, onlyFile=True)

        obj = ThreadAnalyzer(onlyInstance=True)

        obj.saveSystemStat()

        ThreadAnalyzer.printProcTree(obj.procData)

        sys.exit(0)



    @staticmethod
    def doSystat(isProcess=True):
        SysMgr.printLogo(big=True, onlyFile=True)

        # enable default attributes #
        SysMgr.showAll = True
        SysMgr.memEnable = True
        SysMgr.cgroupEnable = True
        SysMgr.cmdlineEnable = True
        SysMgr.delayEnable = True
        SysMgr.irqEnable = True
        SysMgr.perfEnable = True
        SysMgr.nsEnable = True
        SysMgr.ttyRows = sys.maxsize

        if SysMgr.isRoot():
            SysMgr.diskEnable = True
            SysMgr.blockEnable = True
            SysMgr.networkEnable = True
        else:
            SysMgr.printWarn(\
                "Fail to get disk and network stats "
                "because no root permission")

        # initialize perf events #
        SysMgr.initSystemPerfEvents()

        # initialize system stat #
        SysMgr()
        obj = ThreadAnalyzer(onlyInstance=True)
        obj.saveSystemStat()

        if SysMgr.intervalEnable:
            time.sleep(SysMgr.intervalEnable)
        else:
            time.sleep(1)

        # save system stat #
        obj.reinitStats()
        obj.saveSystemStat()

        # print stat #
        if SysMgr.jsonOutputEnable:
            # process system stat #
            obj.printSystemUsage()

            # process task stat #
            obj.printProcUsage()
        else:
            # process system stat #
            obj.printSystemStat()

        SysMgr.printTopStats()

        sys.exit(0)



    @staticmethod
    def updateStatList(statList, commIdx=None):
        if not commIdx:
            commIdx = ConfigMgr.STAT_ATTR.index("COMM")

        # merge comm parts that splited by space #
        if statList[commIdx][-1] != ')':
            idx = commIdx + 1
            while 1:
                tmpStr = str(statList[idx])
                statList[commIdx] = \
                    "%s %s" % (statList[commIdx], tmpStr)
                statList.pop(idx)
                if ')' in tmpStr:
                    break

        return statList



    @staticmethod
    def doLimitCpu(limitInfo, isProcess=False, verbose=True):
        CLK_PRECISION = 100000
        MAX_BUCKET = CLK_PRECISION / 1000
        SLEEP_SEC = 1 / float(MAX_BUCKET)
        COMM_IDX = ConfigMgr.STAT_ATTR.index("COMM")
        UTIME_IDX = ConfigMgr.STAT_ATTR.index("UTIME")
        STIME_IDX = ConfigMgr.STAT_ATTR.index("STIME")
        NR_TARGET = len(limitInfo)

        elapsed = long(0)
        nowTime = None
        taskList = {}

        def openStatFd(tid, isProcess):
            if isProcess:
                statPath = "%s/%s/stat" % \
                    (SysMgr.procPath, tid)
            else:
                statPath = "%s/%s/task/%s/stat" % \
                    (SysMgr.procPath, tid, tid)

            try:
                return open(statPath, 'r')
            except:
                return None

        def getTaskStat(fd):
            try:
                fd.seek(0)
                statBuf = fd.readlines()[0]
            except:
                return None

            # convert string to list #
            statList = statBuf.split()

            # merge comm parts that splited by space #
            statList = SysMgr.updateStatList(statList, COMM_IDX)

            comm = statList[COMM_IDX][1:-1]
            cputime = long(statList[UTIME_IDX]) + long(statList[STIME_IDX])
            return (comm, cputime)

        # initialize task list #
        for task, per in limitInfo.items():
            taskList[task] = \
                {'per': per, 'nowTick': long(0), 'prevTick': long(0), \
                'ticks': long(0), 'running': True}

            if isProcess:
                taskList[task]['group'] = SysMgr.getThreadList(task)
                if not taskList[task]['group']:
                    SysMgr.printErr(\
                        "Fail to get thread list of '%s' process" % task)
                    return

                taskList[task]['fd'] = openStatFd(task, isProcess)
                if not taskList[task]['fd']:
                    SysMgr.printErr(\
                        "Fail to get stats of %s thread" % task)
                    return
            else:
                taskList[task]['group'] = [int(task)]
                taskList[task]['fd'] = openStatFd(task, isProcess)
                if not taskList[task]['fd']:
                    SysMgr.printErr(\
                        "Fail to get stats of %s thread" % task)
                    return

        # set alarm #
        signal.signal(signal.SIGALRM, SysMgr.onAlarm)
        signal.alarm(SysMgr.intervalEnable)

        try:
            while 1:
                # backup time #
                prevTime = nowTime

                # get current time #
                nowTime = time.time()

                for tid in list(taskList.keys()):
                    val = taskList[tid]
                    val['prevTick'] = val['nowTick']

                    # get current tick #
                    stat = getTaskStat(val['fd'])
                    if not stat:
                        SysMgr.printErr(\
                            "Fail to get CPU time of %s thread" % tid)
                        taskList.pop(tid, None)
                    else:
                        val['comm'], val['nowTick'] = stat

                if len(taskList) == 0:
                    SysMgr.printErr(\
                        "Fail to find task to limit cpu")
                    return

                if not prevTime:
                    continue

                for tid, val in taskList.items():
                    # get used tick for interval #
                    diffTick = val['nowTick'] - val['prevTick']
                    val['ticks'] += diffTick

                # get interval time #
                diffTime = nowTime - prevTime
                elapsed += diffTime
                if elapsed >= 1:
                    elapsed = long(0)

                    for tid, val in taskList.items():
                        # update thread list in a process #
                        if isProcess:
                            taskList[tid]['group'] = SysMgr.getThreadList(tid)
                            if not taskList[tid]['group']:
                                continue

                            tasktype = 'process'
                        else:
                            tasktype = 'thread'

                        if verbose:
                            SysMgr.printInfo((\
                                "limited CPU usage of %s(%s) %s to %s%%, "
                                "it used %s%%") % \
                                (val['comm'], tid, tasktype, \
                                val['per'], val['ticks']))

                        val['ticks'] = long(0)
                    continue

                for tid, val in taskList.items():
                    limitTick = val['per'] * elapsed

                    # exceed limited tick #
                    if val['ticks'] > limitTick:
                        if val['running']:
                            for tid in val['group']:
                                try:
                                    os.kill(tid, signal.SIGSTOP)
                                except SystemExit:
                                    raise Exception()
                                except:
                                    SysMgr.printSigError(tid, 'SIGSTOP')
                            val['running'] = False
                    # continue #
                    else:
                        if not val['running']:
                            val['running'] = True
                            for tid in val['group']:
                                try:
                                    os.kill(tid, signal.SIGCONT)
                                except SystemExit:
                                    raise Exception()
                                except:
                                    SysMgr.printSigError(tid, 'SIGCONT')

                time.sleep(SLEEP_SEC)
        except:
            pass
        finally:
            for task, val in taskList.items():
                for tid in val['group']:
                    try:
                        os.kill(tid, signal.SIGCONT)
                    except SystemExit:
                        pass
                    except:
                        SysMgr.printSigError(tid, 'SIGCONT')



    @staticmethod
    def terminateTasks(targetList, sig=ConfigMgr.SIGKILL, group=False):
        if group:
            kill = os.killpg
        else:
            kill = os.kill

        for pid in targetList:
            try:
                kill(pid, sig)
            except:
                SysMgr.printSigError(pid, 'SIGKILL')



    @staticmethod
    def convertPidList(\
        procList, isThread=False, exceptMe=False, withSibling=False):
        if not procList:
            return

        targetList = []

        # get pids #
        for pid in procList:
            taskList = SysMgr.getPids(pid, isThread, withSibling)
            targetList += taskList

        # remove redundant items #
        finalList = list(set(targetList))

        if exceptMe:
            try:
                finalList.remove(SysMgr.pid)
            except:
                pass

        return finalList



    @staticmethod
    def getSigNum(val):
        if val.isdigit():
            return long(val)

        val = val.upper()
        if val in ConfigMgr.SIG_LIST:
            return ConfigMgr.SIG_LIST.index(val)

        val = 'SIG%s' % val
        if val in ConfigMgr.SIG_LIST:
            return ConfigMgr.SIG_LIST.index(val)

        return None



    @staticmethod
    def sendSignalArgs(argList, isThread=False):
        sig = signal.SIGQUIT
        SIG_LIST = ConfigMgr.SIG_LIST
        if not argList:
            return

        # get signal candidates #
        options = [item for item in argList if item.startswith('-')]

        isFound = False
        for val in options:
            try:
                sig = SysMgr.getSigNum(val[1:])
                if not sig:
                    continue

                isFound = True
                del argList[argList.index(val)]
                break
            except:
                pass

        # check type #
        if not isFound:
            sig = signal.SIGINT

        # convert pid list #
        if SysMgr.filterGroup:
            argList = SysMgr.filterGroup
        else:
            try:
                argList = (''.join(argList)).split(',')
            except:
                pass

        # convert comm to pid #
        targetList = SysMgr.convertPidList(argList, exceptMe=True)

        # send signal #
        SysMgr.sendSignalProcs(sig, targetList, isThread=isThread)



    @staticmethod
    def sendSignalProcs(nrSig, pidList, isThread=False, verbose=True):
        def kill(pid, nrSig):
            if isThread:
                return SysMgr.syscall('tkill', pid, nrSig)
            else:
                return os.kill(pid, nrSig)

        myPid = str(SysMgr.pid)
        SIG_LIST = ConfigMgr.SIG_LIST

        if isThread:
            taskType = 'thread'
        else:
            taskType = 'process'

        nrProc = long(0)
        if type(pidList) is list and len(pidList) > 0:
            for pid in pidList:
                # check pid type #
                try:
                    pid = long(pid)
                except:
                    SysMgr.printErr(\
                        "Fail to recognize PID %s to send signal" % pid)
                    return

                # skip myself #
                if pid == SysMgr.pid:
                    continue

                # send signal to a process #
                try:
                    kill(long(pid), nrSig)

                    # get comm #
                    comm = SysMgr.getComm(pid)

                    if verbose:
                        SysMgr.printInfo(\
                            "sent signal %s to %s(%s) %s" % \
                                (SIG_LIST[nrSig], comm, pid, taskType))

                    nrProc += 1
                except:
                    SysMgr.printSigError(pid, SIG_LIST[nrSig])

            if nrProc == 0 and verbose:
                SysMgr.printInfo("No running process in the background")

            return

        # get my comm #
        myComm = SysMgr.getComm(SysMgr.pid)
        if not myComm:
            SysMgr.printErr(\
                "Fail to get my comm", True)
            sys.exit(0)

        # get my cmdline #
        myCmdline = SysMgr.getCmdline(SysMgr.pid)
        if myCmdline:
            myCmdline = myCmdline.split()
        else:
            SysMgr.printErr(\
                "Fail to get my cmdline", True)
            sys.exit(0)

        # handle Guider processes #
        nrProc = long(0)
        for pid in os.listdir(SysMgr.procPath):
            if myPid == pid or not pid.isdigit():
                continue

            # check comm #
            comm = SysMgr.getComm(pid)
            if not comm or not comm.startswith(myComm):
                continue

            # check cmdline again #
            if myComm != __module__:
                cmdlineList = SysMgr.getCmdline(pid, True)
                if len(cmdlineList) > 2 and myCmdline[:2] != cmdlineList[:2]:
                    continue

            if nrSig == signal.SIGINT:
                waitStatus = False

                try:
                    cmdList = SysMgr.getCmdline(pid, True)
                    for val in cmdList:
                        if val == '-c':
                            waitStatus = True
                except:
                    continue

                # get comm #
                comm = SysMgr.getComm(pid)

                if SysMgr.isStartMode() and waitStatus:
                    try:
                        kill(long(pid), nrSig)
                        if verbose:
                            SysMgr.printInfo(\
                                "started %s process to profile" % pid)
                    except:
                        SysMgr.printSigError(pid, SIG_LIST[nrSig])
                elif SysMgr.isStopMode():
                    try:
                        kill(long(pid), nrSig)
                        if verbose:
                            SysMgr.printInfo(\
                                "sent signal %s to %s(%s) %s" % \
                                    (SIG_LIST[nrSig], comm, pid, taskType))
                    except:
                        SysMgr.printSigError(pid, SIG_LIST[nrSig])
            else:
                try:
                    kill(long(pid), nrSig)

                    # get comm #
                    comm = SysMgr.getComm(pid)

                    if verbose:
                        SysMgr.printInfo(\
                            "sent signal %s to %s(%s) %s" % \
                                (SIG_LIST[nrSig], comm, pid, taskType))
                except:
                    SysMgr.printSigError(pid, SIG_LIST[nrSig])

            nrProc += 1

        if nrProc == 0 and verbose:
            SysMgr.printInfo("No running process in the background")



    @staticmethod
    def getThreadList(tid):
        taskPath = "%s/%s/task" % (SysMgr.procPath, tid)

        try:
            return list(map(long, os.listdir(taskPath)))
        except:
            return None



    @staticmethod
    def getDeadlineArgs(value):
        value = value.split('/')
        if len(value) == 3:
            return list(map(long, value))
        elif len(value) == 2:
            value.append(value[-1])
            return list(map(long, value))
        else:
            return [0, 0, 0]



    @staticmethod
    def parsePriorityOption(value):
        if len(value) == 0:
            SysMgr.printErr(\
                ("wrong option value %s with -Y, "
                "input POLICY:PRIORITY|TIME:PID in the format") % value)
            sys.exit(0)

        SysMgr.checkPerm()

        schedGroup = value.split(',')
        schedGroup = SysMgr.clearList(schedGroup)
        for item in schedGroup:
            schedSet = item.split(':')
            try:
                policy = schedSet[0].upper()
                ConfigMgr.SCHED_POLICY.index(policy)
                pri = long(schedSet[1])

                # change myself #
                if len(schedSet) == 2:
                    tid = SysMgr.pid
                    SysMgr.prio = pri
                # change others #
                else:
                    tid = schedSet[2]

                # check tid #
                if UtilMgr.isNumber(tid):
                    isTid = True
                else:
                    isTid = False

                # get thread list #
                withSibling = SysMgr.groupProcEnable
                targetList = SysMgr.getPids(tid, withSibling=withSibling)
                targetList = list(map(long, targetList))

                if not targetList:
                    SysMgr.printErr(\
                        "No threads related to %s" % tid)
                    sys.exit(0)

                for tid in targetList:
                    if schedSet[0].upper() == 'D':
                        # parse deadline arguments #
                        runtime, deadline, period = \
                            SysMgr.getDeadlineArgs(schedSet[1])

                        # set deadline sched #
                        SysMgr.setDeadlinePriority(\
                            tid, runtime, deadline, period)
                    else:
                        SysMgr.setPriority(tid, policy, pri)

                # change others continually #
                if len(schedSet) == 4:
                    if schedSet[3] != 'CONT':
                        raise Exception("wrong last value")

                    # add sched item to list #
                    SysMgr.schedFilter.append([policy, pri, tid])
            except SystemExit:
                sys.exit(0)
            except:
                err = map(str, sys.exc_info()[1].args)
                SysMgr.printErr((\
                    "wrong option value %s with -Y because %s, "
                    "input in the format POLICY:PRIORITY|TIME:TID") % \
                    (item, ' '.join(list(err))))
                sys.exit(0)



    @staticmethod
    def setDeadlinePriority(pid, runtime, deadline, period):
        # check kernel version #
        try:
            ver = SysMgr.getKernelVersion().split('.')[0:2]
            ver = float('.'.join(ver))
            # check whether kernel version is higher than 3.14 #
            if ver < 3.14:
                SysMgr.printErr((\
                    "Fail to set priority of %d "
                    "because kernel version %g is lesser than 3.14") % \
                    (pid, ver))
                return -1
        except:
            err = sys.exc_info()[1]
            SysMgr.printWarn(\
                ("Fail to check kernel version because %s "
                "to set deadline priority") % err.args[0], True)
            return -1

        # get ctypes object #
        SysMgr.importPkgItems('ctypes')

        if not SysMgr.loadLibcObj():
            sys.exit(0)

        # define struct sched_attr #
        class struct_sched_attr(Structure):
            pass

        struct_sched_attr._slots_ = [
            'size',
            'sched_policy',
            'sched_flags',
            'sched_nice',
            'sched_priority',
            'sched_runtime',
            'sched_deadline',
            'sched_period',
        ]

        struct_sched_attr._fields_ = [
            ('size', c_uint32),
            ('sched_policy', c_uint32),
            ('sched_flags', c_uint64),
            ('sched_nice', c_int32),
            ('sched_priority', c_uint32),
            ('sched_runtime', c_uint64),
            ('sched_deadline', c_uint64),
            ('sched_period', c_uint64),
        ]

        # get the number of sched_setattr systemcall #
        nrSyscall = ConfigMgr.sysList.index('sys_sched_setattr')

        # define syscall parameters for sched_setattr() #
        SysMgr.libcObj.syscall.argtypes = \
            [c_int, c_int, POINTER(struct_sched_attr), c_uint]
        SysMgr.libcObj.syscall.restype = c_int

        # set parameters #
        sched_attr = struct_sched_attr()
        sched_attr.size = c_uint32(sizeof(sched_attr))
        sched_attr.sched_flags = c_uint64(0)
        sched_attr.sched_nice = c_int32(0)
        sched_attr.sched_priority = c_uint32(0)
        sched_attr.sched_policy = c_uint32(ConfigMgr.SCHED_POLICY.index('D'))

        # set runtime(ns) #
        sched_attr.sched_runtime = c_uint64(runtime)

        # check deadline and period #
        if deadline == period == 0:
            SysMgr.printErr((\
                "Fail to set priority of %s "
                "as runtime(ns)/deadline(ns)/period(ns)[D]") % pid)
            return -1
        elif deadline == 0:
            deadline = period
        elif period == 0:
            period = deadline

        # set period(ns) #
        sched_attr.sched_deadline = c_uint64(deadline)
        sched_attr.sched_period = c_uint64(period)

        # call sched_setattr() to set deadline sched #
        ret = SysMgr.libcObj.syscall(\
            nrSyscall, pid, pointer(sched_attr), 0)

        # get comm #
        comm = SysMgr.getComm(pid)

        # check return value #
        if ret == 0:
            SysMgr.printInfo((\
                "the priority of %s(%s) is changed to "
                "runtime(%d)/deadline(%d)/period(%d)[D]") % \
                (comm, pid, runtime, deadline, period))
        else:
            SysMgr.printErr((\
                "Fail to set priority of %s(%s) as "
                "runtime(%d)/deadline(%d)/period(%d)[D]") % \
                (comm, pid, runtime, deadline, period))

        return ret



    @staticmethod
    def getEnv(pid):
        path = "%s/%s/environ" % (SysMgr.procPath, pid)

        # open the environ file #
        try:
            with open(path, 'r') as fd:
                return fd.readlines()[0].split('\x00')[:-1]
        except:
            SysMgr.printErr(\
                "Fail to get environment variables of process %s" % pid, True)
            return



    @staticmethod
    def setPriority(pid, policy, pri, runtime=0, deadline=0, period=0):
        if not SysMgr.guiderObj:
            # get ctypes object #
            if not SysMgr.importPkgItems('ctypes', False):
                return

        # get comm #
        comm = SysMgr.getComm(pid)

        try:
            upolicy = policy.upper()

            if not SysMgr.loadLibcObj():
                raise Exception()

            argPolicy = ConfigMgr.SCHED_POLICY.index(upolicy)
            if not SysMgr.guiderObj:
                argPolicy = c_int(argPolicy)

            # set default priority #
            if upolicy == 'I' or upolicy == 'C' or upolicy == 'B':
                argPriority = long(0)
            else:
                argPriority = pri

            # prepare for libc call #
            if not SysMgr.guiderObj:
                argPriority = c_int(argPriority)

            # set scheduler policy #
            if not SysMgr.guiderObj:
                ret = SysMgr.libcObj.sched_setscheduler(\
                    pid, argPolicy, byref(argPriority))
            else:
                func = SysMgr.guiderObj.sched_setscheduler # pylint: disable=no-member
                ret = func(pid, argPolicy, argPriority)
            if ret != 0:
                policy = upolicy
                raise Exception()

            # set nice value #
            if upolicy == 'C' or upolicy == 'B':
                if not SysMgr.guiderObj:
                    argPriority = c_int(pri)
                    ret = SysMgr.libcObj.setpriority(\
                        0, pid, argPriority)
                else:
                    argPriority = pri
                    func = SysMgr.guiderObj.setpriority # pylint: disable=no-member
                    ret = func(0, pid, argPriority)
                if ret != 0:
                    policy = upolicy
                    raise Exception()

            SysMgr.printInfo(\
                'the priority of %s(%s) is changed to %d[%s]' % \
                (comm, pid, pri, upolicy))
        except:
            err = "Fail to set priority of %d as %s[%s]" % \
                (pid, pri, upolicy)

            if not SysMgr.isRoot():
                err += ', it requires root permission to make priority higher'

            SysMgr.printWarn(err, True)
            return



    @staticmethod
    def setTtyAuto(setRows=True, setCols=True):
        if not SysMgr.isLinux:
            return

        # update current terminal size #
        SysMgr.getTty()

        # decide terminal size #
        if setRows and SysMgr.ttyRows < 24:
            SysMgr.ttyRows = 24
        if setCols and SysMgr.ttyCols <= len(oneLine):
            SysMgr.ttyCols = len(oneLine) + 1

        # set terminal size #
        SysMgr.setTty(SysMgr.ttyRows, SysMgr.ttyCols)

        # update current terminal size #
        SysMgr.getTty()



    @staticmethod
    def setTty(rows, cols):
        if not SysMgr.isLinux:
            return

        try:
            if not SysMgr.termSetId:
                termios = SysMgr.getPkg('termios', False)
                SysMgr.termSetId = \
                    getattr(termios, 'TIOCSWINSZ', -2146929561)

            # get fcntl object #
            fcntlObj = SysMgr.getPkg('fcntl', False)

            # set terminal width size #
            fcntlObj.ioctl(\
                sys.stdout.fileno(), SysMgr.termSetId,\
                struct.pack("HHHH", rows, cols, 0, 0))

            # update current terminal size #
            SysMgr.getTty()

            SysMgr.printInfo("set terminal size [ %sx%s ]" % \
                (SysMgr.ttyRows, SysMgr.ttyCols))

            return
        except:
            pass

        try:
            if not UtilMgr.which('stty'):
                return

            os.system('stty rows %d 2> /dev/null' % (long(rows)))
            os.system('stty cols %d 2> /dev/null' % (long(cols)))
            SysMgr.ttyRows = rows
            SysMgr.ttyCols = cols
        except:
            return



    @staticmethod
    def getTty(update=False):
        if not SysMgr.isLinux:
            return

        if update and not SysMgr.termGetId:
            return

        # update tty info by ioctl #
        try:
            if not SysMgr.termGetId:
                termios = SysMgr.getPkg('termios', False)
                SysMgr.termGetId = termios.TIOCGWINSZ

            # get fcntl object #
            fcntlObj = SysMgr.getPkg('fcntl', False)

            SysMgr.ttyRows, SysMgr.ttyCols = \
                struct.unpack('hh', fcntlObj.ioctl(\
                    sys.stdout.fileno(), SysMgr.termGetId, '1234'))

            # update encoding option #
            if SysMgr.encodeEnable and \
                SysMgr.ttyCols < SysMgr.lineLength:
                SysMgr.encodeEnable = False

            return
        except:
            pass

        # update tty info by stty #
        try:
            if not UtilMgr.which('stty'):
                raise Exception("No stty")

            subprocess = SysMgr.getPkg('subprocess', False)
            pd = subprocess.Popen(['stty', 'size'], stdout=subprocess.PIPE)
            SysMgr.ttyRows, SysMgr.ttyCols = \
                list(map(long, pd.stdout.readline().split()))
        except:
            SysMgr.printWarn(\
                "Fail to get terminal info", reason=True)



    def saveSystemInfo(self):
        # update uptime #
        SysMgr.updateUptime()

        # cmdline #
        try:
            self.cmdlineData = SysMgr.procReadline('cmdline')[0:-1]
        except:
            SysMgr.printOpenWarn('cmdline')

        # load #
        try:
            self.loadData = SysMgr.procReadline('loadavg')
        except:
            SysMgr.printWarn(\
                "Fail to get load", reason=True)

        self.loadData = self.loadData.split()
        '''
        loadData[0] = 1min usage, \
        [1] = 5min usage, \
        [2] = 15min usage, \
        [3] = running/total thread, \
        [4] = lastPid
        '''

        # kernel version #
        try:
            self.systemInfo['kernelVer'] = \
                SysMgr.procReadline(\
                    'sys/kernel/osrelease').strip('\n')
        except:
            pass

        # os version #
        try:
            self.systemInfo['osVer'] = \
                SysMgr.procReadline(\
                    'sys/kernel/version').strip('\n')
        except:
            pass

        # os type #
        try:
            self.systemInfo['osType'] = \
                SysMgr.procReadline(\
                    'sys/kernel/ostype').strip('\n')
        except:
            pass

        # rtc #
        try:
            timeInfo = SysMgr.procReadlines('driver/rtc')

            for val in timeInfo:
                timeEntity = val.split()

                if timeEntity[0] == 'rtc_time':
                    self.systemInfo['time'] = timeEntity[2]
                elif timeEntity[0] == 'rtc_date':
                    self.systemInfo['date'] = timeEntity[2]
        except:
            pass



    def saveSysStat(self, initialized=True):
        SysMgr.updateUptime()

        # update resource usage #
        self.updateMemInfo()
        self.updateStorageInfo(isGeneral=True)
        self.updateNetworkInfo()
        self.updateIPCInfo()
        self.saveMacAddr()

        # save user info #
        self.saveUserInfo()

        # save system info #
        if initialized:
            # process info #
            if SysMgr.isRecordMode():
                self.saveProcTree()

            # resource info #
            self.saveSystemInfo()
            self.saveCpuInfo()
            self.saveCpuCacheInfo()

            # os specific info #
            self.saveWebOSInfo()
            self.saveLinuxInfo()

            # write resource info to temporary buffer #
            self.printResourceInfo()



    def saveProcTree(self):
        procTree = SysMgr.getProcTree()

        if procTree:
            self.procData = '!!!!!'
            for tid, pid in procTree.items():
                self.procData += '%s:%s,' % (tid, pid)



    def saveLinuxInfo(self):
        OSFile = '/etc/os-release'

        try:
            with open(OSFile, 'r') as osf:
                self.osData = osf.readlines()
        except:
            SysMgr.printOpenWarn(OSFile)



    def saveWebOSInfo(self):
        OSFile = '/var/run/nyx/os_info.json'
        devFile = '/var/run/nyx/device_info.json'
        osf = devf = None

        try:
            osf = open(OSFile, 'r')
        except:
            pass

        try:
            devf = open(devFile, 'r')
        except:
            pass

        # check webOS #
        if not osf and not devf:
            return False

        try:
            self.osData = osf.readlines()
            osf.close()
        except:
            SysMgr.printOpenWarn(OSFile)

        try:
            self.devData = devf.readlines()
            devf.close()
        except:
            SysMgr.printOpenWarn(devFile)



    def saveCpuInfo(self):
        try:
            self.cpuData = SysMgr.procReadlines('cpuinfo')
        except:
            SysMgr.printWarn(\
                "Fail to save CPU info", reason=True)



    def saveCpuCacheInfo(self):
        cpuPath = '/sys/devices/system/cpu'

        try:
            corelist = os.listdir(cpuPath)

            for core in corelist:
                cachePath = '/sys/devices/system/cpu/%s/cache' % core

                self.cpuCacheInfo[core] = ''

                try:
                    typelist = os.listdir(cachePath)

                    for index in sorted(typelist):
                        if not index.startswith('index'):
                            continue

                        level = '?'
                        path = '%s/%s/level' % (cachePath, index)
                        with open(path, 'r') as fd:
                            level = fd.readline()

                        type = '?'
                        path = '%s/%s/type' % (cachePath, index)
                        with open(path, 'r') as fd:
                            type = fd.readline()

                        size = '?'
                        path = '%s/%s/size' % (cachePath, index)
                        with open(path, 'r') as fd:
                            size = fd.readline()

                        self.cpuCacheInfo[core] = '%sL%s(%s)=%s   ' % \
                            (self.cpuCacheInfo[core], level[:-1], \
                            type[:-1], size[:-1])
                except:
                    pass

                if len(self.cpuCacheInfo[core]) == 0:
                    del self.cpuCacheInfo[core]
        except:
            pass



    def saveDevInfo(self):
        try:
            target = None
            devData = SysMgr.procReadlines('devices')

            for line in devData:
                if line.startswith('Character'):
                    target = self.devInfo['char'] = {}
                elif line.startswith('Block'):
                    target = self.devInfo['block'] = {}

                item = line.split()

                if len(item) != 2:
                    continue

                try:
                    num = long(item[0])
                except:
                    continue

                try:
                    target[num].append(item[1])
                except:
                    target[num] = [item[1]]
        except:
            SysMgr.printWarn(\
                "Fail to save deice info", reason=True)



    def saveStorageInfo(self, isGeneral):
        blockDir = '/sys/class/block'
        partFile = '%s/partitions' % SysMgr.procPath

        # update disk data #
        SysMgr.updateDiskStats()

        # update only a last diskstats if there is a first diskstats exist #
        if not 'prev' in self.diskData:
            self.diskData['prev'] = SysMgr.diskStats
            self.updateDiskInfo('prev', SysMgr.diskStats)
        else:
            self.diskData['next'] = SysMgr.diskStats
            self.updateDiskInfo('next', SysMgr.diskStats)

        # update mount data #
        self.mountData = SysMgr.getMountData()

        # check data type #
        if not isGeneral:
            return

        # save partition range #
        for dirnames in os.walk(blockDir):
            for subdirname in dirnames[1]:
                try:
                    devPath = '/sys/class/block/%s/dev' % subdirname
                    startPath = '/sys/class/block/%s/start' % subdirname
                    sizePath = '/sys/class/block/%s/size' % subdirname

                    with open(sizePath, 'r') as sizeFd:
                        size = sizeFd.readline()[:-1]

                    if any(char.isdigit() for char in subdirname):
                        with open(startPath, 'r') as startFd:
                            start = startFd.readline()[:-1]
                    else:
                        start = long(0)

                    with open(devPath, 'r') as devFd:
                        partName = devFd.readline()[:-1]
                        self.partitionInfo[partName] = {}
                        self.partitionInfo[partName]['start'] = long(start)
                        self.partitionInfo[partName]['end'] = \
                            long(start) + long(size)
                except:
                    pass



    def updateMemInfo(self):
        try:
            lines = SysMgr.procReadlines('meminfo')

            if not 'prev' in self.memData:
                self.memData['prev'] = lines
            else:
                self.memData['next'] = lines
        except:
            SysMgr.printWarn(\
                "Fail to update memory", reason=True)



    @staticmethod
    def getBufferSize():
        bufFile = "%s../buffer_size_kb" % SysMgr.mountPath

        try:
            f = open(bufFile, 'r')
            size = f.readlines()
            f.close()
        except:
            SysMgr.printOpenWarn(bufFile)
            return 0


        return long(size[0])



    @staticmethod
    def setBufferSize(bufferSize):
        SysMgr.writeCmd("../buffer_size_kb", bufferSize)



    @staticmethod
    def copyPipeToFile(pipePath, filePath):
        try:
            pd = open(pipePath, 'r')
        except:
            SysMgr.printOpenErr(pipePath)
            sys.exit(0)

        try:
            # use os.O_DIRECT | os.O_RDWR | os.O_TRUNC | os.O_CREAT #
            fd = open(filePath, 'w')
        except:
            SysMgr.printOpenErr(filePath)
            sys.exit(0)

        pageSize = SysMgr.pageSize

        while 1:
            try:
                # read each 4k data through pipe #
                buf = pd.read(pageSize)

                fd.write(buf)

                # print to console #
                if SysMgr.printStreamEnable:
                    SysMgr.printPipe(buf, newline=False)

                if SysMgr.recordStatus:
                    continue
                else:
                    raise Exception()
            except:
                # close pipe #
                pd.close()

                # read the remaining data under 4k from log buffer #
                tpath = os.path.join(SysMgr.mountPath, '../trace')
                with open(tpath, 'r') as fr:
                    fd.write(fr.read())

                # close file to sync disk buffer #
                fd.close()

                # save system info #
                SysMgr.sysInstance.saveSysStat()

                rbuf = ''
                with open(SysMgr.outputFile, 'r') as fd:
                    rbuf = fd.read()

                with open(SysMgr.outputFile, 'w') as fd:
                    if SysMgr.systemInfoBuffer != '':
                        fd.writelines(SysMgr.magicString + '\n')
                        fd.writelines(SysMgr.systemInfoBuffer)
                        fd.writelines(SysMgr.magicString + '\n')
                        fd.writelines(rbuf)

                SysMgr.printInfo(\
                    "wrote data to %s successfully" % \
                    SysMgr.outputFile)

                return



    @staticmethod
    def getDebugfsPath():
        try:
            lines = SysMgr.procReadlines('mounts')
        except:
            SysMgr.printErr(\
                "Fail to get mount path", True)
            return None

        ret = None
        for l in lines:
            m = re.match(r'(?P<dev>\S+)\s+(?P<dir>\S+)\s+(?P<fs>\S+)', l)
            if not m:
                continue

            d = m.groupdict()
            if d['fs'] == 'debugfs':
                ret = "%s/tracing/events/" % d['dir']

        return ret



    @staticmethod
    def clearChildList():
        SysMgr.childList = {}



    @staticmethod
    def isNoChild():
        if len(SysMgr.childList) == 0:
            return True
        else:
            return False



    @staticmethod
    def updateChilds():
        childList = list(SysMgr.childList.keys())

        for pid in childList:
            if not SysMgr.isAlive(pid):
                try:
                    os.waitpid(pid, os.WNOHANG)
                except:
                    pass

                SysMgr.childList.pop(pid, None)



    @staticmethod
    def killChilds(sig=None, childs=None, wait=False, group=False):
        if not sig:
            sig = ConfigMgr.SIGKILL

        SysMgr.updateChilds()

        if childs is None:
            childs = list(SysMgr.childList.keys())

        # remove child list #
        SysMgr.clearChildList()

        SysMgr.terminateTasks(childs, sig, group)

        if not wait:
            return

        while 1:
            newChilds = list(childs)
            isFinished = True

            for tid in newChilds:
                if SysMgr.isAlive(tid):
                    isFinished = False
                    break

                childs.remove(tid)

            if isFinished:
                break
            else:
                time.sleep(SysMgr.waitDelay)



    @staticmethod
    def removeExitFunc(func, args=None):
        newList = list()
        for handler in SysMgr.exitFuncList:
            if handler[0] == func and \
                handler[1] == args:
                continue
            newList.append(handler)
        SysMgr.exitFuncList = newList



    @staticmethod
    def addExitFunc(func, args=None):
        SysMgr.exitFuncList.append([func, args])



    @staticmethod
    def doExit():
        if not hasattr(SysMgr, 'exitFuncList'):
            return

        # call functions registered #
        for func, args in SysMgr.exitFuncList:
            try:
                func(*args)
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "Fail to execute a exit handler", True)

        # destroy objects registered #
        del SysMgr.exitFuncList

        # release all resources #
        SysMgr.releaseResource()



    @staticmethod
    def getFileList(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 releaseResource():
        # kill child tasks #
        SysMgr.killChilds()

        # close all files #
        SysMgr.closeAllForPrint()



    @staticmethod
    def flushAllForPrint():
        try:
            sys.stdout.flush()
        except:
            pass

        if SysMgr.pipeForPrint:
            try:
                SysMgr.pipeForPrint.flush()
            except:
                pass

        if SysMgr.fileForPrint:
            try:
                SysMgr.fileForPrint.flush()
            except:
                pass



    @staticmethod
    def closeAllForPrint():
        if SysMgr.pipeForPrint:
            try:
                SysMgr.pipeForPrint.close()
            except:
                pass
            finally:
                SysMgr.pipeForPrint = None

        if SysMgr.fileForPrint:
            try:
                SysMgr.fileForPrint.flush()

                fsize = UtilMgr.convSize2Unit(\
                    long(os.fstat(SysMgr.fileForPrint.fileno()).st_size))

                SysMgr.printInfo(\
                    "finish saving all results into %s [%s] successfully" % \
                    (SysMgr.fileForPrint.name, fsize))

                SysMgr.fileForPrint.close()
            except SystemExit:
                sys.exit(0)
            except:
                pass
            finally:
                SysMgr.fileForPrint = None



    @staticmethod
    def clearTraceBuffer():
        SysMgr.writeCmd("../trace", '')



    @staticmethod
    def clearTraceFilter():
        SysMgr.writeCmd("../set_ftrace_filter", '')
        SysMgr.writeCmd("../set_ftrace_pid", '')
        SysMgr.writeCmd("../set_ftrace_notrace", '')
        SysMgr.writeCmd("../set_event", '')
        SysMgr.writeCmd("../set_event_pid", '')
        SysMgr.writeCmd("../set_graph_function", '')
        SysMgr.writeCmd("../set_graph_notrace", '')



    def initCmdList(self):
        sm = SysMgr

        # default #
        self.cmdList["sched/sched_process_fork"] = True
        self.cmdList["sched/sched_process_exit"] = True
        self.cmdList["sched/sched_process_wait"] = True
        self.cmdList["task"] = True
        self.cmdList["signal"] = True
        self.cmdList["printk"] = True
        self.cmdList["module/module_load"] = True
        self.cmdList["module/module_free"] = True
        self.cmdList["module/module_put"] = True
        self.cmdList["module/module_get"] = True

        # sched #
        self.cmdList["sched/sched_switch"] = \
            self.cmdList["sched/sched_migrate_task"] = sm.cpuEnable
        self.cmdList["sched/sched_wakeup"] = \
            self.cmdList["sched/sched_wakeup_new"] = \
            (sm.cpuEnable and sm.latEnable) or sm.depEnable

        self.cmdList["irq"] = sm.irqEnable

        self.cmdList["raw_syscalls"] = \
            sm.sysEnable | sm.depEnable | sm.lockEnable

        # mem #
        self.cmdList["kmem/mm_page_alloc"] = \
            self.cmdList["kmem/mm_page_free"] = \
            self.cmdList["kmem/kmalloc"] = \
            self.cmdList["kmem/kfree"] = \
            self.cmdList["filemap/mm_filemap_delete_from_page_cache"] = \
            self.cmdList["vmscan/mm_vmscan_direct_reclaim_begin"] = \
            self.cmdList["vmscan/mm_vmscan_direct_reclaim_end"] = sm.memEnable
        self.cmdList["kmem/mm_page_free_direct"] = False
        self.cmdList["filemap/mm_filemap_add_to_page_cache"] = False
        self.cmdList["timer/hrtimer_start"] = False
        self.cmdList["vmscan/mm_vmscan_wakeup_kswapd"] = False
        self.cmdList["vmscan/mm_vmscan_kswapd_sleep"] = False

        # bio #
        self.cmdList["block/block_bio_queue"] = \
            self.cmdList["block/block_rq_complete"] = \
            self.cmdList["writeback/writeback_dirty_page"] = \
            self.cmdList["writeback/wbc_writepage"] = sm.blockEnable

        # network #
        self.cmdList["net/net_dev_xmit"] = \
            self.cmdList["net/netif_receive_skb"] = sm.networkEnable

        self.cmdList["uprobes"] = sm.ueventEnable
        self.cmdList["kprobes"] = sm.keventEnable
        self.cmdList["filelock/locks_get_lock_context"] = sm.lockEnable

        # power #
        self.cmdList["power/cpu_idle"] = \
            self.cmdList["power/cpu_frequency"] = \
            self.cmdList["power/suspend_resume"] = sm.powerEnable



    def runPeriodProc(self):
        pid = SysMgr.createProcess()

        if pid == 0:
            signal.signal(signal.SIGINT, 0)

            while 1:
                time.sleep(0.0001)

            sys.exit(0)



    def startTracing(self):
        stat = SysMgr.readCmdVal('../tracing_on')
        if stat == '0':
            pass
        elif SysMgr.forceEnable:
            # write command to stop tracing #
            SysMgr.writeCmd('../tracing_on', '0')
        elif stat == '1':
            # no running Guider process except for myself #
            if SysMgr.getBgProcCount(cache=True) <= 1:
                res = SysMgr.readCmdVal('enable')
                # default status #
                if res == '0':
                    pass
                # tracing status #
                else:
                    SysMgr.printErr(\
                        "Fail to start tracing because "
                        "tracing is already in progress on system\n"
                        "\tit would be stopped so that try to record again")
                    sys.exit(0)
            else:
                SysMgr.printErr(\
                    "Fail to start tracing because "
                    "another Guider is already running")
                os._exit(0)

        # clean up ring buffer for tracing #
        SysMgr.clearTraceBuffer()

        # clear trace filter #
        SysMgr.clearTraceFilter()

        # write command to start tracing #
        SysMgr.writeCmd('../tracing_on', '1')

        # write start event #
        #SysMgr.writeEvent("EVENT_START", False)



    def startRecording(self):
        def writeCommonCmd():
            # enable dynamic events #
            SysMgr.writeCustomCmd()
            SysMgr.writeKernelCmd()
            SysMgr.writeUserCmd()

            # enable flock events #
            if self.cmdList["filelock/locks_get_lock_context"]:
                SysMgr.writeCmd(\
                    "filelock/locks_get_lock_context/enable", '1')

            # enable common events #
            if self.cmdList["task"]:
                SysMgr.writeCmd('task/enable', '1')
            if self.cmdList["sched/sched_process_fork"]:
                SysMgr.writeCmd('sched/sched_process_fork/enable', '1')
            if self.cmdList["sched/sched_process_exit"]:
                SysMgr.writeCmd('sched/sched_process_exit/enable', '1')
            if self.cmdList["signal"]:
                if SysMgr.filterGroup != []:
                    commonFilter  = SysMgr.getPidFilter()
                    genFilter = commonFilter.replace("common_", "")
                    SysMgr.writeCmd(\
                        'signal/signal_deliver/filter', commonFilter)
                    SysMgr.writeCmd(\
                        'signal/signal_generate/filter', genFilter)
                SysMgr.writeCmd('signal/enable', '1')

        # mount debugfs #
        SysMgr.mountPath = SysMgr.getDebugfsPath()
        if not SysMgr.mountPath:
            SysMgr.mountDebugfs()

        # check permission #
        if not os.path.isdir(SysMgr.mountPath):
            if SysMgr.isRoot():
                cmd = '/boot/config-$(uname -r)'
                SysMgr.printErr((\
                    "Check whether ftrace options are enabled in kernel "
                    "through %s") % cmd)
            else:
                SysMgr.printErr(\
                    "Fail to get root permission to trace system")

            sys.exit(0)

        # write user command #
        SysMgr.writeTraceCmd('BEFORE')

        # set size of trace buffer per core #
        if SysMgr.bufferSize == -1:
            SysMgr.bufferSize = '40960' # 40MB #
        else:
            # Change from integer to string #
            SysMgr.bufferSize = str(SysMgr.bufferSize)

        # set system buffer size #
        SysMgr.setBufferSize(SysMgr.bufferSize)

        # get system buffer size #
        setBufferSize = SysMgr.getBufferSize()

        # check system buffer size #
        if long(SysMgr.bufferSize) != setBufferSize:
            SysMgr.printWarn(\
                "Fail to set buffer size to %s KB, buffer size is %s KB now" % \
                (SysMgr.bufferSize, setBufferSize), True)

        # initialize event list to enable #
        self.initCmdList()

        if SysMgr.disableAll:
            SysMgr.sysInstance.disableAllEvents()

        # set comm cache size #
        SysMgr.writeCmd(\
            '../saved_cmdlines_size', '%s' % SysMgr.maxPid)

        # set log format #
        SysMgr.writeCmd('../trace_options', 'noirq-info')
        SysMgr.writeCmd('../trace_options', 'noannotate')
        SysMgr.writeCmd('../trace_options', 'print-tgid')
        SysMgr.writeCmd('../trace_options', 'record-tgid')
        SysMgr.writeCmd('../current_tracer', 'nop')

        SysMgr.printStat(\
            r'start recording... [ STOP(Ctrl+c), MARK(Ctrl+\) ]')

        # start tracing #
        self.startTracing()

        #-------------------- FUNCTION MODE --------------------#
        if SysMgr.isFunctionMode():
            # check conditions for kernel function_graph #
            if SysMgr.graphEnable:
                # reset events #
                SysMgr.stopRecording()
                SysMgr.clearTraceBuffer()

                # set function_graph tracer #
                if SysMgr.writeCmd(\
                    '../current_tracer', 'function_graph') < 0:
                    SysMgr.printErr(\
                        "enable CONFIG_FUNCTION_GRAPH_TRACER kernel option")
                    sys.exit(0)

                # apply filter #
                for pid in SysMgr.filterGroup:
                    try:
                        pid = str(long(pid))
                        SysMgr.writeCmd('../set_ftrace_pid', pid, True)
                    except:
                        SysMgr.printErr((\
                            "Fail to add %s to PID filter "
                            "for function graph tracing") % pid)
                        sys.exit(0)

                optPath = '../trace_options'
                SysMgr.writeCmd(optPath, 'nofuncgraph-proc')
                SysMgr.writeCmd(optPath, 'funcgraph-abstime')
                SysMgr.writeCmd(optPath, 'funcgraph-overhead')
                SysMgr.writeCmd(optPath, 'funcgraph-duration')
                SysMgr.writeCmd(\
                    '../max_graph_depth', str(SysMgr.funcDepth))

                if not SysMgr.customCmd:
                    SysMgr.writeCmd('../set_ftrace_filter', '')
                else:
                    params = ' '.join(SysMgr.customCmd)
                    SysMgr.printStat(\
                        "wait for setting function filter [ %s ]" % params)
                    if SysMgr.writeCmd(\
                        '../set_ftrace_filter', params) < 0:
                        SysMgr.printErr(\
                            "Fail to set function filter")
                        sys.exit(0)
                    else:
                        SysMgr.printStat(\
                            "finished function filter [ %s ]" % params)

                SysMgr.writeCmd('../tracing_on', '1')

                # write user command #
                SysMgr.writeTraceCmd('AFTER')

                return

            # define initialized command variable #
            cmd = ""

            # make filter for function mode #
            if SysMgr.filterGroup != []:
                try:
                    cmd = "%s%s" % (cmd, SysMgr.getPidFilter())
                    if len(cmd) == 0:
                        raise Exception()
                except:
                    SysMgr.printErr(\
                        "wrong TID %s" % SysMgr.filterGroup)
                    sys.exit(0)

            # trace except for swapper threads #
            if cmd == "":
                cmd = "(common_pid != 0)"

            if SysMgr.userEnable:
                SysMgr.writeCmd('../trace_options', 'userstacktrace')
                SysMgr.writeCmd('../trace_options', 'sym-userobj')
            else:
                SysMgr.writeCmd('../trace_options', 'nouserstacktrace')
                SysMgr.writeCmd('../trace_options', 'nosym-userobj')

            SysMgr.writeCmd('../trace_options', 'sym-addr')
            SysMgr.writeCmd('../options/stacktrace', '1')

            if SysMgr.disableAll:
                # write user command #
                SysMgr.writeTraceCmd('AFTER')

                return

            # enable segmentation fault events #
            customCmd = SysMgr.customCmd
            if not customCmd or \
                not any([True for evt in customCmd if evt.startswith('signal')]):
                sigCmd = "sig == %d" % signal.SIGSEGV
                SysMgr.writeCmd('signal/filter', sigCmd)

            # enable CPU events #
            if SysMgr.cpuEnable:
                addr = SysMgr.getKerAddr('tick_sched_timer')
                if addr:
                    SysMgr.writeCmd(\
                        'timer/hrtimer_start/filter',\
                        '%s && function == 0x%s' % (cmd, addr))
                SysMgr.writeCmd('timer/hrtimer_start/enable', '1')
            else:
                SysMgr.writeCmd('timer/hrtimer_start/enable', '0')

            # enable page events #
            if SysMgr.memEnable:
                SysMgr.writeCmd('kmem/mm_page_alloc/filter', cmd)

                if SysMgr.writeCmd('kmem/mm_page_free/filter', cmd) < 0:
                    SysMgr.writeCmd(\
                        'kmem/mm_page_free_direct/filter', cmd)

                SysMgr.writeCmd('kmem/mm_page_alloc/enable', '1')

                if SysMgr.writeCmd('kmem/mm_page_free/enable', '1') < 0:
                    SysMgr.writeCmd(\
                        'kmem/mm_page_free_direct/enable', '1')
            else:
                SysMgr.writeCmd('kmem/mm_page_alloc/enable', '0')

                if SysMgr.writeCmd('kmem/mm_page_free/enable', '0') < 0:
                    SysMgr.writeCmd(\
                        'kmem/mm_page_free_direct/enable', '0')

            # enable all syscall events #
            if SysMgr.sysEnable:
                if SysMgr.heapEnable or \
                    SysMgr.lockEnable:
                    SysMgr.printErr(\
                        "Fail to enable syscall events with other events")
                    sys.exit(0)
                elif len(SysMgr.syscallList) == 0:
                    pass
            else:
                # enable heap events #
                if SysMgr.heapEnable:
                    if SysMgr.arch == 'arm':
                        mmapId = ConfigMgr.sysList.index('sys_mmap2')
                    else:
                        mmapId = ConfigMgr.sysList.index('sys_mmap')

                    brkId = ConfigMgr.sysList.index('sys_brk')

                    SysMgr.syscallList.append(mmapId)
                    SysMgr.syscallList.append(brkId)

                    self.cmdList["raw_syscalls"] = True

                # enable lock events #
                if SysMgr.lockEnable:
                    futexId = ConfigMgr.sysList.index('sys_futex')

                    SysMgr.syscallList.append(futexId)

                    self.cmdList["raw_syscalls"] = True

            # enable target systemcall events #
            SysMgr.writeSyscallCmd(self.cmdList["raw_syscalls"])

            # enable block events #
            if SysMgr.blockEnable:
                blkCmd = cmd + \
                    " && (rwbs == R || rwbs == RA || rwbs == RM || rwbs == WS)"
                SysMgr.writeCmd('block/block_bio_queue/filter', blkCmd)
                SysMgr.writeCmd('block/block_bio_queue/enable', '1')
                SysMgr.writeCmd(\
                    'writeback/writeback_dirty_page/filter', cmd)
                SysMgr.writeCmd(\
                    'writeback/writeback_dirty_page/enable', '1')
                SysMgr.writeCmd('writeback/wbc_writepage/filter', cmd)
                SysMgr.writeCmd('writeback/wbc_writepage/enable', '1')
            else:
                SysMgr.writeCmd('block/block_bio_queue/enable', '0')
                SysMgr.writeCmd(\
                    'writeback/writeback_dirty_page/enable', '0')
                SysMgr.writeCmd('writeback/wbc_writepage/enable', '0')

            # enable special events #
            writeCommonCmd()

            # write user command #
            SysMgr.writeTraceCmd('AFTER')

            return

        #-------------------- THREAD MODE --------------------#
        # enable sched events #
        if self.cmdList["sched/sched_switch"]:
            if len(SysMgr.filterGroup) > 0:
                cmd = "prev_pid == 0 || next_pid == 0 || "

                # apply filter #
                for comm in list(SysMgr.filterGroup):
                    cmd += \
                        "prev_comm == \"*%s*\" || next_comm == \"*%s*\" || " % \
                        (comm, comm)
                    try:
                        pid = long(comm)
                        cmd += "prev_pid == \"%s\" || next_pid == \"%s\" || " % \
                            (pid, pid)
                    except:
                        try:
                            ldir = comm.find('>')
                            if ldir == 0:
                                cmd += "prev_pid >= %s || " % long(comm[1:])
                                cmd += "next_pid >= %s || " % long(comm[1:])
                            elif ldir == len(comm) - 1:
                                cmd += "prev_pid <= %s || " % long(comm[:-1])
                                cmd += "next_pid <= %s || " % long(comm[:-1])

                            rdir = comm.find('<')
                            if rdir == 0:
                                cmd += "prev_pid <= %s || " % long(comm[1:])
                                cmd += "next_pid <= %s || " % long(comm[1:])
                            elif rdir == len(comm) - 1:
                                cmd += "prev_pid >= %s || " % long(comm[:-1])
                                cmd += "next_pid >= %s || " % long(comm[:-1])
                        except:
                            pass

                cmd = cmd[0:cmd.rfind("||")]
                if SysMgr.writeCmd('sched/sched_switch/filter', cmd) < 0:
                    SysMgr.printErr(\
                        "Fail to set filter [ %s ]" % \
                        ' '.join(SysMgr.filterGroup))
                    sys.exit(0)
            else:
                SysMgr.writeCmd('sched/sched_switch/filter', '0')

            if SysMgr.writeCmd('sched/sched_switch/enable', '1') < 0:
                SysMgr.printErr("Fail to enable sched events")
                sys.exit(0)

        # build sched filter #
        if len(SysMgr.filterGroup) > 0:
            cmd = ""

            # apply filter #
            for comm in list(SysMgr.filterGroup):
                cmd += "comm == \"*%s*\" || " % (comm)
                try:
                    pid = long(comm)
                    cmd += "pid == \"%s\" || " % (pid)
                except:
                    try:
                        ldir = comm.find('>')
                        if ldir == 0:
                            cmd += "pid >= %s || " % long(comm[1:])
                        elif ldir == len(comm) - 1:
                            cmd += "pid <= %s || " % long(comm[:-1])

                        rdir = comm.find('<')
                        if rdir == 0:
                            cmd += "pid <= %s || " % long(comm[1:])
                        elif rdir == len(comm) - 1:
                            cmd += "pid >= %s || " % long(comm[:-1])
                    except:
                        pass

            cmd = cmd[0:cmd.rfind("||")]
        else:
            cmd = "0"

        if self.cmdList["sched/sched_wakeup"]:
            if SysMgr.writeCmd('sched/sched_wakeup/filter', cmd) < 0:
                SysMgr.printErr(\
                    "Fail to set filter [ %s ]" % \
                    ' '.join(SysMgr.filterGroup))
                sys.exit(0)

            SysMgr.writeCmd('sched/sched_wakeup/enable', '1')

        if self.cmdList["sched/sched_wakeup_new"]:
            if SysMgr.writeCmd('sched/sched_wakeup_new/filter', cmd) < 0:
                SysMgr.printErr(\
                    "Fail to set filter [ %s ]" % \
                    ' '.join(SysMgr.filterGroup))
                sys.exit(0)

            SysMgr.writeCmd('sched/sched_wakeup_new/enable', '1')

        if self.cmdList["sched/sched_migrate_task"]:
            if SysMgr.writeCmd(\
                'sched/sched_migrate_task/filter', cmd) < 0:
                SysMgr.printErr(\
                    "Fail to set filter [ %s ]" % \
                    ' '.join(SysMgr.filterGroup))
                sys.exit(0)

            SysMgr.writeCmd('sched/sched_migrate_task/enable', '1')

        if self.cmdList["sched/sched_process_wait"]:
            if SysMgr.writeCmd(\
                'sched/sched_process_wait/filter', cmd) < 0:
                SysMgr.printWarn(\
                    "Fail to set filter [ %s ]" % \
                    ' '.join(SysMgr.filterGroup))

            SysMgr.writeCmd('sched/sched_process_wait/enable', '1')

        # enable irq events #
        if self.cmdList["irq"]:
            SysMgr.writeCmd('irq/irq_handler_entry/enable', '1')
            SysMgr.writeCmd('irq/irq_handler_exit/enable', '1')
            SysMgr.writeCmd('irq/softirq_entry/enable', '1')
            SysMgr.writeCmd('irq/softirq_exit/enable', '1')
            #SysMgr.writeCmd('irq/softirq_raise/enable', '1')

        # enable events for dependency tracing #
        if SysMgr.depEnable:
            ecmd = \
                "(id == %s || id == %s" % \
                (ConfigMgr.sysList.index("sys_write"), \
                ConfigMgr.sysList.index("sys_futex"))
            rcmd = \
                "((id == %s || id == %s" % \
                (ConfigMgr.sysList.index("sys_write"), \
                ConfigMgr.sysList.index("sys_futex"))

            if SysMgr.arch == 'arm':
                ecmd = \
                    ("%s || id == %s || id == %s || id == %s || "
                    "id == %s || id == %s || id == %s || id == %s)") % \
                    (ecmd, ConfigMgr.sysList.index("sys_recv"), \
                    ConfigMgr.sysList.index("sys_epoll_wait"), \
                    ConfigMgr.sysList.index("sys_poll"), \
                    ConfigMgr.sysList.index("sys_select"), \
                    ConfigMgr.sysList.index("sys_recvfrom"), \
                    ConfigMgr.sysList.index("sys_recvmmsg"), \
                    ConfigMgr.sysList.index("sys_recvmsg"))
                rcmd = \
                    ("%s || id == %s || id == %s || id == %s || "
                    "id == %s || id == %s || id == %s || id == %s) && ret > 0)") % \
                    (rcmd, ConfigMgr.sysList.index("sys_recv"), \
                    ConfigMgr.sysList.index("sys_poll"), \
                    ConfigMgr.sysList.index("sys_epoll_wait"), \
                    ConfigMgr.sysList.index("sys_select"), \
                    ConfigMgr.sysList.index("sys_recvfrom"), \
                    ConfigMgr.sysList.index("sys_recvmmsg"), \
                    ConfigMgr.sysList.index("sys_recvmsg"))
            elif SysMgr.arch == 'aarch64':
                ecmd = "%s || id == %s || id == %s || id == %s)" % \
                    (ecmd, ConfigMgr.sysList.index("sys_recvfrom"), \
                    ConfigMgr.sysList.index("sys_recvmmsg"), \
                    ConfigMgr.sysList.index("sys_recvmsg"))
                rcmd = "%s || id == %s || id == %s || id == %s) && ret > 0)" % \
                    (rcmd, ConfigMgr.sysList.index("sys_recvfrom"), \
                    ConfigMgr.sysList.index("sys_recvmmsg"), \
                    ConfigMgr.sysList.index("sys_recvmsg"))
            else:
                ecmd = ("%s || id == %s || id == %s || id == %s || "
                "id == %s || id == %s || id == %s)") % \
                    (ecmd, ConfigMgr.sysList.index("sys_recvfrom"), \
                    ConfigMgr.sysList.index("sys_poll"), \
                    ConfigMgr.sysList.index("sys_epoll_wait"), \
                    ConfigMgr.sysList.index("sys_select"), \
                    ConfigMgr.sysList.index("sys_recvmmsg"), \
                    ConfigMgr.sysList.index("sys_recvmsg"))
                rcmd = \
                    ("%s || id == %s || id == %s || id == %s || "
                    "id == %s || id == %s || id == %s) && ret > 0)") % \
                    (rcmd, ConfigMgr.sysList.index("sys_recvfrom"), \
                    ConfigMgr.sysList.index("sys_poll"), \
                    ConfigMgr.sysList.index("sys_epoll_wait"), \
                    ConfigMgr.sysList.index("sys_select"), \
                    ConfigMgr.sysList.index("sys_recvmmsg"), \
                    ConfigMgr.sysList.index("sys_recvmsg"))

            if self.cmdList["sched/sched_switch"]:
                SysMgr.writeCmd('sched/sched_switch/enable', '1')
            if self.cmdList["sched/sched_wakeup"]:
                SysMgr.writeCmd('sched/sched_wakeup/enable', '1')
            if self.cmdList["sched/sched_wakeup_new"]:
                SysMgr.writeCmd('sched/sched_wakeup_new/enable', '1')

            SysMgr.writeCmd('raw_syscalls/sys_enter/filter', ecmd)
            SysMgr.writeCmd('raw_syscalls/sys_enter/enable', '1')
            SysMgr.writeCmd('raw_syscalls/sys_exit/filter', rcmd)
            SysMgr.writeCmd('raw_syscalls/sys_exit/enable', '1')
        elif SysMgr.lockEnable:
            nrFutex = ConfigMgr.sysList.index("sys_futex")
            if nrFutex not in SysMgr.syscallList:
                SysMgr.syscallList.append(nrFutex)
        else:
            SysMgr.writeCmd('raw_syscalls/sys_enter/filter', '0')
            SysMgr.writeCmd('raw_syscalls/sys_enter/enable', '0')

        # enable systemcall events #
        SysMgr.writeSyscallCmd(self.cmdList["raw_syscalls"])

        # enable memory events #
        if self.cmdList["kmem/mm_page_alloc"]:
            SysMgr.writeCmd('kmem/mm_page_alloc/enable', '1')
        if self.cmdList["kmem/mm_page_free"]:
            if SysMgr.writeCmd('kmem/mm_page_free/enable', '1') < 0:
                SysMgr.writeCmd('kmem/mm_page_free_direct/enable', '1')
        if self.cmdList["kmem/kmalloc"]:
            SysMgr.writeCmd('kmem/kmalloc/enable', '1')
        if self.cmdList["kmem/kfree"]:
            SysMgr.writeCmd('kmem/kfree/enable', '1')
        if self.cmdList["filemap/mm_filemap_add_to_page_cache"]:
            SysMgr.writeCmd(\
                'filemap/mm_filemap_add_to_page_cache/enable', '1')
        if self.cmdList["filemap/mm_filemap_delete_from_page_cache"]:
            SysMgr.writeCmd(\
                'filemap/mm_filemap_delete_from_page_cache/enable', '1')

        # enable block events #
        if self.cmdList["block/block_bio_queue"]:
            cmd = "rwbs == R || rwbs == RA || rwbs == RM || rwbs == WS"
            SysMgr.writeCmd('block/block_bio_queue/filter', cmd)
            SysMgr.writeCmd('block/block_bio_queue/enable', '1')
        if self.cmdList["block/block_rq_complete"]:
            cmd = "rwbs == R || rwbs == RA || rwbs == RM || rwbs == WS"
            SysMgr.writeCmd('block/block_rq_complete/filter', cmd)
            SysMgr.writeCmd('block/block_rq_complete/enable', '1')

        # enable writeback events #
        if self.cmdList["writeback/writeback_dirty_page"]:
            SysMgr.writeCmd('writeback/writeback_dirty_page/enable', '1')
        if self.cmdList["writeback/wbc_writepage"]:
            SysMgr.writeCmd('writeback/wbc_writepage/enable', '1')

        # enable network events #
        if self.cmdList["net/net_dev_xmit"]:
            SysMgr.writeCmd('net/net_dev_xmit/enable', '1')
        if self.cmdList["net/netif_receive_skb"]:
            SysMgr.writeCmd('net/netif_receive_skb/enable', '1')

        # enable module events #
        if self.cmdList["module/module_load"]:
            SysMgr.writeCmd('module/module_load/enable', '1')
        if self.cmdList["module/module_free"]:
            SysMgr.writeCmd('module/module_free/enable', '1')
        if self.cmdList["module/module_put"]:
            SysMgr.writeCmd('module/module_put/enable', '1')
        if self.cmdList["module/module_get"]:
            SysMgr.writeCmd('module/module_get/enable', '1')

        # enable power events #
        if SysMgr.powerEnable:
            if self.cmdList["power/cpu_idle"]:
                SysMgr.writeCmd('power/cpu_idle/enable', '1')
            if self.cmdList["power/cpu_frequency"]:
                SysMgr.writeCmd('power/cpu_frequency/enable', '1')
            if self.cmdList["power/suspend_resume"]:
                SysMgr.writeCmd('power/suspend_resume/enable', '1')

        # enable reclaim events #
        if self.cmdList["vmscan/mm_vmscan_wakeup_kswapd"]:
            SysMgr.writeCmd('vmscan/mm_vmscan_wakeup_kswapd/enable', '1')
        if self.cmdList["vmscan/mm_vmscan_kswapd_sleep"]:
            SysMgr.writeCmd('vmscan/mm_vmscan_kswapd_sleep/enable', '1')

        if self.cmdList["vmscan/mm_vmscan_direct_reclaim_begin"]:
            SysMgr.writeCmd(\
                'vmscan/mm_vmscan_direct_reclaim_begin/enable', '1')
        if self.cmdList["vmscan/mm_vmscan_direct_reclaim_end"]:
            SysMgr.writeCmd(\
                'vmscan/mm_vmscan_direct_reclaim_end/enable', '1')

        # enable printk events #
        if self.cmdList["printk"]:
            SysMgr.writeCmd('printk/enable', '1')

        # enable special events #
        writeCommonCmd()

        # write user command #
        SysMgr.writeTraceCmd('AFTER')

        return



    @staticmethod
    def stopRecording():
        if not (SysMgr.isRecordMode() and \
            (SysMgr.isThreadMode() or \
            SysMgr.isFunctionMode())):
            return

        # write signal command #
        if SysMgr.cmdEnable is not False and \
            SysMgr.cmdFd:

            if SysMgr.signalCmd:
                try:
                    SysMgr.cmdFd.write(SysMgr.signalCmd)
                    SysMgr.signalCmd = None
                    SysMgr.printInfo("write commands to %s" %\
                        SysMgr.cmdEnable)
                except:
                    SysMgr.printErr("Fail to write signal command")
            elif SysMgr.outputFile:
                SysMgr.saveCmd =\
                    'cat %s../trace > %s\n' % \
                        (SysMgr.mountPath, SysMgr.outputFile)

        # start tracing #
        SysMgr.writeCmd('../tracing_on', '0')

        # disable all ftrace options registered #
        for idx, val in SysMgr.cmdList.items():
            if val:
                if SysMgr.writeCmd(str(idx) + '/enable', '0') >= 0:
                    SysMgr.writeCmd(str(idx) + '/filter', '0')

        if not SysMgr.graphEnable and \
            SysMgr.customCmd:

            for cmd in SysMgr.customCmd:
                event = cmd.split(':')[0]
                SysMgr.writeCmd(event + '/enable', '0')
                SysMgr.writeCmd(event + '/filter', '0')

        if SysMgr.isFunctionMode():
            SysMgr.writeCmd('../options/stacktrace', '0')
            SysMgr.writeCmd('../trace_options', 'nouserstacktrace')
            SysMgr.writeCmd('../tracing_on', '0')

        # write save command #
        if SysMgr.saveCmd:
            try:
                SysMgr.cmdFd.write(SysMgr.saveCmd)
                SysMgr.cmdFd.write(\
                    "echo '\nsaved command for tracing into %s\n'\n"\
                    % SysMgr.outputFile)
            except:
                SysMgr.printErr("Fail to write save command")



    def printResourceInfo(self):
        self.printSystemInfo()

        self.printOSInfo()

        self.printCpuInfo()

        self.printCpuCacheInfo()

        self.printMemInfo()

        self.printStorageInfo()

        self.printNetworkInfo()

        self.printGpuInfo()

        self.printIPCInfo()

        self.printCgroupInfo()

        self.printProcTreeInfo()



    def printProcTreeInfo(self):
        if self.procData:
            SysMgr.infoBufferPrint(self.procData)



    def printOSInfo(self):
        if not self.osData and not self.devData:
            return

        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('general', dict())
            SysMgr.jsonData['general']['os'] = dict()
            jsonData = SysMgr.jsonData['general']['os']

        SysMgr.infoBufferPrint('\n[System OS Info]')
        SysMgr.infoBufferPrint(twoLine)
        SysMgr.infoBufferPrint(\
            "{0:^35} {1:100}".format("TYPE", "Information"))
        SysMgr.infoBufferPrint(twoLine)

        # save os data #
        try:
            for data in self.osData:
                val = data.split('=')
                if len(val) < 2:
                    val = data.split(':')
                if len(val) < 2:
                    continue

                name = val[0].replace('"', '')
                value = val[1].replace('"', '').\
                    replace('\n', '').replace(',', '')
                SysMgr.infoBufferPrint(\
                    "{0:35} {1:<100}".format(name, value))

                if SysMgr.jsonOutputEnable:
                    jsonData[name] = value
        except:
            SysMgr.printWarn("Fail to parse osData")

        # save device data #
        try:
            for val in self.devData:
                val = data.split('=')
                if len(val) < 2:
                    val = data.split(':')
                if len(val) < 2:
                    continue

                name = val[0].replace('"', '')
                value = val[1].replace('"', '').\
                    replace('\n', '').replace(',', '')
                SysMgr.infoBufferPrint(\
                    "{0:35} {1:<100}".format(name, value))

                if SysMgr.jsonOutputEnable:
                    jsonData[name] = value
        except:
            pass

        SysMgr.infoBufferPrint(twoLine)



    def printSystemInfo(self):
        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('general', dict())
            jsonData = SysMgr.jsonData['general']

        SysMgr.infoBufferPrint('\n\n[System General Info]')
        SysMgr.infoBufferPrint(twoLine)
        SysMgr.infoBufferPrint(\
            "{0:^20} {1:100}".format("TYPE", "Information"))
        SysMgr.infoBufferPrint(twoLine)

        # launch option #
        try:
            launchOption = '%s%s' % (' '.join(sys.argv), ' -')
            SysMgr.infoBufferPrint("{0:20} # {1:<100}".\
                format('Launch', launchOption))

            if SysMgr.jsonOutputEnable:
                jsonData['launch'] = launchOption
        except:
            pass

        # version #
        try:
            SysMgr.infoBufferPrint("{0:20} {1:<100}".\
                format('Version', '%s' % __version__))

            if SysMgr.jsonOutputEnable:
                jsonData['version'] = __version__
        except:
            pass

        # CPU architecture #
        try:
            SysMgr.infoBufferPrint("{0:20} {1:<100}".\
                format('Arch', SysMgr.arch))

            if SysMgr.jsonOutputEnable:
                jsonData['arch'] = SysMgr.arch
        except:
            pass

        # time #
        try:
            timeInfo = '%s %s' % \
                (self.systemInfo['date'], self.systemInfo['time'])
            SysMgr.infoBufferPrint(\
                "{0:20} {1:<100}".format('Date', timeInfo))

            if SysMgr.jsonOutputEnable:
                jsonData['date'] = self.systemInfo['date']
                jsonData['time'] = self.systemInfo['time']
        except:
            pass

        # os #
        try:
            SysMgr.infoBufferPrint("{0:20} {1:<100}".\
                format('OS', self.systemInfo['osVer']))

            if SysMgr.jsonOutputEnable:
                jsonData['os'] = self.systemInfo['osVer']
        except:
            pass

        # kernel #
        try:
            kernelInfo = '%s %s' % \
                (self.systemInfo['osType'], self.systemInfo['kernelVer'])
            SysMgr.infoBufferPrint(\
                "{0:20} {1:<100}".format('Kernel', kernelInfo))

            if SysMgr.jsonOutputEnable:
                jsonData['kernel'] = kernelInfo
        except:
            pass

        # user name #
        try:
            data = SysMgr.procReadlines('self/status')

            for line in data:
                if line.startswith('Uid'):
                    uid = line.split(':')[1].split()[0]
                    break

            SysMgr.infoBufferPrint(\
                "{0:20} {1:<100}".format('User', self.userData[uid]['name']))

            if SysMgr.jsonOutputEnable:
                jsonData['user'] = self.userData[uid]['name']
        except:
            pass

        # system uptime #
        try:
            uptime = UtilMgr.convTime(SysMgr.uptime)
            SysMgr.infoBufferPrint(\
                "{0:20} {1:<100}".format('Uptime', uptime))

            if SysMgr.jsonOutputEnable:
                jsonData['uptime'] = uptime
        except:
            pass

        # Guider runtime #
        try:
            runtime = \
                long(SysMgr.uptime) - long(SysMgr.startRunTime)
            runtime = UtilMgr.convTime(runtime)
            SysMgr.infoBufferPrint(\
                "{0:20} {1:<100}".format('Runtime', runtime))

            if SysMgr.jsonOutputEnable:
                jsonData['runtime'] = runtime
        except:
            pass

        # system load #
        try:
            SysMgr.infoBufferPrint(\
                "{0:20} {1:<1} / {2:<1} / {3:<1}".format('Load', \
                str(long(float(self.loadData[0]) * 100)) + '%(1m)', \
                str(long(float(self.loadData[1]) * 100)) + '%(5m)', \
                str(long(float(self.loadData[2]) * 100)) + '%(15m)'))

            if SysMgr.jsonOutputEnable:
                jsonData['load1m'] = self.loadData[0]
                jsonData['load5m'] = self.loadData[1]
                jsonData['load15m'] = self.loadData[2]
        except:
            pass

        # task #
        try:
            running, total = self.loadData[3].split('/')
            SysMgr.infoBufferPrint(\
                "{0:20} {1:<10}".format('Threads', \
                '%s(running) / %s(total)' % (running, total)))

            if SysMgr.jsonOutputEnable:
                jsonData['nrRunTask'] = running
                jsonData['nrTotalTask'] = total
        except:
            pass

        # last pid #
        try:
            SysMgr.infoBufferPrint(\
                "{0:20} {1:<10}".format('LastPid', self.loadData[4]))

            if SysMgr.jsonOutputEnable:
                jsonData['lastPid'] = self.loadData[4]
        except:
            pass

        # MAC #
        try:
            if self.macAddr is None:
                raise Exception()

            macStr = '%s_%s' % (self.macAddr[0], self.macAddr[1])
            SysMgr.infoBufferPrint(\
                "{0:20} {1:<10}".format('Mac', macStr))

            if SysMgr.jsonOutputEnable:
                jsonData['mac'] = macStr
        except:
            pass

        # kernel args #
        try:
            title = 'Cmdline'
            splitLen = SysMgr.lineLength - 21
            cmdlineList = \
                [self.cmdlineData[i:i+splitLen] for i in \
                range(0, len(self.cmdlineData), splitLen)]
            for string in cmdlineList:
                SysMgr.infoBufferPrint(\
                    "{0:20} {1:<100}".format(title, string))
                title = ''

            if SysMgr.jsonOutputEnable:
                jsonData['cmdline'] = self.cmdlineData
        except:
            pass

        SysMgr.infoBufferPrint(twoLine)



    def printCpuCacheInfo(self):
        if len(self.cpuCacheInfo) == 0:
            return

        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('general', dict())
            SysMgr.jsonData['general']['cache'] = dict()
            jsonData = SysMgr.jsonData['general']['cache']

        SysMgr.infoBufferPrint('\n[System CPU Cache Info]')
        SysMgr.infoBufferPrint(twoLine)
        SysMgr.infoBufferPrint(\
            "{0:^20} {1:100}".format("Core", "Information"))
        SysMgr.infoBufferPrint(twoLine)

        cnt = long(0)
        try:
            for core, info in sorted(\
                self.cpuCacheInfo.items(), key=lambda e: long(e[0][3:])):
                try:
                    SysMgr.infoBufferPrint(\
                        "{0:^20} {1:<100}".format(core[3:], info.strip()))
                    cnt += 1

                    if SysMgr.jsonOutputEnable:
                        jsonData[core[3:]] = info.strip()
                except:
                    pass
        except:
            pass

        if cnt == 0:
            SysMgr.infoBufferPrint("{0:^16}".format('None'))

        SysMgr.infoBufferPrint(twoLine)



    def printCpuInfo(self):
        # parse data #
        if self.cpuData:
            for l in self.cpuData:
                m = re.match(r'(?P<type>.*):\s+(?P<val>.*)', l)
                if not m:
                    continue

                d = m.groupdict()
                self.cpuInfo[d['type'][0:len(d['type'])-1]] = d['val']
        else:
            return

        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('general', dict())
            SysMgr.jsonData['general']['cpu'] = dict()
            jsonData = SysMgr.jsonData['general']['cpu']

        SysMgr.infoBufferPrint('\n[System CPU Info]')
        SysMgr.infoBufferPrint(twoLine)
        SysMgr.infoBufferPrint(\
            "{0:^20} {1:100}".format("TYPE", "Information"))
        SysMgr.infoBufferPrint(twoLine)

        try:
            physical = long(self.cpuInfo['physical id']) + 1
            SysMgr.infoBufferPrint("{0:20} {1:<100}".\
                format('Physical', physical))

            if SysMgr.jsonOutputEnable:
                jsonData['physical'] = physical
        except:
            pass

        try:
            SysMgr.infoBufferPrint("{0:20} {1:<100}".\
                format('CoresPerCPU', self.cpuInfo['cpu cores']))

            if SysMgr.jsonOutputEnable:
                jsonData['corePerCPU'] = self.cpuInfo['cpu cores']
        except:
            pass

        try:
            logical = long(self.cpuInfo['processor']) + 1
            SysMgr.infoBufferPrint("{0:20} {1:<100}".\
                format('Logical', logical))

            if SysMgr.jsonOutputEnable:
                jsonData['logical'] = logical
        except:
            pass

        try:
            SysMgr.infoBufferPrint("{0:20} {1:<100}".\
                format('Vendor', self.cpuInfo['vendor_id']))

            if SysMgr.jsonOutputEnable:
                jsonData['vendor'] = self.cpuInfo['vendor_id']
        except:
            pass

        try:
            SysMgr.infoBufferPrint("{0:20} {1:<100}".\
                format('Model', self.cpuInfo['model name']))

            if SysMgr.jsonOutputEnable:
                jsonData['model'] = self.cpuInfo['model name']
        except:
            pass

        try:
            SysMgr.infoBufferPrint("{0:20} {1:<100}".\
                format('Cache(L2)', self.cpuInfo['cache size']))

            if SysMgr.jsonOutputEnable:
                jsonData['cacheL2'] = self.cpuInfo['cache size']
        except:
            pass

        try:
            SysMgr.infoBufferPrint("{0:20} {1:<100}".\
                format('Perf', self.cpuInfo['bogomips']))

            if SysMgr.jsonOutputEnable:
                jsonData['perf'] = self.cpuInfo['bogomips']
        except:
            pass

        try:
            SysMgr.infoBufferPrint("{0:20} {1:<100}".\
                format('Address', self.cpuInfo['address sizes']))

            if SysMgr.jsonOutputEnable:
                jsonData['address'] = self.cpuInfo['address sizes']
        except:
            pass

        SysMgr.infoBufferPrint(twoLine)



    def updateDiskInfo(self, time, data):
        self.diskInfo[time] = dict()

        if not data:
            return

        for l in data:
            values = l.split()

            diskStat = {}
            for idx, item in enumerate(list(l.split())):
                if len(ConfigMgr.DISKSTAT) <= idx:
                    SysMgr.printWarn(\
                        "Fail to parse all diskstat because of overflow")
                    break
                diskStat[ConfigMgr.DISKSTAT[idx]] = item

            self.diskInfo[time][diskStat['name']] = dict()
            diskInfoBuf = self.diskInfo[time][diskStat['name']]

            # save recent stat #
            diskInfoBuf['major'] = diskStat['major']
            diskInfoBuf['minor'] = diskStat['minor']
            diskInfoBuf['sectorRead'] = diskStat['sectorRead']
            diskInfoBuf['readTime'] = diskStat['readTime']
            diskInfoBuf['sectorWrite'] = diskStat['sectorWrite']
            diskInfoBuf['writeTime'] = diskStat['writeTime']
            diskInfoBuf['currentIO'] = diskStat['currentIO']
            diskInfoBuf['ioTime'] = diskStat['ioTime']
            diskInfoBuf['ioWTime'] = diskStat['ioWTime']



    def updateMountInfo(self):
        class MountException(Exception):
            pass

        if not self.mountData:
            return

        # parse mount info #
        for l in self.mountData:
            # leave for /proc/mounts #
            #dev, path, fs, option, etc1, etc2 = l.split()

            # split mount info #
            values = l.split(' - ')
            if len(values) != 2:
                continue
            left = values[0]
            right = values[1]

            # split left-side part #
            left = left.split()
            mountid, parentid, devid, root, path = left[:5]
            major, minor = devid.split(':')
            option = ' '.join(left[5:-1])

            # split right-side part #
            right = right.split()
            fs, dev = right[0:2]
            soption = ' '.join(right[2:])

            # check skip condition #
            try:
                # special device #
                if not dev.startswith('/'):
                    rpath = path
                else:
                    rpath = os.path.realpath(dev)
                    dev = os.path.basename(rpath)

                if fs == 'tmpfs':
                    continue

                if ':' in dev:
                    major, minor = dev.split(':')
                    for mp in self.diskInfo['prev'].values():
                        if mp['major'] == major and mp['minor'] == minor:
                            raise MountException

                if not dev in self.diskInfo['prev']:
                    # check nodes by device id #
                    for node, attr in self.diskInfo['prev'].items():
                        if attr['major'] == major and attr['minor'] == minor:
                            raise MountException
                    continue
            except MountException:
                pass
            except:
                continue

            # save mount info #
            self.mountInfo[rpath] = dict()
            self.mountInfo[rpath]['major'] = major
            self.mountInfo[rpath]['minor'] = minor
            self.mountInfo[rpath]['mountid'] = mountid
            self.mountInfo[rpath]['path'] = path
            self.mountInfo[rpath]['fs'] = fs
            self.mountInfo[rpath]['option'] = option
            self.mountInfo[rpath]['soption'] = soption



    def updateShmInfo(self):
        try:
            SysMgr.shmFd.seek(0)
            data = SysMgr.shmFd.readlines()[1:]
        except:
            try:
                path = '%s/sysvipc/shm' % SysMgr.procPath
                SysMgr.shmFd = open(path, 'r')
                data = SysMgr.shmFd.readlines()[1:]
            except:
                SysMgr.printOpenWarn(path)
                return

        # backup shm data #
        try:
            self.prevIpcData['shm'] = self.ipcData['shm']
        except:
            pass

        # initialize shm variable #
        self.ipcData['shm'] = dict()

        # parse new shm data #
        for line in data:
            try:
                key, shmid, perms, size, cpid, lpid, \
                    nattch, uid, gid, cuid, cgid, \
                    atime, dtime, ctime, rss, swap = \
                        line.split()
            except:
                pass

            shmData = self.ipcData['shm'][shmid] = dict()
            shmData['key'] = key
            shmData['perms'] = perms
            shmData['size'] = long(size)
            shmData['rss'] = long(rss)
            shmData['swap'] = long(swap)
            shmData['uid'] = uid
            shmData['gid'] = gid
            shmData['cpid'] = cpid
            shmData['lpid'] = lpid
            shmData['nattch'] = nattch
            shmData['atime'] = dtime
            shmData['dtime'] = dtime
            shmData['ctime'] = ctime



    def updateMsgqInfo(self):
        try:
            SysMgr.msgqFd.seek(0)
            data = SysMgr.msgqFd.readlines()[1:]
        except:
            try:
                path = '%s/sysvipc/msg' % SysMgr.procPath
                SysMgr.msgqFd = open(path, 'r')
                data = SysMgr.msgqFd.readlines()[1:]
            except:
                SysMgr.printOpenWarn(path)
                return

        # backup msgq data #
        try:
            self.prevIpcData['msgq'] = self.ipcData['msgq']
        except:
            pass

        # initialize msgq variable #
        self.ipcData['msgq'] = dict()

        # parse new msgq data #
        for line in data:
            try:
                key, msgqid, perms, cbytes, qnum, \
                    lspid, lrpid, uid, gid, cuid, cgid, \
                    stime, rtime, ctime = \
                        line.split()
            except:
                pass

            msgqData = self.ipcData['msgq'][msgqid] = dict()
            msgqData['key'] = key
            msgqData['perms'] = perms
            msgqData['cbytes'] = cbytes
            msgqData['qnum'] = qnum
            msgqData['lspid'] = lspid
            msgqData['lrpid'] = lrpid
            msgqData['uid'] = uid
            msgqData['gid'] = gid
            msgqData['cuid'] = cuid
            msgqData['cgid'] = cgid
            msgqData['stime'] = stime
            msgqData['rtime'] = rtime
            msgqData['ctime'] = ctime



    def updateSemInfo(self):
        try:
            SysMgr.semFd.seek(0)
            data = SysMgr.semFd.readlines()[1:]
        except:
            try:
                path = '%s/sysvipc/sem' % SysMgr.procPath
                SysMgr.semFd = open(path, 'r')
                data = SysMgr.semFd.readlines()[1:]
            except:
                SysMgr.printOpenWarn(path)
                return

        # backup sem data #
        try:
            self.prevIpcData['sem'] = self.ipcData['sem']
        except:
            pass

        # initialize sem variable #
        self.ipcData['sem'] = dict()

        # parse new sem data #
        for line in data:
            try:
                key, semid, perms, nsems, \
                    uid, gid, cuid, cgid, otime, ctime = \
                        line.split()
            except:
                pass

            semData = self.ipcData['sem'][semid] = dict()
            semData['key'] = key
            semData['perms'] = perms
            semData['nsems'] = nsems
            semData['uid'] = uid
            semData['gid'] = gid
            semData['cuid'] = cuid
            semData['cgid'] = cgid
            semData['otime'] = otime
            semData['ctime'] = ctime



    def saveMacAddr(self):
        if self.macAddr:
            return

        # mac address #
        try:
            self.macAddr = NetworkMgr.getRepMacAddr()
        except:
            pass



    def updateIPCInfo(self):
        # check update time #
        if self.ipcUpdate == SysMgr.uptime:
            return
        else:
            self.ipcUpdate = SysMgr.uptime

        # shared memory #
        self.updateShmInfo()

        # message queue #
        self.updateMsgqInfo()

        # semaphore #
        self.updateSemInfo()



    def updateNetworkInfo(self):
        # check update time #
        if self.netUpdate == SysMgr.uptime:
            return
        else:
            self.netUpdate = SysMgr.uptime

        try:
            SysMgr.netdevFd.seek(0)
            data = SysMgr.netdevFd.readlines()[2:]
        except:
            try:
                devPath = '%s/net/dev' % SysMgr.procPath
                SysMgr.netdevFd = open(devPath, 'r')
                data = SysMgr.netdevFd.readlines()[2:]
            except:
                SysMgr.printOpenWarn(devPath)
                return

        try:
            socket = SysMgr.getPkg('socket', False)
            fcntl = SysMgr.getPkg('fcntl', False)
        except:
            socket = fcntl = None

        try:
            for line in data:
                dev, stats = line.split(':')

                dev = dev.strip()

                try:
                    self.networkInfo[dev]
                except:
                    self.networkInfo[dev] = dict()

                # set ip addr #
                try:
                    if not SysMgr.localServObj:
                        NetworkMgr.setServerNetwork(None, None)

                    sockObj = SysMgr.localServObj

                    res = fcntl.ioctl(\
                        sockObj.socket.fileno(), 0x8915, # SIOCGIFADDR
                        struct.pack('256s', dev[:15].encode('utf-8')))
                    ipaddr = socket.inet_ntoa(res[20:24])
                except:
                    ipaddr = ''

                self.networkInfo[dev]['ipaddr'] = ipaddr

                stats = stats.split()
                '''
                bytes, packets, errs, drop, fifo, \
                    frame, compressed, multicast
                '''

                nrdvd = long(len(stats) / 2)

                # Receive #
                rlist = list(map(long, stats[:nrdvd]))

                if 'recv' in self.networkInfo[dev]:
                    self.networkInfo[dev]['rdiff'] = list()

                    for idx, val in enumerate(rlist):
                        self.networkInfo[dev]['rdiff'].append(\
                            val - self.networkInfo[dev]['recv'][idx])
                else:
                    self.networkInfo[dev]['initrecv'] = rlist

                self.networkInfo[dev]['recv'] = rlist

                # Transmit #
                tlist = list(map(long, stats[nrdvd:]))

                if 'tran' in self.networkInfo[dev]:
                    self.networkInfo[dev]['tdiff'] = list()

                    for idx, val in enumerate(tlist):
                        self.networkInfo[dev]['tdiff'].append(\
                            val - self.networkInfo[dev]['tran'][idx])
                else:
                    self.networkInfo[dev]['inittran'] = tlist

                self.networkInfo[dev]['tran'] = tlist
        except:
            return



    def saveUserInfo(self):
        # check user data #
        if len(self.userData) > 0:
            return

        try:
            path = '/etc/passwd'
            with open(path, 'rb') as fd:
                data = fd.readlines()
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printOpenWarn(path)
            return

        # parse data #
        for line in data:
            try:
                user, passwd, uid, gid, info, home, shell = \
                    line.decode().split(':')

                self.userData[uid] = {
                    'name': user,
                    'gid': gid,
                    'info': info,
                    'home': home,
                    'shell': shell,
                }
            except:
                pass



    def updateStorageInfo(self, isGeneral=False):
        # check update time #
        if self.storageUpdate == SysMgr.uptime:
            return
        else:
            self.storageUpdate = SysMgr.uptime

        # get device type #
        self.saveDevInfo()

        # get storage info and update stat #
        self.saveStorageInfo(isGeneral)

        # get mount info #
        self.updateMountInfo()

        # get storage stat #
        self.prevStorageData = self.storageData
        self.storageData = self.getStorageInfo()



    def getStorageInfo(self):
        storageData = dict()
        init_storageData = \
            {'total': long(0), 'free': long(0), 'favail': long(0), \
            'read': long(0), 'write': long(0), 'usage': long(0), \
            'usageper': long(0), 'mount': None}

        storageData['total'] = dict(init_storageData)

        # make block device table #
        for key, val in sorted(self.mountInfo.items(), key=lambda e: e[0]):
            # check device node path #
            if key[0] != '/':
                continue

            storageData[key] = dict(init_storageData)
            storageData[key]['mount'] = val

            # calculate read & write load of devices #
            try:
                # get node name from full-path #
                dev = key[key.rfind('/')+1:]

                if ':' in dev:
                    major, minor = dev.split(':')
                    for name, mp in self.diskInfo['prev'].items():
                        if mp['major'] == major and mp['minor'] == minor:
                            dev = name

                # define shortcut variable of this device info #
                beforeInfo = self.diskInfo['prev'][dev]
                afterInfo = self.diskInfo['next'][dev]

                # get interval load of this device #
                read = \
                    (long(afterInfo['sectorRead']) - \
                    long(beforeInfo['sectorRead'])) << 9
                read = read >> 20

                write = \
                    (long(afterInfo['sectorWrite']) - \
                    long(beforeInfo['sectorWrite'])) << 9
                write = write >> 20

                load = \
                    long(afterInfo['sectorRead']) + \
                    long(afterInfo['sectorWrite'])

                readtime = long(afterInfo['readTime'])
                writetime = long(afterInfo['writeTime'])
                iotime = long(afterInfo['ioTime'])
                iowtime = long(afterInfo['ioWTime'])

                # save recent stat #
                storageData[key]['read'] = read
                storageData[key]['write'] = write
                storageData[key]['load'] = load
                storageData[key]['readtime'] = readtime
                storageData[key]['writetime'] = writetime
                storageData[key]['iotime'] = iotime
                storageData[key]['iowtime'] = iowtime

                storageData['total']['read'] += read
                storageData['total']['write'] += write
            except:
                pass

            # get device stat #
            try:
                stat = os.statvfs(val['path'])

                total = (stat.f_bsize * stat.f_blocks) >> 20
                free = (stat.f_bsize * stat.f_bavail) >> 20
                avail = stat.f_favail
                usage = long((total - free) / float(total) * 100)

                storageData[key]['total'] = total
                storageData[key]['free'] = free
                storageData[key]['usage'] = total - free
                storageData[key]['usageper'] = usage
                storageData[key]['favail'] = avail

                storageData['total']['total'] += total
                storageData['total']['free'] += free
                storageData['total']['favail'] += avail
            except:
                pass

        # set total storage stat #
        try:
            total = storageData['total']
            storageData['total']['usage'] = \
                total['total'] - total['free']
            storageData['total']['usageper'] = \
                long((total['total'] - total['free']) / \
                float(total['total']) * 100)
        except:
            pass

        return storageData



    def getCgroupPath(self):
        if not self.mountData:
            return None

        # search cgroup mount point #
        for mount in self.mountData:
            mountList = mount.split(' - ')

            if not mountList[1].startswith('cgroup'):
                continue

            mountpath = mountList[0].split()[4]

            # check cgroup version #
            if mountList[1].startswith('cgroup2'):
                return mountpath
            else:
                return mountpath[:mountpath.rfind('/')]

        return None



    def getCgroupTree(self):
        def updateValues(dirpath, subfiles, item):
            for target in subfiles:
                if not target in ConfigMgr.CGROUP_VALUE:
                    continue

                try:
                    path = '%s/%s' % (dirpath, target)
                    with open(path, 'r') as fd:
                        if target == 'tasks' or target == 'cgroup.procs':
                            taskList = fd.read().splitlines()
                            item[target] = \
                                UtilMgr.convNum(len(taskList))
                            if SysMgr.showAll and \
                                len(taskList) > 0 and target == 'cgroup.procs':
                                item['PROCS'] = dict.fromkeys(taskList, {})
                        else:
                            cval = fd.readline()[:-1]
                            if cval.isdigit():
                                cval = UtilMgr.convNum(long(cval))
                            elif cval == '':
                                cval = 'none'
                            item[target] = cval
                except SystemExit:
                    sys.exit(0)
                except:
                    pass

        def getPaths(root, path):
            for dirpath, subdirs, subfiles in path:
                # update subdir #
                for item in subdirs:
                    subdir = os.path.join(dirpath, item)
                    root[subdir] = dict()

                # update subfiles #
                for item in subfiles:
                    subfile = os.path.join(dirpath, item)

                    # check value file #
                    if not item in ConfigMgr.CGROUP_VALUE:
                        continue

                    root.setdefault(dirpath, {})
                    updateValues(dirpath, subfiles, root[dirpath])

        cgroupPath = self.getCgroupPath()
        if not cgroupPath:
            return None

        # get full path list #
        dirList = dict()
        getPaths(dirList, os.walk(cgroupPath))

        # split a path to multiple tokens #
        dirDict = {}
        for item, val in dirList.items():
            # skip symbolic link #
            if os.path.islink(item):
                continue

            p = dirDict
            tokList = item[len(cgroupPath):].split('/')[1:]
            for x in tokList:
                p = p.setdefault(x, {})

            # merge with a value #
            p.update(val)

        return dirDict



    def printCgroupInfo(self, printTitle=True):
        commList = {}

        def printDirTree(root, depth):
            if type(root) is not dict:
                return

            tempRoot = deepcopy(root)

            for curdir, subdir in sorted(\
                tempRoot.items(), \
                key=lambda e: long(e[0]) if e[0].isdigit() else e[0]):
                cstr = ''
                nrProcs = long(0)
                nrTasks = long(0)

                # check subdir type #
                if type(subdir) is not dict:
                    continue

                tempSubdir = deepcopy(subdir)
                for val in list(subdir.keys()):
                    if not val in ConfigMgr.CGROUP_VALUE:
                        continue
                    elif val == 'tasks':
                        nrTasks = subdir[val]
                        tempSubdir.pop(val, None)
                        continue
                    elif val == 'cgroup.procs':
                        nrProcs = subdir[val]
                        tempSubdir.pop(val, None)
                        continue

                    cname = '.'.join(val.split('.')[1:])
                    cstr = '%s%s:%s, ' % (cstr, cname, subdir[val])
                    tempSubdir.pop(val, None)

                indent = ''
                if depth == 0:
                    indent = '\n'

                for idx in range(0, depth):
                    indent = '%s%s|' % (indent, '     ')

                if len(cstr) > 0:
                    cstr = '<%s>' % cstr[:-2]

                nrWorker = '(proc:%s,task:%s)' % (nrProcs, nrTasks)
                if len(tempSubdir) > 0:
                    nrChild = '[sub:%s]' % len(tempSubdir)

                    if curdir == 'PROCS':
                        nrWorker = ''

                    SysMgr.infoBufferPrint(\
                        '%s- %s%s%s%s' % \
                        (indent, curdir, nrChild, nrWorker, cstr))
                elif depth > 0 and nrProcs == nrTasks == 0:
                    if curdir in commList:
                        comm = commList[curdir]
                    else:
                        comm = commList[curdir] = \
                            SysMgr.getComm(curdir)

                    SysMgr.infoBufferPrint(\
                        '%s- %s(%s)' % \
                        (indent, comm, curdir))
                else:
                    SysMgr.infoBufferPrint(\
                        '%s- %s%s%s' % \
                        (indent, curdir, nrWorker, cstr))

                printDirTree(tempSubdir, depth + 1)

            if depth == 0:
                SysMgr.infoBufferPrint(' ')

        # check cgroup option #
        if not SysMgr.cgroupEnable:
            return

        try:
            cgroupTree = self.getCgroupTree()
            if not cgroupTree:
                return
        except SystemExit:
            sys.exit(0)
        except:
            return

        # print cgroup info #
        if printTitle:
            SysMgr.infoBufferPrint('\n[System Cgroup Info]')
            SysMgr.infoBufferPrint(twoLine)

        printDirTree(cgroupTree, 0)

        if printTitle:
            SysMgr.infoBufferPrint(twoLine)

        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('general', dict())
            SysMgr.jsonData['general']['cgroup'] = cgroupTree



    def printIPCInfo(self):
        self.printShmInfo()
        self.printMsgqInfo()
        self.printSemInfo()



    def printShmInfo(self):
        # check shm data #
        if not 'shm' in self.ipcData:
            return

        # print IPC info #
        SysMgr.infoBufferPrint('\n[System SHM Info]')
        SysMgr.infoBufferPrint(twoLine)
        SysMgr.infoBufferPrint(\
            "{0:^70} | {1:^24} | {2:^15} | {3:^36} ".format(\
            "ID", "Segment", "Attr", "Time"))
        SysMgr.infoBufferPrint(oneLine)
        SysMgr.infoBufferPrint((\
            "{0:^26}   {1:^14}   {2:^24} | "
            "{3:^6}   {4:^6}   {5:^6} | "
            "{6:^6}   {7:^6} | {8:^10}   {9:^10}   {10:^10}".format(\
                "OWNER", "SHM", "USER", "SIZE", "RSS", \
                "SWAP", "REF", "PERM", "ATIME", "DTIME", "CTIME")))
        SysMgr.infoBufferPrint(twoLine)

        # get attr #
        cnt = long(0)
        prevOwner = None
        now = time.mktime(time.gmtime())
        convertSizeFunc = UtilMgr.convSize2Unit
        convTimeFunc = UtilMgr.convTime

        # merge stats per-owner #
        ownerData = dict()
        for shmid, stats in self.ipcData['shm'].items():
            try:
                owner = stats['cpid']

                ownerData[owner]['count'] += 1
                ownerData[owner]['size'] += stats['size']
                ownerData[owner]['rss'] += stats['rss']
                ownerData[owner]['swap'] += stats['swap']
            except:
                ownerData[owner] = dict()
                ownerData[owner]['uid'] = stats['uid']
                ownerData[owner]['count'] = 1
                ownerData[owner]['size'] = stats['size']
                ownerData[owner]['rss'] = stats['rss']
                ownerData[owner]['swap'] = stats['swap']

        # print stats #
        for shmid, stats in sorted(\
            self.ipcData['shm'].items(), key=lambda e:e[1]['cpid']):

            # get owner name #
            try:
                pid = stats['cpid']

                if pid != prevOwner:
                    prevOwner = pid

                    comm = SysMgr.getComm(pid)
                    if not comm:
                        raise Exception()

                    owner = '%s(%s)' % (comm, pid)
                else:
                    owner = ''
            except:
                owner = '? (%s)' % pid

            # print total stat #
            try:
                if len(owner) == 0:
                    raise Exception()

                try:
                    user = self.userData[stats['uid']]['name']
                    owner = '%s[%s]' % (owner, user)
                except:
                    pass

                if cnt > 0:
                    SysMgr.infoBufferPrint(oneLine)

                totalStat = '[ TOTAL: %s ]' % ownerData[pid]['count']
                space = 70 - len(owner) - len(totalStat)
                totalStr = '%s%s%s' % (owner, ' ' * space, totalStat)
                SysMgr.infoBufferPrint(\
                    "{0:>40}   {1:>6}   {2:>6}   {3:>6}   {4:>15}".format(\
                        totalStr, \
                        convertSizeFunc(ownerData[pid]['size'], True), \
                        convertSizeFunc(ownerData[pid]['rss'], True), \
                        convertSizeFunc(ownerData[pid]['swap'], True), \
                        ' '))
            except:
                pass

            owner = ''

            try:
                pid = stats['lpid']
                comm = SysMgr.getComm(pid)
                if not comm:
                    raise Exception()

                access = '%s (%s)' % (comm, pid)
            except:
                access = '? (%s)' % stats['lpid']

            # get time #
            atime = now - time.mktime(time.gmtime(long(stats['atime'])))
            if atime < 0:
                atime = '?'
            dtime = now - time.mktime(time.gmtime(long(stats['dtime'])))
            if dtime < 0:
                dtime = '?'
            ctime = now - time.mktime(time.gmtime(long(stats['ctime'])))
            if ctime < 0:
                ctime = '?'

            # print stats #
            try:
                SysMgr.infoBufferPrint((\
                    "{0:>26}   {1:>14}   {2:>24}   {3:>6}   {4:>6}   "
                    "{5:>6}   {6:>6}   {7:>6}   {8:>10}   {9:>10}   "
                    "{10:>10}").format(\
                        owner, shmid, access, \
                        convertSizeFunc(stats['size'], True), \
                        convertSizeFunc(stats['rss'], True), \
                        convertSizeFunc(stats['swap'], True), \
                        stats['nattch'], stats['perms'], \
                        convTimeFunc(atime)[:10], \
                        convTimeFunc(dtime)[:10], \
                        convTimeFunc(ctime)[:10]))

                cnt += 1
            except:
                pass

        # check output count #
        if cnt == 0:
            SysMgr.infoBufferPrint('\tNone')

        SysMgr.infoBufferPrint(twoLine)



    def printSemInfo(self):
        pass



    def printMsgqInfo(self):
        pass



    def printGpuInfo(self):
        try:
            gpuInfo = SysMgr.getGpuInfo()
            if not gpuInfo:
                return None
        except:
            return None

        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('general', dict())
            SysMgr.jsonData['general']['gpu'] = dict()
            jsonData = SysMgr.jsonData['general']['gpu']

        # print GPU info #
        SysMgr.infoBufferPrint('\n[System GPU Info]')
        SysMgr.infoBufferPrint(twoLine)
        SysMgr.infoBufferPrint(\
            "{0:^32} | {1:^16} | {2:^32} |\n{3:1}".format(\
            "Name", "Stat", "Value", oneLine))

        for item in gpuInfo.values():
            name = item['name']
            for key, value in sorted(item.items()):
                if key == 'name':
                    continue

                SysMgr.infoBufferPrint(\
                    "{0:^32} | {1:>16} | {2:>32} |".format(\
                        name, key, value))

                name = ''

            SysMgr.infoBufferPrint(oneLine)



    def printNetworkInfo(self):
        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('general', dict())
            SysMgr.jsonData['general']['network'] = dict()
            jsonData = SysMgr.jsonData['general']['network']

        # print network info #
        SysMgr.infoBufferPrint('\n[System Network Info]')
        SysMgr.infoBufferPrint(twoLine)
        SysMgr.infoBufferPrint(\
            "{0:^38} | {1:^45} | {2:^45}\n{3:1}".format(\
            "Network", "Receive", "Transfer", oneLine))
        SysMgr.infoBufferPrint((\
            "{0:^16} {1:^21} | "
            "{2:^8} {3:^8} {4:^8} {5:^8} {6:^9} | "
            "{2:^8} {3:^8} {4:^8} {5:^8} {6:^9}").format(\
                "Dev", "TYPE", "Size", "Packet", "Error", "Drop", "Multicast"))
        SysMgr.infoBufferPrint(twoLine)

        convertFunc = UtilMgr.convSize2Unit

        cnt = 1
        totalStat = \
            {'rdiff': [0] * 5, 'tdiff': [0] * 5, \
                'rtotal': [0] * 5, 'ttotal': [0] * 5}

        for dev, val in sorted(self.networkInfo.items(), key=lambda e:e[0]):
            try:
                '''
                [ network stat sequence ]
                bytes, packets, errs, drop, fifo, \
                    frame, compressed, multicast
                '''

                # recv diff #
                rdiff = list()
                for idx, stat in enumerate(val['recv']):
                    rdiff.append(stat - val['initrecv'][idx])

                # tran diff #
                tdiff = list()
                for idx, stat in enumerate(val['tran']):
                    tdiff.append(stat - val['inittran'][idx])

                # sum diff stats #
                totalStat['rdiff'][0] += rdiff[0]
                totalStat['rdiff'][1] += rdiff[1]
                totalStat['rdiff'][2] += rdiff[2]
                totalStat['rdiff'][3] += rdiff[3]
                totalStat['rdiff'][4] += rdiff[-1]
                totalStat['tdiff'][0] += tdiff[0]
                totalStat['tdiff'][1] += tdiff[1]
                totalStat['tdiff'][2] += tdiff[2]
                totalStat['tdiff'][3] += tdiff[3]
                totalStat['tdiff'][4] += tdiff[-1]

                SysMgr.infoBufferPrint((\
                    "{0:>16} {1:^21}   "
                    "{2:>8} {3:>8} {4:>8} {5:>8} {6:>9}   "
                    "{7:>8} {8:>8} {9:>8} {10:>8} {11:>9}").format(\
                        dev, 'DIFF',\
                        convertFunc(rdiff[0]), convertFunc(rdiff[1]), \
                        convertFunc(rdiff[2]), convertFunc(rdiff[3]), \
                        convertFunc(rdiff[-1]), \
                        convertFunc(tdiff[0]), convertFunc(tdiff[1]), \
                        convertFunc(tdiff[2]), convertFunc(tdiff[3]), \
                        convertFunc(tdiff[-1])))

                # per-device total stats #
                rlist = val['recv']
                tlist = val['tran']

                # sum total stats #
                totalStat['rtotal'][0] += rlist[0]
                totalStat['rtotal'][1] += rlist[1]
                totalStat['rtotal'][2] += rlist[2]
                totalStat['rtotal'][3] += rlist[3]
                totalStat['rtotal'][4] += rlist[-1]
                totalStat['ttotal'][0] += tlist[0]
                totalStat['ttotal'][1] += tlist[1]
                totalStat['ttotal'][2] += tlist[2]
                totalStat['ttotal'][3] += tlist[3]
                totalStat['ttotal'][4] += tlist[-1]

                SysMgr.infoBufferPrint((\
                    "{0:>16} {1:^21}   "
                    "{2:>8} {3:>8} {4:>8} {5:>8} {6:>9}   "
                    "{7:>8} {8:>8} {9:>8} {10:>8} {11:>9}").format(\
                        ' ', 'TOTAL',\
                        convertFunc(rlist[0]), convertFunc(rlist[1]), \
                        convertFunc(rlist[2]), convertFunc(rlist[3]), \
                        convertFunc(rlist[-1]), \
                        convertFunc(tlist[0]), convertFunc(tlist[1]), \
                        convertFunc(tlist[2]), convertFunc(tlist[3]), \
                        convertFunc(tlist[-1])))

                if cnt < len(self.networkInfo):
                    SysMgr.infoBufferPrint(\
                        "{0:1}".format(oneLine))

                cnt += 1

                if SysMgr.jsonOutputEnable:
                    jsonData[dev] = dict()

                    jsonData[dev]['ipaddr'] = val['ipaddr']

                    jsonData[dev]['recv'] = {
                        'bytes': convertFunc(rlist[0]),
                        'packets': convertFunc(rlist[1]),
                        'errs': convertFunc(rlist[2]),
                        'drop': convertFunc(rlist[3]),
                        'fifo': convertFunc(rlist[4]),
                        'frame': convertFunc(rlist[5]),
                        'compressed': convertFunc(rlist[6]),
                        'multicast': convertFunc(rlist[7]),
                    }

                    jsonData[dev]['trans'] = {
                        'bytes': convertFunc(tlist[0]),
                        'packets': convertFunc(tlist[1]),
                        'errs': convertFunc(tlist[2]),
                        'drop': convertFunc(tlist[3]),
                        'fifo': convertFunc(tlist[4]),
                        'frame': convertFunc(tlist[5]),
                        'compressed': convertFunc(tlist[6]),
                        'multicast': convertFunc(tlist[7]),
                    }
            except:
                pass

        if cnt == 1:
            SysMgr.infoBufferPrint("\tNone")
        else:
            rdiff = totalStat['rdiff']
            tdiff = totalStat['tdiff']
            SysMgr.infoBufferPrint((\
                "{12:1}\n{0:>16} {1:^21}   "
                "{2:>8} {3:>8} {4:>8} {5:>8} {6:>9}   "
                "{7:>8} {8:>8} {9:>8} {10:>8} {11:>9}").format(\
                    '[ TOTAL ]', 'DIFF',\
                    convertFunc(rdiff[0]), convertFunc(rdiff[1]), \
                    convertFunc(rdiff[2]), convertFunc(rdiff[3]), \
                    convertFunc(rdiff[-1]), \
                    convertFunc(tdiff[0]), convertFunc(tdiff[1]), \
                    convertFunc(tdiff[2]), convertFunc(tdiff[3]), \
                    convertFunc(tdiff[-1]), oneLine))

            rtotal = totalStat['rtotal']
            ttotal = totalStat['ttotal']
            SysMgr.infoBufferPrint((\
                "{0:>16} {1:^21}   "
                "{2:>8} {3:>8} {4:>8} {5:>8} {6:>9}   "
                "{7:>8} {8:>8} {9:>8} {10:>8} {11:>9}").format(\
                    ' ', 'TOTAL',\
                    convertFunc(rtotal[0]), convertFunc(rtotal[1]), \
                    convertFunc(rtotal[2]), convertFunc(rtotal[3]), \
                    convertFunc(rtotal[-1]), \
                    convertFunc(ttotal[0]), convertFunc(ttotal[1]), \
                    convertFunc(ttotal[2]), convertFunc(ttotal[3]), \
                    convertFunc(ttotal[-1])))

        SysMgr.infoBufferPrint("%s" % twoLine)



    def printStorageInfo(self):
        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('general', dict())
            SysMgr.jsonData['general']['storage'] = dict()
            jsonData = SysMgr.jsonData['general']['storage']

        # print storage info #
        SysMgr.infoBufferPrint('\n[System Storage Info]')
        SysMgr.infoBufferPrint(twoLine)
        SysMgr.infoBufferPrint((\
            "{0:^16} {1:>7} {2:>8} {3:>8} {4:>8} "
            "{5:>8} {6:>6} {7:>7} {8:>8} {9:>40}").\
            format("DEV", "NUM", "READ", "WRITE", \
            "TOTAL", "FREE", "USAGE", "AVF", "FS", "MountPoint <Option>"))
        SysMgr.infoBufferPrint(twoLine)

        devInfo = {}
        totalInfo = \
            {'total': long(0), 'free': long(0), 'favail': long(0), \
            'read': long(0), 'write': long(0)}
        outputCnt = long(0)

        # create block device table #
        for key, val in sorted(self.mountInfo.items(), key=lambda e: e[0]):
            # check device node path #
            if val['fs'] == 'tmpfs':
                key = val['path']

            if key[0] == '/':
                devInfo[key] = {}
                outputCnt += 1
            else:
                continue

            # calculate read & write size of devices #
            try:
                # initialize device data #
                dev = key[key.rfind('/')+1:]
                readSize = readTime = writeSize = writeTime = '?'

                # get real device node #
                if ':' in dev:
                    major, minor = dev.split(':')
                    for name, mp in self.diskInfo['prev'].items():
                        if mp['major'] == major and mp['minor'] == minor:
                            dev = name
                elif not dev in self.diskInfo['prev'] and \
                    not dev in self.diskInfo['next']:
                    for k, v in self.diskInfo['next'].items():
                        if val['major'] == v['major'] and \
                            val['minor'] == v['minor']:
                            dev = k
                            break

                beforeInfo = self.diskInfo['prev'][dev]
                afterInfo = self.diskInfo['next'][dev]

                read = readSize = \
                    (long(afterInfo['sectorRead']) - \
                        long(beforeInfo['sectorRead'])) << 9
                readSize = UtilMgr.convSize2Unit(readSize)

                write = writeSize = \
                    (long(afterInfo['sectorWrite']) - \
                        long(beforeInfo['sectorWrite'])) << 9
                writeSize = UtilMgr.convSize2Unit(writeSize)

                totalInfo['read'] += read
                totalInfo['write'] += write
            except:
                pass

            # get device stat #
            try:
                major = minor = total = free = use = avail = '?'

                fstat = os.lstat(val['path'])
                major = os.major(fstat.st_dev)
                minor = os.minor(fstat.st_dev)

                stat = os.statvfs(val['path'])

                total = stat.f_bsize * stat.f_blocks
                free = stat.f_bsize * stat.f_bavail
                avail = stat.f_favail
                use = '%d%%' % long((total - free) / float(total) * 100)

                try:
                    totalInfo['total'] += total
                    totalInfo['free'] += free
                    totalInfo['favail'] += avail
                except:
                    pass

                total = UtilMgr.convSize2Unit(total)
                free = UtilMgr.convSize2Unit(free)
                avail = UtilMgr.convSize2Unit(avail)
            except:
                pass

            # get partition range #
            try:
                devid = '%s:%s' % (major, minor)
                prange = '[%s-%s]' % \
                    (self.partitionInfo[devid]['start'], \
                    self.partitionInfo[devid]['end'])
            except:
                prange = '[?]'

            # update device path with partition range #
            try:
                key = '%s (%s) %s' % \
                    (key, ','.join(self.devInfo['block'][major]), prange)
            except:
                pass

            # print device info #
            SysMgr.infoBufferPrint("{0:<16}".format(key))

            # build block device info string #
            try:
                diskInfo = \
                    ("{0:<16} {1:>7} {2:>8} {3:>8} {4:>8} "
                    "{5:>8} {6:>6} {7:>7} {8:>8} ").\
                    format(' ', '%s:%s' % (major, minor), readSize, \
                    writeSize, total, free, use, avail, val['fs'])
            except:
                continue

            # print storage info #
            try:
                title = diskInfo
                splitLen = SysMgr.lineLength - len(diskInfo) - 1

                if len(val['option']) > 0:
                    mountList = '%s <%s>' % (val['path'], val['option'])
                else:
                    mountList = val['path']

                mountList = \
                    [mountList[i:i+splitLen] for i in \
                    range(0, len(mountList), splitLen)]
                for string in mountList:
                    SysMgr.infoBufferPrint(\
                        '{0:85} {1:<1}'.format(title, string))
                    title = ' '
            except:
                pass

            try:
                if SysMgr.jsonOutputEnable:
                    jsonData[key] = {
                        'major': major,
                        'minor': minor,
                        'read': readSize,
                        'write': writeSize,
                        'total': total,
                        'free': free,
                        'use': use,
                        'avail': avail,
                        'fs': val['fs'],
                        'mount': '%s %s' % (val['path'], val['option']),
                    }
            except:
                pass

        # print total I/O size #
        if outputCnt == 0:
            SysMgr.infoBufferPrint('\tN/A')
        else:
            try:
                try:
                    usage = long((totalInfo['total'] - totalInfo['free']) / \
                        float(totalInfo['total']) * 100)
                except:
                    usage = long(0)

                totalInfo['total'] = \
                    UtilMgr.convSize2Unit(totalInfo['total'])
                totalInfo['free'] = \
                    UtilMgr.convSize2Unit(totalInfo['free'])
                totalInfo['favail'] = \
                    UtilMgr.convSize2Unit(totalInfo['favail'])
                totalInfo['read'] = \
                    UtilMgr.convSize2Unit(totalInfo['read'])
                totalInfo['write'] = \
                    UtilMgr.convSize2Unit(totalInfo['write'])
                totalInfo['use'] = '%d%%' % usage
            except:
                totalInfo['use'] = '?%'

            SysMgr.infoBufferPrint((\
                "{0:^16}\n{1:^24} {2:>8} {3:>8} {4:>8} "
                "{5:>8} {6:>6} {7:>7} {8:>8} {9:<20}").\
                format(oneLine, 'TOTAL', totalInfo['read'], \
                totalInfo['write'], totalInfo['total'], totalInfo['free'], \
                totalInfo['use'], totalInfo['favail'], ' ', ' '))

        SysMgr.infoBufferPrint("%s" % twoLine)



    def printMemInfo(self):
        if len(self.memData) != 2:
            return

        # parse data #
        time = 'prev'
        self.memInfo[time] = dict()
        for l in self.memData[time]:
            m = re.match(r'(?P<type>\S+):\s+(?P<size>[0-9]+)', l)
            if m:
                d = m.groupdict()
                self.memInfo[time][d['type']] = d['size']

        time = 'next'
        self.memInfo[time] = dict()
        for l in self.memData[time]:
            m = re.match(r'(?P<type>\S+):\s+(?P<size>[0-9]+)', l)
            if m:
                d = m.groupdict()
                self.memInfo[time][d['type']] = d['size']

        before = self.memInfo['prev']
        after = self.memInfo['next']

        # check items for compatibility #
        try:
            before['Shmem']
        except:
            before['Shmem'] = '0'
            after['Shmem'] = '0'

        try:
            before['SReclaimable']
        except:
            before['SReclaimable'] = '0'
            after['SReclaimable'] = '0'

        try:
            before['Sunreclaim']
        except:
            before['Sunreclaim'] = '0'
            after['Sunreclaim'] = '0'

        try:
            before['Mlocked']
        except:
            before['Mlocked'] = '0'
            after['Mlocked'] = '0'

        # define convert function #
        convertFunc = UtilMgr.convSize2Unit

        # print memory info #
        SysMgr.infoBufferPrint('\n[System Memory Info]')
        SysMgr.infoBufferPrint(twoLine)
        SysMgr.infoBufferPrint((\
            "[%6s] %10s %10s %10s %10s %10s %10s %10s %10s "
            "%10s %10s %10s %10s %10s") % \
            ("DESC ", "Memory", "Swap", "Buffer", "Cache", "Shared", \
            "Mapped", "Active", "Inactive", "PageTables", "Slab", \
            "SlabRclm", "SlabUnRclm", "Mlocked"))
        SysMgr.infoBufferPrint(twoLine)

        SysMgr.infoBufferPrint("[ TOTAL] %10s %10s" % \
            (convertFunc(long(before['MemTotal']) << 10), \
            convertFunc(long(before['SwapTotal']) << 10)))

        SysMgr.infoBufferPrint("[ FREE ] %10s %10s" % \
            (convertFunc(long(before['MemFree']) << 10), \
            convertFunc(long(before['SwapFree']) << 10)))
        if 'MemAvailable' in before:
            SysMgr.infoBufferPrint("[ AVAIL] %10s %10s" % \
                (convertFunc(long(before['MemAvailable']) << 10), \
                convertFunc(long(before['SwapFree']) << 10)))
        SysMgr.infoBufferPrint(oneLine)

        if 'MemAvailable' in before:
            memBeforeUsage = \
                long(before['MemTotal']) - long(before['MemAvailable'])
        else:
            memBeforeUsage = \
                long(before['MemTotal']) - long(before['MemFree'])

        swapBeforeUsage = \
            long(before['SwapTotal']) - long(before['SwapFree'])
        if 'MemAvailable' in before:
            memAfterUsage = \
                long(after['MemTotal']) - long(after['MemAvailable'])
        else:
            memAfterUsage = \
                long(after['MemTotal']) - long(after['MemFree'])

        swapAfterUsage = \
            long(after['SwapTotal']) - long(after['SwapFree'])

        SysMgr.infoBufferPrint((\
            "[ FIRST] %10s %10s %10s %10s %10s %10s %10s "
            "%10s %10s %10s %10s %10s %10s") % \
                (convertFunc(memBeforeUsage << 10), \
                convertFunc(swapBeforeUsage << 10), \
                convertFunc(long(before['Buffers']) << 10),\
                convertFunc(long(before['Cached']) << 10), \
                convertFunc(long(before['Shmem']) << 10), \
                convertFunc(long(before['Mapped']) << 10), \
                convertFunc(long(before['Active']) << 10), \
                convertFunc(long(before['Inactive']) << 10), \
                convertFunc(long(before['PageTables']) << 10), \
                convertFunc(long(before['Slab']) << 10), \
                convertFunc(long(before['SReclaimable']) << 10), \
                convertFunc(long(before['SUnreclaim']) << 10), \
                convertFunc(long(before['Mlocked']) << 10)))

        SysMgr.infoBufferPrint((\
            "[ LAST ] %10s %10s %10s %10s %10s %10s %10s "
            "%10s %10s %10s %10s %10s %10s") % \
                (convertFunc(memAfterUsage << 10), \
                convertFunc(swapAfterUsage << 10), \
                convertFunc(long(after['Buffers']) << 10), \
                convertFunc(long(after['Cached']) << 10), \
                convertFunc(long(after['Shmem']) << 10), \
                convertFunc(long(after['Mapped']) << 10), \
                convertFunc(long(after['Active']) << 10), \
                convertFunc(long(after['Inactive']) << 10), \
                convertFunc(long(after['PageTables']) << 10), \
                convertFunc(long(after['Slab']) << 10), \
                convertFunc(long(after['SReclaimable']) << 10), \
                convertFunc(long(after['SUnreclaim']) << 10), \
                convertFunc(long(after['Mlocked']) << 10)))

        SysMgr.infoBufferPrint(oneLine)

        SysMgr.infoBufferPrint((\
            "[ DIFF ] %10s %10s %10s %10s %10s %10s %10s "
            "%10s %10s %10s %10s %10s %10s") % \
                (convertFunc((memAfterUsage - memBeforeUsage ) << 10), \
                convertFunc((swapAfterUsage - swapBeforeUsage) << 10), \
                convertFunc((long(after['Buffers']) - \
                    long(before['Buffers'])) << 10), \
                convertFunc((long(after['Cached']) - \
                    long(before['Cached'])) << 10), \
                convertFunc((long(after['Shmem']) - \
                    long(before['Shmem'])) << 10), \
                convertFunc((long(after['Mapped']) - \
                    long(before['Mapped'])) << 10), \
                convertFunc((long(after['Active']) - \
                    long(before['Active'])) << 10), \
                convertFunc((long(after['Inactive']) - \
                    long(before['Inactive'])) << 10), \
                convertFunc((long(after['PageTables']) - \
                    long(before['PageTables'])) << 10), \
                convertFunc((long(after['Slab']) - \
                    long(before['Slab'])) << 10), \
                convertFunc((long(after['SReclaimable']) - \
                    long(before['SReclaimable'])) << 10), \
                convertFunc((long(after['SUnreclaim']) - \
                    long(before['SUnreclaim'])) << 10), \
                convertFunc((long(after['Mlocked']) - \
                    long(before['Mlocked'])) << 10)))

        SysMgr.infoBufferPrint(twoLine)

        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('general', dict())
            SysMgr.jsonData['general']['mem'] = {
                'memTotal': convertFunc(long(after['MemTotal']) << 10),
                'memFree': convertFunc(long(after['MemFree']) << 10),
                'swapTotal': convertFunc(long(after['SwapTotal']) << 10),
                'swapFree': convertFunc(long(after['SwapFree']) << 10),
                'buffer': convertFunc(long(after['Buffers']) << 10),
                'cache': convertFunc(long(after['Cached']) << 10),
                'shmem': convertFunc(long(after['Shmem']) << 10),
                'mapped': convertFunc(long(after['Mapped']) << 10),
                'active': convertFunc(long(after['Active']) << 10),
                'inactive': convertFunc(long(after['Inactive']) << 10),
                'pagetable': convertFunc(long(after['PageTables']) << 10),
                'slab': convertFunc(long(after['Slab']) << 10),
                'sreclaimable': \
                    convertFunc(long(after['SReclaimable']) << 10),
                'sunreclaimable': \
                    convertFunc(long(after['SUnreclaim']) << 10),
                'mlock': convertFunc(long(after['Mlocked']) << 10),
            }

            if 'MemAvailable' in after:
                SysMgr.jsonData['general']['mem']['memAvailable'] = \
                    convertFunc(long(after['MemAvailable']) << 10)





class DbusAnalyzer(object):
    """ Analyzer for D-Bus """

    errObj = None
    dbusErrObj = None
    sentData = {}
    recvData = {}
    prevData = {}
    msgSentTable = {}
    msgRecvTable = {}
    dbgObj = None

    G_IO_ERROR_TYPE = [
        'G_IO_ERROR_FAILED',
        'G_IO_ERROR_NOT_FOUND',
        'G_IO_ERROR_EXISTS',
        'G_IO_ERROR_IS_DIRECTORY',
        'G_IO_ERROR_NOT_DIRECTORY',
        'G_IO_ERROR_NOT_EMPTY',
        'G_IO_ERROR_NOT_REGULAR_FILE',
        'G_IO_ERROR_NOT_SYMBOLIC_LINK',
        'G_IO_ERROR_NOT_MOUNTABLE_FILE',
        'G_IO_ERROR_FILENAME_TOO_LONG',
        'G_IO_ERROR_INVALID_FILENAME',
        'G_IO_ERROR_TOO_MANY_LINKS',
        'G_IO_ERROR_NO_SPACE',
        'G_IO_ERROR_INVALID_ARGUMENT',
        'G_IO_ERROR_PERMISSION_DENIED',
        'G_IO_ERROR_NOT_SUPPORTED',
        'G_IO_ERROR_NOT_MOUNTED',
        'G_IO_ERROR_ALREADY_MOUNTED',
        'G_IO_ERROR_CLOSED',
        'G_IO_ERROR_CANCELLED',
        'G_IO_ERROR_PENDING',
        'G_IO_ERROR_READ_ONLY',
        'G_IO_ERROR_CANT_CREATE_BACKUP',
        'G_IO_ERROR_WRONG_ETAG',
        'G_IO_ERROR_TIMED_OUT',
        'G_IO_ERROR_WOULD_RECURSE',
        'G_IO_ERROR_BUSY',
        'G_IO_ERROR_WOULD_BLOCK',
        'G_IO_ERROR_HOST_NOT_FOUND',
        'G_IO_ERROR_WOULD_MERGE',
        'G_IO_ERROR_FAILED_HANDLED',
        'G_IO_ERROR_TOO_MANY_OPEN_FILES',
        'G_IO_ERROR_NOT_INITIALIZED',
        'G_IO_ERROR_ADDRESS_IN_USE',
        'G_IO_ERROR_PARTIAL_INPUT',
        'G_IO_ERROR_INVALID_DATA',
        'G_IO_ERROR_DBUS_ERROR',
        'G_IO_ERROR_HOST_UNREACHABLE',
        'G_IO_ERROR_NETWORK_UNREACHABLE',
        'G_IO_ERROR_CONNECTION_REFUSED',
        'G_IO_ERROR_PROXY_FAILED',
        'G_IO_ERROR_PROXY_AUTH_FAILED',
        'G_IO_ERROR_PROXY_NEED_AUTH',
        'G_IO_ERROR_PROXY_NOT_ALLOWED',
        'G_IO_ERROR_BROKEN_PIPE',
        'G_IO_ERROR_CONNECTION_CLOSED',
        'G_IO_ERROR_NOT_CONNECTED',
        'G_IO_ERROR_MESSAGE_TOO_LARGE',
    ]

    DBusBusType = {
        "DBUS_BUS_SESSION": 0,
        "DBUS_BUS_SYSTEM": 1,
        "DBUS_BUS_STARTER": 2,
    }

    GDBusMessageType = [
        "INVALID",
        "METHOD", # METHOD_CALL
        "RETURN", # METHOD_RETURN
        "ERROR",
        "SIGNAL"
    ]

    taskInfo = {
        'min': long(0),
        'max': long(0),
        'err': long(0),
        'cnt': long(0),
        'size': long(0),
        'total': long(0)
    }

    @staticmethod
    def getErrInfo():
        if DbusAnalyzer.dbusErrObj:
            errObj = DbusAnalyzer.dbusErrObj
            return "%s: %s" % (errObj.name, errObj.message)
        else:
            return "N/A"



    @staticmethod
    def getErrP():
        if DbusAnalyzer.dbusErrObj:
            dbusErrP = byref(DbusAnalyzer.dbusErrObj)
            SysMgr.libdbusObj.dbus_error_init(dbusErrP)
            return dbusErrP

        # define error object #
        class DBusError(Structure):
            _fields_ = (
                ("name", c_char_p),
                ("message", c_char_p),
                ("padding2", c_void_p * 2),
            )

        DbusAnalyzer.dbusErrObj = dbusErr = DBusError()
        dbusErrP = byref(dbusErr)
        SysMgr.libdbusObj.dbus_error_init(dbusErrP)
        return dbusErrP



    @staticmethod
    def getBus(bus, tid=None, addr=None):
        dbusObj = SysMgr.libdbusObj
        name = "guider.method.caller".encode()

        if bus == 'system':
            bustype = DbusAnalyzer.DBusBusType['DBUS_BUS_SYSTEM']
        elif bus == 'session' or bus == 'user':
            bustype = DbusAnalyzer.DBusBusType['DBUS_BUS_SESSION']
        else:
            SysMgr.printWarn("Fail to recognize %s bus" % bus)
            return None

        # get connection #
        conn = dbusObj.dbus_bus_get(bustype, DbusAnalyzer.getErrP())
        if not conn:
            # get connection by session address #
            ADDRENV = 'DBUS_SESSION_BUS_ADDRESS'
            if ADDRENV in os.environ:
                address = os.environ[ADDRENV]
                address = c_char_p(address.encode())
                conn = dbusObj.dbus_connection_open(\
                    address, DbusAnalyzer.getErrP())
            else:
                envList = SysMgr.getEnv(tid)
                for env in envList:
                    if env.startswith(ADDRENV):
                        address = c_char_p(env.lstrip(ADDRENV)[1:].encode())
                        conn = dbusObj.dbus_connection_open(\
                            address, DbusAnalyzer.getErrP())
                        break

            # check error #
            if conn:
                ret = dbusObj.dbus_bus_set_unique_name(\
                    c_void_p(conn), c_char_p(name))
                ret = dbusObj.dbus_bus_get_unique_name(c_void_p(conn))
                ret = dbusObj.dbus_bus_register(\
                    c_void_p(conn), DbusAnalyzer.getErrP())
                if not ret:
                    SysMgr.printWarn(\
                        "Fail to register D-Bus %s bus because %s" % \
                            (bus, DbusAnalyzer.getErrInfo()))
                    return None
            else:
                SysMgr.printWarn(\
                    "Fail to get D-Bus %s bus because %s" % \
                        (bus, DbusAnalyzer.getErrInfo()))
                return None

        '''
        # request name #
        DBUS_NAME_FLAG_ALLOW_REPLACEMENT = c_uint(0x1)
        DBUS_NAME_FLAG_REPLACE_EXISTING = c_uint(0x2)
        ret = dbusObj.dbus_bus_request_name(\
            conn, c_char_p(name), DBUS_NAME_FLAG_REPLACE_EXISTING, \
            DbusAnalyzer.getErrP())
        if ret < 0:
            SysMgr.printWarn(\
                "Fail to request D-Bus bus name to %s because %s" % \
                    (name.decode(), DbusAnalyzer.getErrInfo()))
        '''

        return conn



    @staticmethod
    def getStats(bus, request, des=None):
        if not bus:
            return

        dbusObj = SysMgr.libdbusObj

        conn = DbusAnalyzer.getBus(bus)
        if not conn:
            return

        # prepare method args #
        path = '/'
        if not des:
            des = 'org.freedesktop.DBus'
        if not des.startswith(':'):
            path += des.replace('.', '/')
        if dbusObj.dbus_validate_path(\
            c_char_p(path.encode()), DbusAnalyzer.getErrP()) == 0:
            SysMgr.printWarn(\
                "Fail to create a D-Bus message because %s" % \
                    DbusAnalyzer.getErrInfo())
            return

        if request == 'introspect':
            iface = 'org.freedesktop.DBus.Introspectable'
            method = 'Introspect'
            timeout = c_int(100)
        elif request == 'allmatch':
            iface = 'org.freedesktop.DBus.Debug.Stats'
            method = 'GetAllMatchRules'
            timeout = c_int(-1)
        else:
            SysMgr.printErr('Unknown request %s' % request)
            sys.exit(0)

        # create a message for method call #
        msg = dbusObj.dbus_message_new_method_call(\
            des.encode(), path.encode(), \
            iface.encode(), method.encode())
        if not msg:
            dbusObj.dbus_connection_unref(conn)
            SysMgr.printWarn("Fail to create a D-Bus message")
            return

        # call a remote method #
        reply = dbusObj.dbus_connection_send_with_reply_and_block(\
            conn, msg, timeout, DbusAnalyzer.getErrP())
        if not reply:
            dbusObj.dbus_message_unref(msg)
            dbusObj.dbus_connection_unref(conn)
            SysMgr.printWarn(\
                "Fail to call a D-Bus remote method because %s" % \
                    DbusAnalyzer.getErrInfo())
            return

        # prepare args #
        array = c_char('a'.encode())
        DBUS_TYPE_ARRAY = cast(byref(array), POINTER(c_int)).contents
        dicte = c_char('e'.encode())
        DBUS_TYPE_DICT_ENTRY = cast(byref(dicte), POINTER(c_int)).contents
        char = c_char('s'.encode())
        DBUS_TYPE_STRING = cast(byref(char), POINTER(c_int)).contents
        null = c_char('\0'.encode())
        DBUS_TYPE_INVALID = cast(byref(null), POINTER(c_int)).contents

        # introspect #
        if request == 'introspect':
            strRes = c_char_p(''.encode())
            res = dbusObj.dbus_message_get_args(\
                reply, DbusAnalyzer.getErrP(), DBUS_TYPE_STRING, \
                byref(strRes), DBUS_TYPE_INVALID)
            if not res:
                dbusObj.dbus_message_unref(msg)
                dbusObj.dbus_message_unref(reply)
                dbusObj.dbus_connection_unref(conn)
                SysMgr.printWarn(\
                    "Fail to parse D-Bus message args because %s" % \
                        DbusAnalyzer.getErrInfo())
                return

	    # parse args #
            strRes = c_char_p(''.encode())
            res = dbusObj.dbus_message_get_args(\
                    reply, DbusAnalyzer.getErrP(), DBUS_TYPE_STRING, \
                    byref(strRes), DBUS_TYPE_INVALID)
            if not res:
                SysMgr.printWarn(\
                    "Fail to parse D-Bus message args because %s" % \
                        DbusAnalyzer.getErrInfo())
                return

            # convert value #
            buf = str(strRes.value.decode())

            # clean up #
            dbusObj.dbus_message_unref(msg)
            dbusObj.dbus_message_unref(reply)
            dbusObj.dbus_connection_unref(conn)

            return buf

        # allmatch #
        perProcList = {}
        perSigList = {}

        class DBusMessageIter(Structure):
            _fields_ = (
                ("dummy1", c_void_p),
                ("dummy2", c_void_p),
                ("dummy3", c_uint32),
                ("dummy4", c_int),
                ("dummy5", c_int),
                ("dummy6", c_int),
                ("dummy7", c_int),
                ("dummy8", c_int),
                ("dummy9", c_int),
                ("dummy10", c_int),
                ("dummy11", c_int),
                ("pad1", c_int),
                ("pad2", c_void_p),
                ("pad3", c_void_p),
            )

        # initialize message iterator #
        rootIter = DBusMessageIter()
        rootIterP = byref(rootIter)
        arrayIter = DBusMessageIter()
        arrayIterP = byref(arrayIter)
        dictIter = DBusMessageIter()
        dictIterP = byref(dictIter)
        arraySigIter = DBusMessageIter()
        arraySigIterP = byref(arraySigIter)

        procInfo = c_char_p(''.encode())
        sigInfo = c_char_p(''.encode())

        # initialize iteration #
        ret = dbusObj.dbus_message_iter_init(reply, rootIterP)
        if not ret:
            SysMgr.printWarn("Fail to initialize D-Bus message iteration")
            dbusObj.dbus_message_unref(msg)
            dbusObj.dbus_message_unref(reply)
            dbusObj.dbus_connection_unref(conn)
            return

        ret = dbusObj.dbus_message_iter_get_arg_type(rootIterP)
        if ret != DBUS_TYPE_ARRAY.value:
            SysMgr.printWarn("Fail to parse array in D-Bus message")
            dbusObj.dbus_message_unref(msg)
            dbusObj.dbus_message_unref(reply)
            dbusObj.dbus_connection_unref(conn)
            return

        # get item count #
        cnt = dbusObj.dbus_message_iter_get_element_count(rootIterP)
        dbusObj.dbus_message_iter_recurse(rootIterP, arrayIterP)

        SysMgr.printStat('start collecting signals for %s bus' % bus)

        # array item loop #
        while 1:
            ret = dbusObj.dbus_message_iter_get_arg_type(arrayIterP)
            if ret != DBUS_TYPE_DICT_ENTRY.value:
                SysMgr.printWarn("Fail to parse dict in D-Bus message")
                dbusObj.dbus_message_unref(msg)
                dbusObj.dbus_message_unref(reply)
                dbusObj.dbus_connection_unref(conn)
                return

            dbusObj.dbus_message_iter_recurse(arrayIterP, dictIterP)

            # dictionary item loop #
            while 1:
                ret = dbusObj.dbus_message_iter_get_arg_type(dictIterP)
                if ret != DBUS_TYPE_STRING.value:
                    SysMgr.printWarn(\
                        "Fail to parse 1st string in D-Bus message")
                    dbusObj.dbus_message_unref(msg)
                    dbusObj.dbus_message_unref(reply)
                    dbusObj.dbus_connection_unref(conn)
                    return

                # get process id #
                dbusObj.dbus_message_iter_get_basic(dictIterP, byref(procInfo))
                if not procInfo.value:
                    SysMgr.printWarn(\
                        "Fail to parse process info in D-Bus message")
                    dbusObj.dbus_message_unref(msg)
                    dbusObj.dbus_message_unref(reply)
                    dbusObj.dbus_connection_unref(conn)
                    return

                if not dbusObj.dbus_message_iter_next(dictIterP):
                    break

                ret = dbusObj.dbus_message_iter_get_arg_type(dictIterP)
                if ret != DBUS_TYPE_ARRAY.value:
                    SysMgr.printWarn("Fail to parse array in D-Bus message")
                    dbusObj.dbus_message_unref(msg)
                    dbusObj.dbus_message_unref(reply)
                    dbusObj.dbus_connection_unref(conn)
                    return

                # check array size #
                if dbusObj.dbus_message_iter_get_element_count(dictIterP) == 0:
                    if not dbusObj.dbus_message_iter_next(dictIterP):
                        break
                    continue

                # allocate a new task dict #
                procId = procInfo.value.decode()
                perProcList.setdefault(procId, dict())
                procSigList = perProcList[procId]

                # parse signal array #
                dbusObj.dbus_message_iter_recurse(dictIterP, arraySigIterP)

                while 1:
                    ret = dbusObj.dbus_message_iter_get_arg_type(arraySigIterP)
                    if ret != DBUS_TYPE_STRING.value:
                        SysMgr.printWarn(\
                            "Fail to parse 2nd string in D-Bus message")
                        dbusObj.dbus_message_unref(msg)
                        dbusObj.dbus_message_unref(reply)
                        dbusObj.dbus_connection_unref(conn)
                        return

                    # get signal info #
                    dbusObj.dbus_message_iter_get_basic(\
                        arraySigIterP, byref(sigInfo))
                    if not sigInfo.value:
                        SysMgr.printWarn(\
                            "Fail to parse signal info in D-Bus message")
                        dbusObj.dbus_message_unref(msg)
                        dbusObj.dbus_message_unref(reply)
                        dbusObj.dbus_connection_unref(conn)
                        return

                    # parse items #
                    sinfo = {}
                    for item in sigInfo.value.decode().split(','):
                        slist = item.strip('"').split('=')
                        sinfo[slist[0]] = slist[1].strip("'")

                    # save items to list #
                    if 'interface' in sinfo:
                        iface = sinfo['interface']

                        if 'sender' in sinfo:
                            sender = sinfo['sender']
                        else:
                            sender = iface

                        if 'member' in sinfo:
                            member = '.%s' % sinfo['member']
                        else:
                            member= ''

                        addr = '%s%s' % (iface, member)

                        # save perProc items #
                        procSigList.setdefault(sender, dict())
                        procSigList[sender].setdefault(addr, dict())
                        if 'arg0' in sinfo:
                            argList = [ '%s' % sinfo[i] for i in sorted(list(sinfo.keys())) if i.startswith('arg') ]
                            procSigList[sender][addr].setdefault(', '.join(argList))

                        # save perSignal items #
                        perSigList.setdefault(sender, dict())
                        sigProcList = perSigList[sender]
                        sigProcList.setdefault(addr, dict())
                        sigProcList[addr].setdefault(procId)

                    if not dbusObj.dbus_message_iter_next(arraySigIterP):
                        break

                if not dbusObj.dbus_message_iter_next(dictIterP):
                    break

            if not dbusObj.dbus_message_iter_next(arrayIterP):
                break

        # clean up #
        dbusObj.dbus_message_unref(msg)
        dbusObj.dbus_message_unref(reply)
        dbusObj.dbus_connection_unref(conn)

        return perProcList, perSigList



    @staticmethod
    def getServiceProc(bus, service):
        if not bus or not service:
            return

        dbusObj = SysMgr.libdbusObj

        conn = DbusAnalyzer.getBus(bus)
        if not conn:
            return

        # create a message for method call #
        des = 'org.freedesktop.DBus'
        path = '/'
        iface = des
        method = 'GetConnectionUnixProcessID'
        msg = dbusObj.dbus_message_new_method_call(\
            des.encode(), path.encode(), \
            iface.encode(), method.encode())
        if not msg:
            dbusObj.dbus_connection_unref(conn)
            SysMgr.printWarn("Fail to create a D-Bus message")
            return

        # prepare args #
        char = c_char('s'.encode())
        DBUS_TYPE_STRING = cast(byref(char), POINTER(c_int)).contents
        null = c_char('\0'.encode())
        DBUS_TYPE_INVALID = cast(byref(null), POINTER(c_int)).contents

        # append args #
        item = c_char_p(service.encode())
        res = dbusObj.dbus_message_append_args(\
            msg, DBUS_TYPE_STRING, byref(item), DBUS_TYPE_INVALID)
        if not res:
            dbusObj.dbus_message_unref(msg)
            dbusObj.dbus_connection_unref(conn)
            SysMgr.printWarn("Fail to append D-Bus message args")
            return

        # call a remote method #
        reply = dbusObj.dbus_connection_send_with_reply_and_block(\
            conn, msg, -1, DbusAnalyzer.getErrP())
        if not reply:
            dbusObj.dbus_message_unref(msg)
            dbusObj.dbus_connection_unref(conn)
            SysMgr.printWarn(\
                "Fail to call a D-Bus remote method because %s" % \
                    DbusAnalyzer.getErrInfo())
            return

        # parse args #
        pid = c_uint32(0)
        uint32 = c_char('u'.encode())
        DBUS_TYPE_UINT32 = cast(byref(uint32), POINTER(c_int)).contents
        res = dbusObj.dbus_message_get_args(\
            reply, DbusAnalyzer.getErrP(), DBUS_TYPE_UINT32, \
            byref(pid), DBUS_TYPE_INVALID)
        if not res:
            dbusObj.dbus_message_unref(msg)
            dbusObj.dbus_message_unref(reply)
            dbusObj.dbus_connection_unref(conn)
            SysMgr.printWarn(\
                "Fail to parse D-Bus message args because %s" % \
                    DbusAnalyzer.getErrInfo())
            return

        # clean up #
        dbusObj.dbus_message_unref(msg)
        dbusObj.dbus_message_unref(reply)
        dbusObj.dbus_connection_unref(conn)

        # get comm #
        comm = SysMgr.getComm(pid.value)
        if not comm:
            comm = '??'

        try:
            return '%s(%s)' % (comm, pid.value)
        except SystemExit:
            sys.exit(0)
        except:
            return



    @staticmethod
    def getBusService(bus, tid=None, addr=None):
        if not bus:
            return

        dbusObj = SysMgr.libdbusObj

        conn = DbusAnalyzer.getBus(bus, tid, addr)
        if not conn:
            return

        # create a message for method call #
        des = 'org.freedesktop.DBus'
        path = '/'
        iface = des
        method = 'ListNames'
        msg = dbusObj.dbus_message_new_method_call(\
            des.encode(), path.encode(), \
            iface.encode(), method.encode())
        if not msg:
            dbusObj.dbus_connection_unref(conn)
            SysMgr.printWarn("Fail to create a D-Bus message")
            return

        # call a remote method #
        reply = dbusObj.dbus_connection_send_with_reply_and_block(\
            conn, msg, -1, DbusAnalyzer.getErrP())
        if not reply:
            dbusObj.dbus_message_unref(msg)
            dbusObj.dbus_connection_unref(conn)
            SysMgr.printWarn(\
                "Fail to call a D-Bus remote method because %s" % \
                    DbusAnalyzer.getErrInfo())
            return

        # prepare args #
        array = c_char('a'.encode())
        DBUS_TYPE_ARRAY = cast(byref(array), POINTER(c_int)).contents
        char = c_char('s'.encode())
        DBUS_TYPE_STRING = cast(byref(char), POINTER(c_int)).contents
        null = c_char('\0'.encode())
        DBUS_TYPE_INVALID = cast(byref(null), POINTER(c_int)).contents

        # parse args #
        cntRes = c_int(0)
        arrayRes = (POINTER(c_char_p))()
        res = dbusObj.dbus_message_get_args(\
            reply, DbusAnalyzer.getErrP(), DBUS_TYPE_ARRAY, \
            DBUS_TYPE_STRING, byref(arrayRes), \
            byref(cntRes), DBUS_TYPE_INVALID)
        if not res:
            dbusObj.dbus_message_unref(msg)
            dbusObj.dbus_message_unref(reply)
            dbusObj.dbus_connection_unref(conn)
            SysMgr.printWarn(\
                "Fail to parse D-Bus message args because %s" % \
                    DbusAnalyzer.getErrInfo())
            return

        slist = []
        for idx in range(0, cntRes.value):
            slist.append(str(arrayRes[idx].decode()))

        dbusObj.dbus_free_string_array(arrayRes)

        # clean up #
        dbusObj.dbus_message_unref(msg)
        dbusObj.dbus_message_unref(reply)
        dbusObj.dbus_connection_unref(conn)

        return slist



    @staticmethod
    def prepareDbusMethods():
        # get ctypes object #
        SysMgr.importPkgItems('ctypes')

        # try to load libraries #
        try:
            # load libgio library #
            if not SysMgr.libgioObj:
                SysMgr.libgioObj = SysMgr.loadLib(SysMgr.libgioPath)

            # load libgobj library #
            if not SysMgr.libgObj:
                SysMgr.libgObj = SysMgr.loadLib(SysMgr.libgobjPath)

            # load standard libdbus library #
            if not SysMgr.libdbusObj:
                SysMgr.libdbusObj = SysMgr.loadLib(SysMgr.libdbusPath)
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Fail to load library to analyze D-Bus packets", True)
            sys.exit(0)

        # define error object #
        class GError(Structure):
            _fields_ = (
                ("domain", c_uint32),
                ("code", c_int),
                ("message", c_char_p),
            )
        DbusAnalyzer.errObj = GError

        # define gobject methods #
        gObj = SysMgr.libgObj

        gObj.g_object_unref.argtypes = [c_void_p]

        # define gio methods #
        gioObj = SysMgr.libgioObj

        gioObj.g_dbus_message_new_from_blob.argtypes = \
            [c_char_p, c_ulong, c_ulong, c_void_p]
        gioObj.g_dbus_message_new_from_blob.restype = c_ulong

        gioObj.g_dbus_message_bytes_needed.argtypes = \
            [c_char_p, c_ulong, c_void_p]
        gioObj.g_dbus_message_bytes_needed.restype = c_ulong

        gioObj.g_error_free.argtypes = [c_void_p]

        gioObj.g_dbus_message_get_message_type.argtypes = [c_ulong]
        gioObj.g_dbus_message_get_message_type.restype = c_ulong

        gioObj.g_dbus_message_get_arg0.argtypes = [c_ulong]
        gioObj.g_dbus_message_get_arg0.restype = c_char_p

        gioObj.g_dbus_message_get_sender.argtypes = [c_ulong]
        gioObj.g_dbus_message_get_sender.restype = c_char_p

        gioObj.g_dbus_message_get_destination.argtypes = [c_ulong]
        gioObj.g_dbus_message_get_destination.restype = c_char_p

        gioObj.g_dbus_message_get_path.argtypes = [c_ulong]
        gioObj.g_dbus_message_get_path.restype = c_char_p

        gioObj.g_dbus_message_get_signature.argtypes = [c_ulong]
        gioObj.g_dbus_message_get_signature.restype = c_char_p

        gioObj.g_dbus_message_get_interface.argtypes = [c_ulong]
        gioObj.g_dbus_message_get_interface.restype = c_char_p

        gioObj.g_dbus_message_get_member.argtypes = [c_ulong]
        gioObj.g_dbus_message_get_member.restype = c_char_p

        gioObj.g_dbus_message_get_error_name.argtypes = [c_ulong]
        gioObj.g_dbus_message_get_error_name.restype = c_char_p

        gioObj.g_dbus_message_get_serial.argtypes = [c_ulong]
        gioObj.g_dbus_message_get_serial.restype = c_ulong

        gioObj.g_dbus_message_print.argtypes = [c_ulong, c_ulong]
        gioObj.g_dbus_message_print.restype = c_char_p

        gioObj.g_dbus_message_get_reply_serial.argtypes = [c_ulong]
        gioObj.g_dbus_message_get_reply_serial.restype = c_ulong

        # define dbus methods #
        dbusObj = SysMgr.libdbusObj

        dbusObj.dbus_bus_get.argtypes = [c_uint, c_void_p]
        dbusObj.dbus_bus_get.restype = c_void_p

        dbusObj.dbus_connection_open.argtypes = [c_char_p, c_void_p]
        dbusObj.dbus_connection_open.restype = c_void_p

        dbusObj.dbus_bus_get_unique_name.argtypes = [c_void_p]
        dbusObj.dbus_bus_get_unique_name.restype = c_char_p

        dbusObj.dbus_bus_set_unique_name.argtypes = [c_void_p, c_char_p]
        dbusObj.dbus_bus_set_unique_name.restype = c_bool

        dbusObj.dbus_bus_register.argtypes = [c_void_p, c_void_p]
        dbusObj.dbus_bus_register.restype = c_bool

        dbusObj.dbus_parse_address.argtypes = \
            [c_void_p, c_void_p, POINTER(c_int), c_void_p]
        dbusObj.dbus_parse_address.restype = c_bool

        dbusObj.dbus_bus_request_name.argtypes = \
            [c_void_p, c_char_p, c_uint, c_void_p]
        dbusObj.dbus_bus_request_name.restype = c_int

        dbusObj.dbus_message_unref.argtypes = [c_void_p]
        dbusObj.dbus_message_unref.restype = None

        dbusObj.dbus_connection_unref.argtypes = [c_void_p]
        dbusObj.dbus_connection_unref.restype = None

        dbusObj.dbus_message_new_method_call.argtypes = \
            [c_char_p, c_char_p, c_char_p, c_char_p]
        dbusObj.dbus_message_new_method_call.restype = c_void_p

        dbusObj.dbus_connection_send_with_reply_and_block.argtypes = \
            [c_void_p, c_void_p, c_int, c_void_p]
        dbusObj.dbus_connection_send_with_reply_and_block.restype = c_void_p

        dbusObj.dbus_message_get_args.argtypes = \
            [c_void_p, c_void_p, c_int]
        dbusObj.dbus_message_get_args.restype = c_bool

        dbusObj.dbus_message_append_args.argtypes = [c_void_p, c_int]
        dbusObj.dbus_message_append_args.restype = c_bool

        dbusObj.dbus_message_demarshal.argtypes = \
            [c_char_p, c_int, c_void_p]
        dbusObj.dbus_message_demarshal.restype = c_ulong

        dbusObj.dbus_message_demarshal_bytes_needed.argtypes = \
            [c_char_p, c_int]
        dbusObj.dbus_message_demarshal_bytes_needed.restype = c_int

        dbusObj.dbus_message_get_interface.argtypes = [c_void_p]
        dbusObj.dbus_message_get_interface.restype = c_char_p

        dbusObj.dbus_message_get_type.argtypes = [c_void_p]
        dbusObj.dbus_message_get_type.restype = c_int



    @staticmethod
    def printSignalInfo(tid, perProc, perSig, procInfo):
        conv = UtilMgr.convNum

        totalSubscription = 0
        procId = '%s(%s)' % (SysMgr.getComm(tid), tid)

        # create a table for perProc signals #
        nrPerProcSignals = {}
        for cli, items in perProc.items():
            nrPerProcSignals.setdefault(\
                cli, dict({'nrStub': 0, 'nrSignal': 0}))

            for sender, iface in items.items():
                nrPerProcSignals[cli]['nrStub'] += 1
                nrPerProcSignals[cli]['nrSignal'] += len(iface)
                totalSubscription += len(iface)

        # print perProc signals #
        SysMgr.printPipe((\
            '\nD-Bus Signal Proxy Info [Target: %s] '
            '[nrProcess: %s] [nrSubscription: %s]\n%s') % \
                (procId, conv(len(perProc)), conv(totalSubscription), twoLine))
        SysMgr.printPipe(\
            "{0:^23} {1:<23} {2:^10} {3:>1}".format(\
                'Client', 'Server', 'Interface', 'Args'))
        SysMgr.printPipe(oneLine)
        for cli, stats in sorted(nrPerProcSignals.items(),\
            key=lambda e: e[1]['nrSignal'], reverse=True):
            if cli in procInfo:
                proc = procInfo[cli]
            else:
                proc = cli

            # print signal stat #
            mergedList = {}
            for sender, iface in perProc[cli].items():
                if sender in procInfo:
                    sender = procInfo[sender]
                else:
                    tokens = sender.split('.')
                    pos = len(tokens) - 1
                    while 1:
                        if pos == 0:
                            break

                        key = '.'.join(tokens[:pos])
                        if key in procInfo:
                            procInfo[sender] = procInfo[key]
                            sender = procInfo[key]
                            break

                        pos -= 1

                if sender in mergedList:
                    mergedList[sender].update(iface)
                else:
                    mergedList[sender] = dict(iface)

            # print process stat #
            SysMgr.printPipe(\
                "{0:>23} [nrStub: {1:1}, nrSignal: {2:1}]".format(\
                    proc, conv(len(mergedList)), conv(stats['nrSignal'])))

            # print signal stat #
            for sender, iface in sorted(mergedList.items(),\
                key=lambda e: len(e[1]), reverse=True):
                SysMgr.printPipe(\
                    "{0:>23} {1:<23} [nrSignal: {2:1}]".format(\
                        ' ', sender, conv(len(iface))))
                if not SysMgr.showAll:
                    continue

                for name, arg in sorted(iface.items()):
                    SysMgr.printPipe(\
                        "{0:>23} {1:<23} {2:<12}".format(\
                            ' ', ' ', name))
                    for key in sorted(list(arg.keys())):
                        SysMgr.printPipe(\
                            "{0:>23} {1:<23} {2:<10} ({3:<1})".format(\
                                ' ', ' ', ' ', key))
            SysMgr.printPipe(oneLine)
        if len(nrPerProcSignals) == 0:
            SysMgr.printPipe('\tNone\n%s' % oneLine)

        # create a table for perSignal processes #
        nrPerSigProcs = {}
        for sender, items in perSig.items():
            if sender in procInfo:
                proc = procInfo[sender]
            else:
                proc = sender

            nrPerSigProcs.setdefault(\
                proc, dict({'proxyList': dict(), 'nrSignal': 0, 'interface': dict()}))
            nrPerSigProcs[proc]['interface'].setdefault(sender, dict())
            nrPerSigProcs[proc]['interface'][sender].update(items)

            nrPerSigProcs[proc]['nrSignal'] += len(items)
            for iface, receiver in items.items():
                nrPerSigProcs[proc]['proxyList'].update(receiver)

        # print perSignal processes #
        SysMgr.printPipe((\
            '\nD-Bus Signal Stub Info [Target: %s] '
            '[nrProcess: %s] [nrSubscription: %s]\n%s') % \
                (procId, conv(len(perSig)), conv(totalSubscription), twoLine))
        SysMgr.printPipe(\
            "{0:^23} {1:^12} {2:<23}".format(\
                'Server', 'Interface', 'Client'))
        SysMgr.printPipe(oneLine)
        for serv, stats in sorted(nrPerSigProcs.items(),\
            key=lambda e: len(e[1]['proxyList']), reverse=True):
            # print stub process stat #
            SysMgr.printPipe(\
                "{0:>23} [nrProxy: {1:1}, nrSignal: {2:1}]".format(\
                    serv, conv(len(stats['proxyList'])), conv(stats['nrSignal'])))

            # print interface stat #
            for iface, receiver in sorted(stats['interface'].items(),\
                key=lambda e: len(e[1]), reverse=True):
                procList = {}
                for signame, procs in receiver.items():
                    procList.update(procs)

                SysMgr.printPipe(\
                    "{0:>23} {1:<12} [nrProxy: {2:1}] [nrSignal: {3:1}]".format(\
                        ' ', iface, conv(len(procList)), conv(len(receiver))))

                if not SysMgr.showAll:
                    continue

                for signame, procs in sorted(receiver.items(),\
                    key=lambda e: len(e[1]), reverse=True):
                    SysMgr.printPipe(\
                        "{0:>23} {1:<12} {2:<23} [nrProxy: {3:<1}]".format(\
                            ' ', ' ', signame, conv(len(procs))))
                    procs = [ procInfo[name] if name in procInfo else name for name in list(procs.keys()) ]
                    # print proxy process stat #
                    for name in sorted(procs):
                        if name in procInfo:
                            cproc = procInfo[name]
                        else:
                            cproc = name

                        SysMgr.printPipe(\
                            "{0:>23} {1:<12} {2:<12} {3:<1}".format(\
                                ' ', ' ', ' ', cproc))
            SysMgr.printPipe(oneLine)
        if len(nrPerSigProcs) == 0:
            SysMgr.printPipe('\tNone\n%s' % oneLine)





    @staticmethod
    def runDbusSnooper(mode='top'):
        def updateTaskInfo(dbusData, sentData, recvData):
            try:
                taskManager.saveSystemStat()
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "Fail to update system stat", True)

            convertNum = UtilMgr.convNum
            convertSize = UtilMgr.convSize2Unit

            for pid in taskList:
                try:
                    if pid not in dbusData:
                        continue

                    dbusList = []

                    # build D-Bus usage string #
                    dbusCnt = dbusData[pid]['totalCnt']
                    dbusList.append(\
                        '[TOTAL]: %s / [TYPE]: %s' % \
                            (convertNum(dbusCnt), \
                            convertNum(len(dbusData[pid])-1)))

                    for name, value in sorted(dbusData[pid].items(),\
                        key=lambda x:x[1]['cnt'] if x[0] != 'totalCnt' else 0,\
                        reverse=True):

                        if name == 'totalCnt' or value['cnt'] == 0:
                            continue

                        try:
                            per = long((value['cnt'] / float(dbusCnt)) * 100)
                        except SystemExit:
                            sys.exit(0)
                        except:
                            per = long(0)

                        # get time info #
                        if pid in sentData and \
                            name in sentData[pid]:
                            data = sentData[pid][name]
                        elif pid in recvData and \
                            name in recvData[pid]:
                            data = recvData[pid][name]
                        else:
                            continue

                        # get complete count and status #
                        cnt = data['cnt']
                        if data['time'] > 0:
                            wstat = '/WAIT'
                        else:
                            wstat = ''

                        # get complete call count #
                        if cnt > 0:
                            avr = data['total'] / cnt
                        else:
                            avr = long(0)

                        if data['err'] > 0:
                            errstr = ', Err: %s' % data['err']
                        else:
                            errstr = ''

                        if data['max'] > 0:
                            name = \
                                '%s {Min: %.3f, Avr: %.3f, Max: %.3f%s} %s' % \
                                (name, data['min'], avr, data['max'], \
                                    errstr, wstat)

                        count = convertNum(value['cnt'])
                        size = convertSize(data['size'])

                        dbusList.append(\
                            "{0:>4}({1:>6}/{2:>3}%) {3:1}".format(\
                                count, size, per, name))

                    # add D-Bus usage #
                    taskManager.procData[pid]['dbusList'] = dbusList
                    taskManager.procData[pid]['dbusCnt'] = dbusCnt
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printWarn(\
                        "Fail to update task info", True, reason=True)

        def printSummary(signum, frame):
            def checkRepeatCnt():
                if SysMgr.repeatCount > 0:
                    SysMgr.progressCnt += 1
                    if SysMgr.repeatCount <= SysMgr.progressCnt:
                        sys.exit(0)

            if SysMgr.isPrintDbusMode():
                checkRepeatCnt()
                return

            # disable alarm #
            signal.signal(signal.SIGALRM, signal.SIG_IGN)

            # check user input #
            SysMgr.waitUserInput(0.000001)

            # get summary list #
            if lock:
                lock.acquire()

            # initialize data #
            prevRecvData = DbusAnalyzer.recvData
            prevSentData = DbusAnalyzer.sentData
            DbusAnalyzer.sentData = {}
            DbusAnalyzer.recvData = {}
            DbusAnalyzer.msgSentTable = {}
            DbusAnalyzer.msgRecvTable = {}
            prevDbusData = ThreadAnalyzer.dbusData
            ThreadAnalyzer.dbusData = \
                {'totalCnt': long(0), 'totalErr': long(0)}

            if lock and lock.locked():
                try:
                    lock.release()
                except SystemExit:
                    sys.exit(0)
                except:
                    pass

            convertNum = UtilMgr.convNum

            # update CPU usage of tasks #
            updateTaskInfo(prevDbusData, prevSentData, prevRecvData)

            if DbusAnalyzer.dbgObj:
                cpuUsage = DbusAnalyzer.dbgObj.getCpuUsage()
                ttime = cpuUsage[0] / SysMgr.uptimeDiff
                utime = cpuUsage[1] / SysMgr.uptimeDiff
                stime = cpuUsage[2] / SysMgr.uptimeDiff
                cpuStr = '%d%%(Usr:%d%%/Sys:%d%%)' % (ttime, utime, stime)
            else:
                cpuStr = '?'

            # print title #
            SysMgr.addPrint(\
                ("[%s] [Time: %7.3f] [Interval: %.1f] "
                "[NrMsg: %s] [NrErr: %s] [CPU: %s]\n") % \
                    ('D-Bus Info', SysMgr.uptime, \
                    SysMgr.uptimeDiff, \
                    convertNum(prevDbusData['totalCnt']),
                    convertNum(prevDbusData['totalErr']),
                    cpuStr))

            # print resource usage of tasks #
            taskManager.printSystemUsage()
            taskManager.printProcUsage()
            taskManager.reinitStats()
            SysMgr.printTopStats()

            # check repeat count #
            checkRepeatCnt()

            # enable alarm #
            signal.signal(signal.SIGALRM, printSummary)

            # reset timer #
            SysMgr.updateTimer()

        def executeLoop(rdPipeList):
            tid = SysMgr.syscall('gettid')

            # main thread #
            if SysMgr.pid == tid:
                SysMgr.updateUptime()

                # update stats #
                updateTaskInfo(\
                    ThreadAnalyzer.dbusData, \
                    DbusAnalyzer.sentData, \
                    DbusAnalyzer.recvData)

                # save initial stat of tasks #
                taskManager.reinitStats()

                # set timer #
                signal.signal(signal.SIGALRM, printSummary)
                SysMgr.updateTimer()

            while 1:
                if len(rdPipeList) == 0:
                    return

                # multi-threaded loop #
                if len(threadingList) > 0:
                    # sibling thread #
                    if SysMgr.pid != tid:
                        updateDataFromPipe(rdPipeList)
                    # main thread #
                    else:
                        try:
                            signal.pause()
                        except SystemExit:
                            sys.exit(0)
                        except:
                            break
                # single-threaded loop #
                else:
                    updateDataFromPipe(rdPipeList)

        def updateData(data):
            tid, params, bus, service = data

            # convert string to dict #
            jsonData = UtilMgr.convStr2Dict(params)
            if not jsonData:
                return

            # check message #
            try:
                ctype = jsonData["name"]

                # check time #
                if jsonData["type"] != "enter":
                    return
            except:
                return

            # check args #
            try:
                # check syscall #
                if ctype == "sendmsg" or ctype == "recvmsg":
                    msgList = jsonData["args"]["msg"]["msg_iov"]
                    handleMsg(ctype, msgList, jsonData, data)
                elif ctype == "sendmmsg" or ctype == "recvmmsg":
                    for idx, value in jsonData["args"]["msg"].items():
                        msgList = value["msg_iov"]
                        handleMsg(ctype, msgList, jsonData, data)
                else:
                    return
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printWarn(\
                    "Fail to handle %s" % [jsonData], reason=True)

        def handleMsg(ctype, msgList, jsonData, data):
            try:
                tid, params, bus, service = data

                libgioObj = SysMgr.libgioObj
                libgObj = SysMgr.libgObj

                mlist = {}
                cnt = long(0)
                gdmsg = long(0)

                if type(msgList) is not dict:
                    return

                msgs = []
                for key, msg in sorted(msgList.items()):
                    msgs.append(msg)

                for idx, msg in enumerate(msgs):
                    # get message info #
                    length = msg['len']
                    ecall = msg['data']

                    # free gdbus message object #
                    if gdmsg != 0:
                        libgObj.g_object_unref(gdmsg)
                        gdmsg = long(0)

                    # decode from base64 #
                    call = UtilMgr.decodeBase64(ecall)
                    if type(call) is bytes:
                        call = call.decode('latin-1')

                    # check message sequence #
                    isFirst = isLast = False
                    if idx == 0:
                        isFirst = True
                    if idx == len(msgs)-1:
                        isLast = True

                    # update message size #
                    if length == 0:
                        length = len(call)

                    # check message size #
                    if length == 0:
                        ThreadAnalyzer.dbusData['totalErr'] += 1
                        continue

                    # recover data #
                    if len(call) > length:
                        call = call[:length]
                    elif len(call) < length:
                        call = call + ('\0' * (length - len(call)))

                    # check previous data #
                    if not tid in DbusAnalyzer.prevData:
                        DbusAnalyzer.prevData[tid] = dict()
                        DbusAnalyzer.prevData[tid]['recvmsg'] = ''
                        DbusAnalyzer.prevData[tid]['sendmsg'] = ''

                    try:
                        prevData = DbusAnalyzer.prevData[tid][ctype]
                    except SystemExit:
                        sys.exit(0)
                    except:
                        prevData = ''

                    # composite data #
                    if isLast:
                        if DbusAnalyzer.prevData[tid][ctype]:
                            call = DbusAnalyzer.prevData[tid][ctype] + call
                        DbusAnalyzer.prevData[tid][ctype] = ''
                    elif isFirst:
                        DbusAnalyzer.prevData[tid][ctype] = call
                        continue
                    else:
                        DbusAnalyzer.prevData[tid][ctype] += call
                        continue

                    # cast bytes to void_p #
                    buf = c_char_p(call.encode('latin-1'))

                    errp = POINTER(DbusAnalyzer.errObj)()

                    # check message size in header #
                    hsize = libgioObj.g_dbus_message_bytes_needed(\
                        buf, c_ulong(len(call)), byref(errp))
                    if hsize > len(call):
                        continue

                    # create GDBusMessage from bytes #
                    gdmsg = libgioObj.g_dbus_message_new_from_blob(\
                        buf, c_ulong(len(call)), 0, byref(errp))

                    # check error #
                    if not gdmsg and errp:
                        code = errp.contents.code
                        message = errp.contents.message

                        SysMgr.printWarn(\
                            "Fail to convert GDbusMessage because %s(%s)" % \
                            (DbusAnalyzer.G_IO_ERROR_TYPE[code], message))

                        libgioObj.g_error_free(byref(errp.contents))

                        ThreadAnalyzer.dbusData['totalErr'] += 1
                        continue

                    # get address of the message #
                    addr = c_ulong(gdmsg)

                    # get sender #
                    srcInfo = '??'
                    src = libgioObj.g_dbus_message_get_sender(addr)
                    if src:
                        if type(src) is bytes:
                            src = src.decode()
                        srcInfo = src
                    if service and src in service:
                        srcInfo = service[src]

                    # get receiver #
                    desInfo = '??'
                    des = libgioObj.g_dbus_message_get_destination(addr)
                    if des:
                        if type(des) is bytes:
                            des = des.decode()
                        desInfo = des
                    if service and des in service:
                        desInfo = service[des]

                    # get message type #
                    try:
                        nrType = libgioObj.g_dbus_message_get_message_type(addr)
                        mtype = DbusAnalyzer.GDBusMessageType[nrType]
                    except SystemExit:
                        sys.exit(0)
                    except:
                        SysMgr.printWarn(\
                            "Fail to get type of GDbusMessage", reason=True)
                        ThreadAnalyzer.dbusData['totalErr'] += 1
                        continue

                    # check direction #
                    if ctype.startswith('sendm'):
                        direction = 'OUT'
                        data = DbusAnalyzer.sentData
                        msgTable = DbusAnalyzer.msgSentTable
                    else:
                        direction = 'IN'
                        data = DbusAnalyzer.recvData
                        msgTable = DbusAnalyzer.msgRecvTable

                    effectiveReply = False
                    if mtype == 'RETURN':
                        # get reply-serial #
                        repSerial = \
                            libgioObj.g_dbus_message_get_reply_serial(\
                                c_ulong(gdmsg))
                        if repSerial in msgTable:
                            effectiveReply = True

                    # print message #
                    if SysMgr.isPrintDbusMode() or SysMgr.customCmd:
                        if len(jsonData['backtrace']) > 2:
                            backtrace = \
                                'Backtrace: %s\n' % jsonData['backtrace']
                        else:
                            backtrace = ''

                        if SysMgr.isDbusTopMode() or SysMgr.showAll:
                            addInfo = "\n%s%s" % \
                                (libgioObj.g_dbus_message_print(\
                                    c_ulong(gdmsg), c_ulong(0)).decode(), \
                                    backtrace)
                        else:
                            path = libgioObj.g_dbus_message_get_path(addr)
                            if not path:
                                path = b''

                            iface = \
                                libgioObj.g_dbus_message_get_interface(addr)
                            if not iface:
                                iface = b''

                            member = libgioObj.g_dbus_message_get_member(addr)
                            if not member:
                                member = b''

                            addInfo = " %s.%s" % \
                                (iface.decode(), member.decode())

                        msgStr = \
                            "[%s] %s(%s) %s->%s %s %g %s%s" % \
                            (mtype, jsonData['comm'], tid, srcInfo, desInfo, \
                                direction, jsonData['timediff'], \
                                UtilMgr.convSize2Unit(hsize), addInfo)

                        if effectiveReply:
                            pass
                        elif SysMgr.customCmd and \
                            not UtilMgr.isEffectiveStr(\
                                msgStr, SysMgr.customCmd, ignCap=True):
                            continue

                        if SysMgr.isPrintDbusMode():
                            SysMgr.printPipe(msgStr, flush=True)
                            continue

                    # set task default dict #
                    DbusAnalyzer.sentData.setdefault(tid, dict())
                    DbusAnalyzer.recvData.setdefault(tid, dict())

                    # return check #
                    if mtype == 'RETURN':
                        if repSerial in msgTable:
                            targetIf, prevTime = msgTable[repSerial]
                        else:
                            targetIf = prevTime = None

                        # handle method return #
                        if targetIf in data[tid] and prevTime:
                            lastData = data[tid][targetIf]
                            elapsed = jsonData['time'] - prevTime

                            if lastData['min'] == 0 or \
                                elapsed < lastData['min']:
                                data[tid][targetIf]['min'] = elapsed

                            if elapsed > lastData['max']:
                                data[tid][targetIf]['max'] = elapsed

                            data[tid][targetIf]['total'] += elapsed
                            data[tid][targetIf]['cnt'] += 1
                            data[tid][targetIf]['time'] = long(0)

                        continue

                    # get properties from message #
                    #path = libgioObj.g_dbus_message_get_path(addr)
                    interface = libgioObj.g_dbus_message_get_interface(addr)
                    member = libgioObj.g_dbus_message_get_member(addr)
                    arg0 = libgioObj.g_dbus_message_get_arg0(addr)
                    serial = libgioObj.g_dbus_message_get_serial(addr)

                    # handle error message #
                    if mtype == 'ERROR' or mtype == 'INVALID':
                        ename = libgioObj.g_dbus_message_get_error_name(addr)
                        if not ename:
                            continue

                        mname = '[%6s] %3s %s: %s' % \
                            (mtype, direction, ename.decode(), arg0.decode())
                        data[tid].setdefault(mname, dict(DbusAnalyzer.taskInfo))
                        data[tid][mname]['cnt'] += 1
                        data[tid][mname]['err'] += 1
                        ThreadAnalyzer.dbusData['totalErr'] += 1
                    # handle normal message #
                    else:
                        mname = '[%6s] %3s %s.%s' % \
                            (mtype, direction, \
                                interface.decode(), member.decode())

                    # save serial number except for signal #
                    if mtype != 'SIGNAL':
                        msgTable[serial] = (mname, jsonData['time'])

                    # initialize new interface #
                    data[tid].setdefault(mname, dict(DbusAnalyzer.taskInfo))

                    # increase count #
                    cnt += 1
                    if mname not in mlist:
                        mlist[mname] = {'count': 1}
                    else:
                        mlist[mname]['count'] += 1

                    # increase size #
                    data[tid][mname]['size'] += hsize

                    # save timestamp #
                    data[tid][mname]['time'] = jsonData['time']

                    # save last interface except for signal #
                    if mtype != 'SIGNAL':
                        pass

                if cnt == 0:
                    return

                # acquire lock #
                if lock:
                    lock.acquire()

                # increase count #
                if tid not in ThreadAnalyzer.dbusData:
                    ThreadAnalyzer.dbusData[tid] = {'totalCnt': cnt}
                else:
                    ThreadAnalyzer.dbusData[tid]['totalCnt'] += cnt

                ThreadAnalyzer.dbusData['totalCnt'] += cnt

                # merge D-Bus interface #
                for name, value in mlist.items():
                    try:
                        ThreadAnalyzer.dbusData[tid][name]['cnt'] += \
                            value['count']
                    except SystemExit:
                        sys.exit(0)
                    except:
                        ThreadAnalyzer.dbusData[tid][name] = dict()
                        ThreadAnalyzer.dbusData[tid][name]['cnt'] = \
                            value['count']
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printWarn(\
                    "Fail to handle %s" % [jsonData], reason=True)
            finally:
                # free gdbus message object #
                if gdmsg != 0:
                    libgObj.g_object_unref(gdmsg)

                # release lock #
                if lock and lock.locked():
                    try:
                        lock.release()
                    except SystemExit:
                        sys.exit(0)
                    except:
                        pass

        def updateDataFromPipe(rdPipeList):
            # merge dbus data #
            try:
                # wait for event #
                [read, write, error] = \
                    selectObj.select(rdPipeList, [], [])

                # read messages through pipe connected to child processes #
                for robj in read:
                    # get tid of target #
                    try:
                        index = pipeList.index(robj)
                        tid = taskList[index]
                        bus = busList[index]
                        try:
                            service = busServiceList[tid][index]
                        except:
                            service = None
                    except SystemExit:
                        sys.exit(0)
                    except:
                        tid = '?'
                        bus = None
                        service = None

                    # handle data arrived #
                    while 1:
                        output = robj.readline()
                        if output == '\n':
                            continue
                        elif output == '':
                            try:
                                rdPipeList.remove(robj)
                            except SystemExit:
                                sys.exit(0)
                            except:
                                pass
                        elif output and len(output) > 0:
                            updateData((tid, output, bus, service))

                        break
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printWarn('Fail to read data from pipe', reason=True)
                return

        def getDefaultTasks(comm, withSibling=True):
            taskList = []
            tempList = SysMgr.getPids(comm, withSibling=withSibling)
            for tid in tempList:
                taskList.append(SysMgr.getTgid(tid))

                comm = SysMgr.getComm(tid)
                if comm == 'gdbus':
                    taskList.append(tid)

            return taskList

        # check permission #
        SysMgr.checkPerm()

        # check filter #
        taskList = []
        if not SysMgr.filterGroup:
            onlyDaemon = True
            taskList += getDefaultTasks('dbus-daemon')
            taskList += getDefaultTasks('dbus-broker')
        else:
            onlyDaemon = False
            for val in SysMgr.filterGroup:
                if SysMgr.groupProcEnable:
                    taskList += SysMgr.getPids(val, withSibling=True)
                else:
                    taskList += getDefaultTasks(val)
        if not taskList:
            SysMgr.printErr(\
                "Fail to find task to analyze D-Bus message")
            sys.exit(0)
        else:
            # remove redundant tasks #
            taskList = SysMgr.clearList(taskList)
            taskList.sort(key=int)
            SysMgr.printInfo((\
                "only specific processes that are involved "
                "in the process group [ %s ] are shown") % \
                    SysMgr.getCommList(taskList))

        # prepare D-Bus methods to analyze BLOB data #
        DbusAnalyzer.prepareDbusMethods()

        # get select object #
        selectObj = SysMgr.getPkg('select')

        # get threading object #
        threadObj = SysMgr.getPkg('threading', False)
        if threadObj:
            lock = threadObj.Lock()
        else:
            lock = None

        # initialize task stat #
        DbusAnalyzer.dbgObj = Debugger(SysMgr.pid, attach=False)
        DbusAnalyzer.dbgObj.initValues()
        DbusAnalyzer.dbgObj.getCpuUsage()

        # define common list #
        busList = []
        pipeList = []
        busServiceList = {}
        gBusServiceList = {}
        interfaceList = {}
        threadingList = []
        SysMgr.filterGroup = taskList

        # initialize system stat #
        SysMgr.exceptCommFilter = True
        taskManager = ThreadAnalyzer(onlyInstance=True)
        taskManager.saveSystemStat()
        SysMgr.sort = 'd'
        SysMgr.processEnable = False
        SysMgr.cmdlineEnable = True

        # set target syscalls #
        if not onlyDaemon:
            SysMgr.syscallList.append(\
                ConfigMgr.sysList.index('sys_recvmsg'))
            SysMgr.syscallList.append(\
                ConfigMgr.sysList.index('sys_recvmmsg'))
        SysMgr.syscallList.append(\
            ConfigMgr.sysList.index('sys_sendmsg'))
        SysMgr.syscallList.append(\
            ConfigMgr.sysList.index('sys_sendmmsg'))

        # create child processes to attach each targets #
        for tid in taskList:
            # create pipe #
            rd, wr = os.pipe()

            # get cmdline for parent #
            try:
                ppidIdx = SysMgr.topInstance.ppidIdx
                ppid = taskManager.procData[tid]['stat'][ppidIdx]
                cmdline = SysMgr.getCmdline(ppid)
            except:
                cmdline = ''

            # get bus type #
            bus = None
            listen = None
            cmdline += SysMgr.getCmdline(tid)
            if '--system' in cmdline:
                bus = 'system'
            elif '--session' in cmdline:
                bus = 'session'
            elif '--scope system' in cmdline:
                bus = 'system'
            elif '--scope user' in cmdline:
                bus = 'user'
            elif '--config-file=' in cmdline:
                try:
                    cpath = cmdline.split('--config-file=', 1)[1]
                    pos = cpath.find(' --')
                    if pos > 0:
                        cpath = cpath[:pos]

                    with open(cpath, "r") as fd:
                        for item in fd.readlines():
                            item = item.strip()
                            if item.startswith('<listen>'):
                                item = item.lstrip('<listen>')
                                item = item.split('</listen>')[0]
                                item = item.strip()
                                listen = item
                            if item.startswith('<type>'):
                                item = item.lstrip('<type>')
                                item = item.split('</type>')[0]
                                item = item.strip()
                                bus = item
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printWarn(\
                        "Fail to get D-Bus configuration", reason=True)
            busList.append(bus)

            # get servce list #
            if bus:
                services = DbusAnalyzer.getBusService(bus, tid=tid, addr=listen)
            else:
                services = None

            # register services #
            busServiceList[tid] = []
            if services:
                busProcList = {}

                # register process #
                for idx, service in enumerate(services):
                    pinfo = DbusAnalyzer.getServiceProc(bus, service)
                    busProcList[service] = pinfo
                    gBusServiceList.setdefault(service, pinfo)

                    # register methods and properties #
                    if False and not service.startswith(':'):
                        interfaceList[service] = \
                            DbusAnalyzer.getStats(bus, 'introspect', service)

                busServiceList[tid].append(busProcList)
            else:
                busServiceList[tid].append(dict())

            # print signals #
            if mode == 'signal':
                ret = DbusAnalyzer.getStats(bus, 'allmatch')
                if ret:
                    perProc, perSig = ret
                    DbusAnalyzer.printSignalInfo(tid, perProc, perSig, busProcList)
                continue

            # create a new process #
            pid = SysMgr.createProcess(chPgid=False)

            # parent #
            if pid > 0:
                os.close(wr)
                rdPipe = os.fdopen(rd)
                pipeList.append(rdPipe)

                # create a new worker thread #
                if threadObj:
                    tobj = threadObj.Thread(\
                        target=executeLoop, args=[[rdPipe]])
                    tobj.daemon = True
                    threadingList.append(tobj)
            # child #
            elif pid == 0:
                # redirect stdout to pipe #
                os.dup2(wr,1)
                os.close(wr)
                os.close(rd)

                # set SIGPIPE handler for termination of parent #
                SysMgr.setPipeHandler()

                # set options #
                sys.argv[1] = 'strace'
                SysMgr.showAll = True
                SysMgr.optStrace = True
                SysMgr.encodeB64Enable = True
                SysMgr.intervalEnable = long(0)
                SysMgr.printFile = SysMgr.fileForPrint = None
                SysMgr.logEnable = False
                SysMgr.filterGroup = [tid]
                SysMgr.jsonOutputEnable = True

                # execute strace mode #
                SysMgr.doTrace('syscall')

                sys.exit(0)

            # error #
            else:
                sys.exit(0)

        # check signal mode #
        if mode == 'signal':
            return

        # start worker threads #
        for tobj in threadingList:
            tobj.start()

        # run event loop #
        executeLoop(pipeList)





class DltAnalyzer(object):
    """ Manager for DLT """

    # define constant #
    DLT_HTYP_WEID = 0x04
    DLT_SIZE_WEID = DLT_ID_SIZE = 4
    DLT_MSIN_MSTP = 0x0e # message type #
    DLT_MSIN_MSTP_SHIFT = 1 # shift right offset to get mstp value #
    DLT_DAEMON_TEXTSIZE = 10024
    DLT_FILTER_MAX = 30

    # define message type #
    MSGTYPE = \
        ["log", "app_trace", "nw_trace", "control"]
    LOGINFO = \
        ["", "fatal", "error", "warn", "info", "debug", "verb"]

    # define log level #
    LOGLEVEL = {
        "DEFAULT":  -1, # Default log level
        "OFF": 0x00, # Log level off
        "FATAL": 0x01, # fatal system error
        "ERROR": 0x02, # error with impact to correct functionality
        "WARN": 0x03, # warning, correct behaviour could not be ensured
        "INFO": 0x04, # informational
        "DEBUG": 0x05, # debug
        "VERBOSE": 0x06, # highest grade of information
    }

    SERVICEID = {
        "DLT_SERVICE_ID": 0x00,
        "DLT_SERVICE_ID_SET_LOG_LEVEL": 0x01,
        "DLT_SERVICE_ID_SET_TRACE_STATUS": 0x02,
        "DLT_SERVICE_ID_GET_LOG_INFO": 0x03,
        "DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL": 0x04,
        "DLT_SERVICE_ID_STORE_CONFIG": 0x05,
        "DLT_SERVICE_ID_RESET_TO_FACTORY_DEFAULT": 0x06,
        "DLT_SERVICE_ID_SET_COM_INTERFACE_STATUS": 0x07,
        "DLT_SERVICE_ID_SET_COM_INTERFACE_MAX_BANDWIDTH": 0x08,
        "DLT_SERVICE_ID_SET_VERBOSE_MODE": 0x09,
        "DLT_SERVICE_ID_SET_MESSAGE_FILTERING": 0x0A,
        "DLT_SERVICE_ID_SET_TIMING_PACKETS": 0x0B,
        "DLT_SERVICE_ID_GET_LOCAL_TIME": 0x0C,
        "DLT_SERVICE_ID_USE_ECU_ID": 0x0D,
        "DLT_SERVICE_ID_USE_SESSION_ID": 0x0E,
        "DLT_SERVICE_ID_USE_TIMESTAMP": 0x0F,
        "DLT_SERVICE_ID_USE_EXTENDED_HEADER": 0x10,
        "DLT_SERVICE_ID_SET_DEFAULT_LOG_LEVEL": 0x11,
        "DLT_SERVICE_ID_SET_DEFAULT_TRACE_STATUS": 0x12,
        "DLT_SERVICE_ID_GET_SOFTWARE_VERSION": 0x13,
        "DLT_SERVICE_ID_MESSAGE_BUFFER_OVERFLOW": 0x14,
    }

    SERVICERESPONSE = {
        "DLT_SERVICE_RESPONSE_OK": 0x00,
        "DLT_SERVICE_RESPONSE_NOT_SUPPORTED": 0x01,
        "DLT_SERVICE_RESPONSE_ERROR": 0x02,
        "DLT_SERVICE_RESPONSE_PERM_DENIED": 0x03,
        "DLT_SERVICE_RESPONSE_WARNING": 0x04,
        "DLT_SERVICE_RESPONSE_LAST": 0x05,
    }

    # define list #
    pids = []
    procInfo = None
    dltData = {'cnt': long(0)}

    @staticmethod
    def printSummary():
        quitLoop = False
        convertFunc = UtilMgr.convNum

        # update uptime #
        SysMgr.updateUptime()

        # print title #
        SysMgr.addPrint(\
            ("[%s] [Time: %7.3f] [Interval: %.1f] [NrMsg: %s]\n") % \
                ('DLT Info', SysMgr.uptime, \
                SysMgr.uptimeDiff, \
                convertFunc(DltAnalyzer.dltData['cnt'])))

        # update daemon stat #
        DltAnalyzer.procInfo.saveProcInstance()
        for pid in DltAnalyzer.pids:
            DltAnalyzer.procInfo.saveProcData(\
                '%s/%s' % (SysMgr.procPath, pid), pid)
        DltAnalyzer.procInfo.printProcUsage()
        DltAnalyzer.procInfo.reinitStats()

        SysMgr.addPrint(\
                "{0:^20} | {1:^19} | {2:^19} |\n{3:1}\n".format(\
                "ECU", "AP", "CONTEXT", twoLine), newline=2)

        # traverse DLT table #
        dltCnt = long(0)
        for ecuId, ecuItem in sorted(DltAnalyzer.dltData.items(), \
            key=lambda x:x[1]['cnt'] if x[0] != 'cnt' else 0, \
            reverse=True):
            if ecuId == 'cnt':
                continue

            if quitLoop or \
                SysMgr.checkCutCond():
                break

            ecuCnt = ecuItem['cnt']
            ecuPer = ecuCnt / float(DltAnalyzer.dltData['cnt']) * 100
            ecuStr = "{0:4} {1:>8}({2:5.1f}%)\n".format(\
                ecuId, convertFunc(ecuCnt), ecuPer)
            SysMgr.addPrint(ecuStr)
            dltCnt += 1

            for apId, apItem in sorted(ecuItem.items(), \
                key=lambda x:x[1]['cnt'] if x[0] != 'cnt' else 0, \
                reverse=True):
                if apId == 'cnt':
                    continue

                if quitLoop or \
                    SysMgr.checkCutCond():
                    quitLoop = True
                    break

                depth = len(ecuStr) * ' '
                apCnt = apItem['cnt']
                apPer = apCnt / float(ecuCnt) * 100
                apStr = "{0:1}{1:4} {2:>8}({3:5.1f}%)\n".format(\
                    depth, apId, convertFunc(apCnt), apPer)
                SysMgr.addPrint(apStr)

                for ctxId, ctxItem in sorted(apItem.items(), \
                    key=lambda x:x[1]['cnt'] if x[0] != 'cnt' else 0, \
                    reverse=True):
                    if ctxId == 'cnt':
                        continue

                    if quitLoop or \
                        SysMgr.checkCutCond():
                        quitLoop = True
                        break

                    depth = len(apStr) * ' '
                    ctxCnt = ctxItem['cnt']
                    ctxPer = ctxCnt / float(apCnt) * 100
                    ctxStr = "{0:1}{1:4} {2:>8}({3:5.1f}%)\n".format(\
                        depth, ctxId, convertFunc(ctxCnt), ctxPer)
                    SysMgr.addPrint(ctxStr)

        if dltCnt == 0:
            SysMgr.addPrint('\tNone\n')

        if not quitLoop:
            SysMgr.addPrint('%s\n' % oneLine)

        SysMgr.printTopStats()

        # initialize data #
        DltAnalyzer.dltData = {'cnt': long(0)}



    @staticmethod
    def onAlarm(signum, frame):
        if SysMgr.isPrintDltMode():
            SysMgr.progressCnt += 1
            if SysMgr.repeatCount <= SysMgr.progressCnt:
                sys.exit(0)

        if DltAnalyzer.dltData['cnt'] == 0 and \
            not SysMgr.inWaitStatus:
            SysMgr.printWarn(\
                "No DLT message received", True)
        else:
            DltAnalyzer.printSummary()

        SysMgr.updateTimer()



    @staticmethod
    def handleMessage(dltObj, msg, buf, mode, verbose, buffered=False):
        DLT_MSIN_MTIN = 0xf0 # message type info #
        DLT_MSIN_MTIN_SHIFT = 4 # shift right offset to get mtin value #

        # save and reset global filter #
        filterGroup = SysMgr.filterGroup

        # pick storage info #
        if msg.storageheader:
            ecuId = msg.storageheader.contents.ecu.decode()
        else:
            return
        if msg.extendedheader:
            apId = msg.extendedheader.contents.apid.decode()
            ctxId = msg.extendedheader.contents.ctid.decode()
        else:
            return

        # summarizing #
        if mode == 'top':
            # check filter #
            if len(filterGroup) > 0:
                skipFlag = True
                for cond in filterGroup:
                    if cond == ecuId or \
                        cond == apId or \
                        cond == ctxId:
                        skipFlag = False
                        break
                if skipFlag:
                    return

            DltAnalyzer.dltData['cnt'] += 1

            # add ecuId #
            if not ecuId in DltAnalyzer.dltData:
                DltAnalyzer.dltData[ecuId] = {'cnt': long(0)}
            DltAnalyzer.dltData[ecuId]['cnt'] += 1

            # add apId #
            if not apId in DltAnalyzer.dltData[ecuId]:
                DltAnalyzer.dltData[ecuId][apId] = {'cnt': long(0)}
            DltAnalyzer.dltData[ecuId][apId]['cnt'] += 1

            # add ctxId #
            if not ctxId in DltAnalyzer.dltData[ecuId][apId]:
                DltAnalyzer.dltData[ecuId][apId][ctxId] = {'cnt': long(0)}
            DltAnalyzer.dltData[ecuId][apId][ctxId]['cnt'] += 1
        # printing #
        elif mode == 'print':
            # get payload #
            dltObj.dlt_message_payload(\
                byref(msg), buf, \
                DltAnalyzer.DLT_DAEMON_TEXTSIZE, 2, verbose)
            try:
                #string = buf.value.decode("utf8")
                string = buf.value
                string = string.decode()
            except:
                string = [string]

            # check filter #
            if len(filterGroup) > 0:
                skipFlag = True
                for cond in filterGroup:
                    if cond == ecuId or \
                        cond == apId or \
                        cond == ctxId or \
                        cond in string:
                        skipFlag = False
                        break
                if skipFlag:
                    return

            # get message info #
            timeSec = msg.storageheader.contents.seconds
            timeUs = msg.storageheader.contents.microseconds
            uptime = '%.6f' % (msg.headerextra.tmsp / float(10000))
            subtype = \
                (msg.extendedheader.contents.msin & DLT_MSIN_MTIN) \
                    >> DLT_MSIN_MTIN_SHIFT
            try:
                info = DltAnalyzer.LOGINFO[subtype]
            except:
                info = ''

            # get date time #
            ntime = time.strftime(\
                '%Y-%m-%d %H:%M:%S', time.localtime(timeSec))

            output = "{0:1}.{1:06d} {2:1} {3:4} {4:4} {5:4} {6:5} {7!s:1}".format(\
                ntime, timeUs, uptime, ecuId, apId, ctxId, info, string)

            if buffered:
                SysMgr.addPrint(output, force=True, listBuf=True)
            else:
                SysMgr.printPipe(output, flush=True)



    @staticmethod
    def doLogDlt(\
        appid='GUID'.encode(), context='GUID'.encode(), msg=None, level='INFO'):
        # get ctypes object #
        SysMgr.importPkgItems('ctypes')

        class DltContext(Structure):
            _fields_ = [
                ('contextID', c_char * 4),
                ('log_level_pos', c_int32),
                ('log_level_ptr', POINTER(c_int8)),
                ('trace_status_ptr', POINTER(c_int8)),
                ('mcnt', c_uint8)
            ]

        DLT_USER_BUF_MAX_SIZE = 1380

        # set log level #
        try:
            loglevel = DltAnalyzer.LOGLEVEL[level.upper()]
        except:
            loglevel = DltAnalyzer.LOGLEVEL['INFO']

        # load DLT library #
        try:
            if not SysMgr.dltObj:
                SysMgr.dltObj = SysMgr.loadLib(SysMgr.libdltPath)
            if not SysMgr.dltObj:
                raise Exception()
            dltObj = SysMgr.dltObj
        except:
            SysMgr.dltObj = None
            SysMgr.printWarn(\
                'Fail to find %s to log DLT' % SysMgr.libdltPath, True)
            sys.exit(0)

        # register #
        if not SysMgr.dltCtx:
            ctx = DltContext()
            ret = dltObj.dlt_register_app(appid, 'Guider'.encode())
            if ret < 0:
                SysMgr.printErr(\
                    "Fail to register app '%s'" % appid)
                sys.exit(0)

            ret = dltObj.dlt_register_context(byref(ctx), context, 'Guider'.encode())
            if ret < 0:
                SysMgr.printErr(\
                    "Fail to register context '%s'" % context)
                sys.exit(0)

            SysMgr.dltCtx = ctx

        # log #
        pos = long(0)
        while 1:
            if len(msg[pos:]) >= DLT_USER_BUF_MAX_SIZE:
                end = DLT_USER_BUF_MAX_SIZE + pos
            else:
                end = len(msg)

            ret = dltObj.dlt_log_string(\
                byref(SysMgr.dltCtx), loglevel, msg[pos:end].encode())

            if end == len(msg):
                return ret

            pos = end

        '''
        # unregister #
        dltObj.dlt_unregister_context(byref(ctx))
        dltObj.dlt_unregister_app()
        '''



    @staticmethod
    def runDltReceiver(mode='top'):
        def findNextHeader(path, filePos):
            with open(path, "rb") as fobj:
                lastPos = filePos
                fobj.seek(lastPos)
                buf = fobj.read(1024)
                while buf:
                    found = buf.find(b"DLT\x01")
                    if found != -1:
                        return lastPos + found
                    lastPos = fobj.tell()
                    buf = fobj.read(1024)
            return None

        def setFilter(dltObj, dltFilter, dltFile, apid=None, ctid=None, init=True):
            # initialize filter #
            if init and dltObj.dlt_filter_init(byref(dltFilter), verbose) == -1:
                SysMgr.printErr(\
                    "Fail to initialize the DLTFilter object")
                return -1

            if dltObj.dlt_filter_add(\
                byref(dltFilter), apid or b"", ctid or b"", verbose) == -1:
                SysMgr.printErr(\
                    "Fail to add %s and %s to the DLTFilter object" % \
                        (apid, ctid))
                return -1

            if dltFilter.counter >= DltAnalyzer.DLT_FILTER_MAX:
                SysMgr.printErr((\
                    "Fail to add %s and %s to the DLTFilter object "
                    "because maximum filter count %s exceed") % \
                        (apid, ctid, DltAnalyzer.DLT_FILTER_MAX))
                return -1

            return dltObj.dlt_file_set_filter(\
                byref(dltFile), byref(dltFilter), verbose)

        # get ctypes object #
        SysMgr.importPkgItems('ctypes')

        # define constant #
        DLT_HTYP_WEID = DltAnalyzer.DLT_HTYP_WEID
        DLT_ID_SIZE = DltAnalyzer.DLT_ID_SIZE
        DLT_FILTER_MAX = DltAnalyzer.DLT_FILTER_MAX

        class DltContext(Structure):
            _fields_ = [
                ('contextID', c_char * 4),
                ('log_level_pos', c_int32),
                ('log_level_ptr', POINTER(c_int8)),
                ('trace_status_ptr', POINTER(c_int8)),
                ('mcnt', c_uint8)
            ]

        class DltReceiver(Structure):
            '''
            typedef struct
             {
                 int32_t lastBytesRcvd;    /**< bytes received in last receive call */
                 int32_t bytesRcvd;        /**< received bytes */
                 int32_t totalBytesRcvd;   /**< total number of received bytes */
                 char *buffer;             /**< pointer to receiver buffer */
                 char *buf;                /**< pointer to position within receiver buffer */
                 char *backup_buf;     /** pointer to the buffer with partial messages if any **/
                 int fd;                   /**< connection handle */
                 int32_t buffersize;       /**< size of receiver buffer */
             } DltReceiver;
             '''

            _fields_ = [
                ("lastBytesRcvd", c_int32),
                ("bytesRcvd", c_int32),
                ("totalBytesRcvd", c_int32),
                ("buffer", POINTER(c_char)),
                ("buf", POINTER(c_char)),
                ("backup_buf", POINTER(c_char)),
                ("fd", c_int),
                ("buffersize", c_int32)
            ]

        class DltClient(Structure):
            '''
            typedef struct
            {
                DltReceiver receiver;  /**< receiver pointer to dlt receiver structure */
                int sock;              /**< sock Connection handle/socket */
                char *servIP;          /**< servIP IP adress/Hostname of TCP/IP interface */
                int port;              /**< Port for TCP connections (optional) */
                char *serialDevice;    /**< serialDevice Devicename of serial device */
                char *socketPath;      /**< socketPath Unix socket path */
                char ecuid[4];           /**< ECUiD */
                speed_t baudrate;      /**< baudrate Baudrate of serial interface, as speed_t */
                DltClientMode mode;    /**< mode DltClientMode */
            } DltClient;
            '''

            _pack_ = 1
            _fields_ = [
                    ("receiver", DltReceiver),
                    ("sock", c_int),
                    ("servIP", c_char_p),
                    ("port", c_int),
                    ("serialDevice", c_char_p),
                    ("socketPath", c_char_p),
                    ("ecuid", c_char * DLT_ID_SIZE),
                    ("baudrate", c_int),
                    ("mode", c_int)
            ]

        class ContextIDsInfoType(Structure):
            '''
             typedef struct
             {
                 char context_id[DLT_ID_SIZE];
                 int16_t log_level;
                 int16_t trace_status;
                 uint16_t len_context_description;
                 char *context_description;
             } ContextIDsInfoType;
            '''
            _pack_ = 1
            _fields_ = [
                ("context_id", c_char * DLT_ID_SIZE),
                ("log_level", c_int16),
                ("trace_status", c_int16),
                ("len_context_description", c_uint16),
                ("context_description", c_char_p)
            ]

        class AppIDsType(Structure):
            '''
            typedef struct
             {
                 char app_id[DLT_ID_SIZE];
                 uint16_t count_context_ids;
                 ContextIDsInfoType *context_id_info; /**< holds info about a specific con id */
                 uint16_t len_app_description;
                 char *app_description;
             } AppIDsType;
            '''
            _pack_ = 1
            _fields_ = [
                ("app_id", c_char * DLT_ID_SIZE),
                ("count_context_ids", c_uint16),
                ("context_id_info", POINTER(ContextIDsInfoType)),
                ("len_app_description", c_uint16),
                ("app_description", c_char_p)
            ]

        class LogInfoType(Structure):
            '''
            typedef struct
            {
		uint16_t count_app_ids;
		AppIDsType *app_ids;            /**< holds info about a specific app id */
             } LogInfoType;
            '''
            _pack_ = 1
            _fields_ = [
                ("count_app_ids", c_uint16),
                ("app_ids", POINTER(AppIDsType)),
            ]

        class DltServiceGetLogInfoResponse(Structure):
            '''
            typedef struct
            {
                uint32_t service_id;            /**< service ID */
                uint8_t status;                 /**< type of request */
                LogInfoType log_info_type;      /**< log info type */
                char com[DLT_ID_SIZE];      /**< communication interface */
             } DltServiceGetLogInfoResponse;
            '''
            _pack_ = 1
            _fields_ = [
                ("service_id", c_uint32),
                ("status", c_uint8),
                ("log_info_type", LogInfoType),
                ("com", c_char * DLT_ID_SIZE)
            ]

        class DltStorageHeader(Structure):
            '''
            typedef struct
            {
                char pattern[DLT_ID_SIZE];        /**< This pattern should be DLT0x01 */
                uint32_t seconds;                    /**< seconds since 1.1.1970 */
                int32_t microseconds;            /**< Microseconds */
                char ecu[DLT_ID_SIZE];            /**< The ECU id is added, if it is not already in the DLT message itself */
            } PACKED DltStorageHeader;
            '''

            _pack_ = 1
            _fields_ = [
                ("pattern", c_char * DLT_ID_SIZE),
                ("seconds", c_uint32),
                ("microseconds", c_int32),
                ("ecu", c_char * DLT_ID_SIZE)
            ]

            def __reduce__(self):
                return (DltStorageHeader, \
                    (self.pattern, self.seconds, self.microseconds, self.ecu))

        class DltStandardHeader(BigEndianStructure):
            '''
            typedef struct
            {
                uint8_t htyp;           /**< This parameter contains several informations, see definitions below */
                uint8_t mcnt;           /**< The message counter is increased with each sent DLT message */
                uint16_t len;           /**< Length of the complete message, without storage header */
            } PACKED DltStandardHeader;
            '''

            _pack_ = 1
            _fields_ = [
                ("htyp", c_uint8),
                ("mcnt", c_uint8),
                ("len", c_ushort)
            ]

            def __reduce__(self):
                return (DltStandardHeader, (self.htyp, self.mcnt, self.len))

        class DltExtendedHeader(Structure):
            '''
            typedef struct
            {
                uint8_t msin;          /**< messsage info */
                uint8_t noar;          /**< number of arguments */
                char apid[DLT_ID_SIZE];          /**< application id */
                char ctid[DLT_ID_SIZE];          /**< context id */
            } PACKED DltExtendedHeader;
            '''

            _pack_ = 1
            _fields_ = [
                ("msin", c_uint8),
                ("noar", c_uint8),
                ("apid", c_char * DLT_ID_SIZE),
                ("ctid", c_char * DLT_ID_SIZE)
            ]

            def __reduce__(self):
                return (DltExtendedHeader, \
                    (self.msin, self.noar, self.apid, self.ctid))

        class DltStandardHeaderExtra(Structure):
            '''
            typedef struct
            {
                char ecu[DLT_ID_SIZE];       /**< ECU id */
                uint32_t seid;     /**< Session number */
                uint32_t tmsp;     /**< Timestamp since system start in 0.1 milliseconds */
            } PACKED DltStandardHeaderExtra;
            '''

            _pack_ = 1
            _fields_ = [
                ("ecu", c_char * DLT_ID_SIZE),
                ("seid", c_uint32),
                ("tmsp", c_uint32)
            ]

            def __reduce__(self):
                return (DltStandardHeaderExtra, (self.ecu, self.seid, self.tmsp))

        class DLTMessage(Structure):
            '''
            typedef struct sDltMessage
            {
                /* flags */
                int8_t found_serialheader;

                /* offsets */
                int32_t resync_offset;

                /* size parameters */
                int32_t headersize;    /**< size of complete header including storage header */
                int32_t datasize;      /**< size of complete payload */

                /* buffer for current loaded message */
                uint8_t headerbuffer[sizeof(DltStorageHeader)+
                     sizeof(DltStandardHeader)+sizeof(DltStandardHeaderExtra)+sizeof(DltExtendedHeader)];
                     /**< buffer for loading complete header */
                uint8_t *databuffer;         /**< buffer for loading payload */
                int32_t databuffersize;

                /* header values of current loaded message */
                DltStorageHeader       *storageheader;  /**< pointer to storage header of current loaded header */
                DltStandardHeader      *standardheader; /**< pointer to standard header of current loaded header */
                DltStandardHeaderExtra headerextra;     /**< extra parameters of current loaded header */
                DltExtendedHeader      *extendedheader; /**< pointer to extended of current loaded header */
            } DltMessage;
            '''

            _fields_ = [
                ("found_serialheader", c_int8),
                ("resync_offset", c_int32),
                ("headersize", c_int32),
                ("datasize", c_int32),
                ("headerbuffer", \
                    c_uint8 * (sizeof(DltStorageHeader) +
                        sizeof(DltStandardHeader) + \
                        sizeof(DltStandardHeaderExtra) +
                        sizeof(DltExtendedHeader))),
                ("databuffer", POINTER(c_uint8)),
                ("databuffersize", c_int32),
                ("storageheader", POINTER(DltStorageHeader)),
                ("standardheader", POINTER(DltStandardHeader)),
                ("headerextra", DltStandardHeaderExtra),
                ("extendedheader", POINTER(DltExtendedHeader))
            ]

        class DLTFilter(Structure):
            '''
            typedef struct
            {
                char apid[DLT_FILTER_MAX][DLT_ID_SIZE]; /**< application id */
                char ctid[DLT_FILTER_MAX][DLT_ID_SIZE]; /**< context id */
                int  counter;                           /**< number of filters */
            } DltFilter;
            '''

            _fields_ = [
                ("apid", (c_char * DLT_ID_SIZE) * DLT_FILTER_MAX),
                ("ctid", (c_char * DLT_ID_SIZE) * DLT_FILTER_MAX),
                ("counter", c_int)
            ]

        class DLTFile(Structure):
            '''
            typedef struct sDltFile
            {
                /* file handle and index for fast access */
                FILE *handle;      /**< file handle of opened DLT file */
                long *index;       /**< file positions of all DLT messages for fast access to file, only filtered messages */

                /* size parameters */
                int32_t counter;       /**< number of messages in DLT file with filter */
                int32_t counter_total; /**< number of messages in DLT file without filter */
                int32_t position;      /**< current index to message parsed in DLT file starting at 0 */
                long file_length;  /**< length of the file */
                long file_position; /**< current position in the file */

                /* error counters */
                int32_t error_messages; /**< number of incomplete DLT messages found during file parsing */

                /* filter parameters */
                DltFilter *filter;  /**< pointer to filter list. Zero if no filter is set. */
                int32_t filter_counter; /**< number of filter set */

                /* current loaded message */
                DltMessage msg;     /**< pointer to message */

            } DltFile;
            '''

            _fields_ = [
                ("handle", POINTER(c_int)),
                ("index", POINTER(c_long)),
                ("counter", c_int32),
                ("counter_total", c_int32),
                ("position", c_int32),
                ("file_length", c_long),
                ("file_position", c_long),
                ("error_messages", c_int32),
                ("filter", POINTER(DLTFilter)),
                ("filter_counter", c_int32),
                ("msg", DLTMessage)
            ]

        # load DLT library #
        try:
            if not SysMgr.dltObj:
                SysMgr.dltObj = SysMgr.loadLib(SysMgr.libdltPath)

            dltObj = SysMgr.dltObj
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.dltObj = None
            SysMgr.printWarn(\
                'Fail to find %s to get DLT log' % \
                    SysMgr.libdltPath, True, reason=True)
            sys.exit(0)

        # define verbose #
        if SysMgr.warnEnable:
            # set log level to DEBUG #
            if hasattr(dltObj, 'dlt_log_set_level'):
                dltObj.dlt_log_set_level(LogMgr.LOG_DEBUG)

            verbose = 1
        else:
            verbose = long(0)

        # get socket object #
        socket = SysMgr.getPkg('socket')

        try:
            from socket import socket, AF_INET, SOCK_DGRAM, \
                SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR, SO_RCVBUF, \
                create_connection, MSG_PEEK, MSG_DONTWAIT
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Fail to import socket", True)
            sys.exit(0)

        # define default variables #
        msg = DLTMessage()
        dltFile = DLTFile()
        dltFilter = DLTFilter()
        buf = create_string_buffer(\
            b'\000' * DltAnalyzer.DLT_DAEMON_TEXTSIZE)

        # initialize input path #
        flist = []
        if SysMgr.inputParam:
            for item in SysMgr.inputParam.split(','):
                ret = UtilMgr.convertPath(item, retStr=False)
                flist += ret
            flist = list(set(flist))

        # check sort option #
        if SysMgr.findOption('S'):
            buffered = True
            SysMgr.printStreamEnable = False
        else:
            buffered = False

        # messages from file #
        if mode == 'print' and flist:
            for path in flist:
                # convert path string to utf-8 format #
                path = UtilMgr.encodeStr(path)

                # initialize file object #
                ret = dltObj.dlt_file_init(byref(dltFile), verbose)
                if ret < 0:
                    SysMgr.printErr(\
                        "Fail to initialize a DLTFile object")

                # set filter #
                #setFilter(dltObj, dltFilter, dltFile, apid=b"", ctid=b"", init=True)

                # open file #
                ret = dltObj.dlt_file_open(byref(dltFile), path, verbose)
                if ret != 0:
                    SysMgr.printErr(\
                        "Fail to open %s" % path)
                    return
                elif dltFile.file_length == 0:
                    SysMgr.printErr(\
                        "Fail to read %s because size is 0" % path)
                    return

                # read a file #
                while dltFile.file_position < dltFile.file_length:
                    ret = dltObj.dlt_file_read(byref(dltFile), verbose)
                    # storage header corrupted #
                    if ret < 0:
                        nextHeaderPos = findNextHeader(path, dltFile.file_position)
                        if nextHeaderPos is not None:
                            if dltFile.file_position == nextHeaderPos:
                                break
                            else:
                                dltFile.file_position = nextHeaderPos
                        else:
                            break

                # read messages #
                for index in range(0, dltFile.counter_total):
                    ret = dltObj.dlt_file_message(byref(dltFile), index, verbose)
                    if ret < 0:
                        SysMgr.printWarn(\
                            "Fail to read %s message from %s" % (index, path), True)
                        continue

                    # print message #
                    DltAnalyzer.handleMessage(\
                        dltObj, dltFile.msg, buf, mode, verbose, buffered=buffered)

                # free file object #
                ret = dltObj.dlt_file_free(byref(dltFile), verbose)
                if ret < 0:
                    SysMgr.printErr(\
                        "Fail to free a DLTFile object")

            # handle buffered logs #
            if buffered:
                output = SysMgr.getPrintList(retStr=True, sort=True)
                SysMgr.clearPrint()
                SysMgr.printPipe(output, flush=True)

            sys.exit(0)

        # check dlt-daemon #
        DltAnalyzer.pids = SysMgr.getProcPids('dlt-daemon')
        if len(DltAnalyzer.pids) == 0:
            SysMgr.printErr(\
                "Fail to find running dlt-daemon process")
            sys.exit(0)

        # set connection info #
        try:
            if SysMgr.remoteServObj:
                servIp = SysMgr.remoteServObj.ip
                servPort = long(SysMgr.remoteServObj.port)
            else:
                servIp = '127.0.0.1'
                servPort = 3490
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Fail to get the address of dlt-daemon", True)
            sys.exit(0)

        # connect to server #
        try:
            servIpStr = string_at(servIp.encode())
            connSock = create_connection((servIpStr, servPort), timeout=1)

            # set blocking #
            connSock.setblocking(1) # pylint: disable=no-member

            if not connSock:
                raise Exception()
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Fail to connect to dlt-daemon with %s:%s" % \
                    (servIp, servPort), True)
            sys.exit(0)

        # initialize client #
        dltClient = DltClient()
        dltObj.dlt_client_init(byref(dltClient), verbose)
        dltClient.sock = c_int(connSock.fileno())
        dltClient.receiver.fd = c_int(connSock.fileno())
        #dltObj.dlt_client_cleanup(byref(dltClient), verbose)

        # change default log level #
        try:
            if SysMgr.customCmd:
                val = SysMgr.customCmd[0].upper()
                level = DltAnalyzer.LOGLEVEL[val]
                dltObj.dlt_client_send_all_log_level(byref(dltClient), level)
        except:
            SysMgr.printErr(\
                "Fail to set %s to default log level" % val)
            sys.exit(0)

        # print log level #
        try:
            ret = dltObj.dlt_client_get_log_info(byref(dltClient))
            if ret == 0:
                resp = DltServiceGetLogInfoResponse()
                resp.service_id = DltAnalyzer.SERVICEID['DLT_SERVICE_ID_GET_LOG_INFO']
                resp.status = DltAnalyzer.SERVICERESPONSE['DLT_SERVICE_RESPONSE_ERROR']
                dltObj.dlt_client_main_loop(byref(dltClient), byref(resp), 0)
                appids = resp.log_info_type.count_app_ids
                for idx in range(0, appids):
                    app = resp.log_info_type.app_ids[idx]
                    for num in range(0, app.count_context_ids):
                        con = app.context_id_info[num]
                        SysMgr.printPipe("[%s] [%s] %s" % \
                            (app.app_id, con.context_id, con.log_level))
        except:
            SysMgr.printWarn(\
                "Fail to print log level", reason=True)

        # initialize receiver #
        dltReceiver = dltClient.receiver

        # initialize connection #
        try:
            nrConnSock = connSock.fileno() # pylint: disable=no-member
            RECVBUFSIZE = connSock.getsockopt(SOL_SOCKET, SO_RCVBUF) # pylint: disable=no-member

            ret = dltObj.dlt_receiver_init(\
                byref(dltReceiver), c_int(nrConnSock), c_int(RECVBUFSIZE))
            if ret < 0:
                SysMgr.printErr(\
                    "Fail to initialize DLT receiver")
                sys.exit(0)
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Fail to initialize connection", True)
            sys.exit(0)

        # define receiver symbol #
        try:
            if hasattr(dltObj, 'dlt_receiver_receive_socket'):
                dlt_receiver_receive = dltObj.dlt_receiver_receive_socket
            elif hasattr(dltObj, 'dlt_receiver_receive'):
                dlt_receiver_receive = dltObj.dlt_receiver_receive
            else:
                raise Exception()
        except:
            SysMgr.printErr(\
                "Fail to get dlt_receiver_receive symbol")
            sys.exit(0)

        # save timestamp #
        prevTime = time.time()
        SysMgr.updateUptime()

        # initialize dlt-daemon info #
        SysMgr.showAll = True
        SysMgr.cmdlineEnable = True
        procInfo = DltAnalyzer.procInfo = ThreadAnalyzer(onlyInstance=True)
        for pid in DltAnalyzer.pids:
            procInfo.saveProcData(\
                '%s/%s' % (SysMgr.procPath, pid), pid)
            procInfo.saveCmdlineData(\
                '%s/%s' % (SysMgr.procPath, pid), pid)

        # set timer #
        signal.signal(signal.SIGALRM, DltAnalyzer.onAlarm)
        SysMgr.updateTimer()

        if mode == 'top':
            SysMgr.printInfo(\
                "start collecting DLT log... [ STOP(Ctrl+c) ]")
        elif mode == 'print':
            SysMgr.printInfo(\
                "start printing DLT log... [ STOP(Ctrl+c) ]\n")

        while 1:
            try:
                # initialize message #
                ret = dltObj.dlt_message_init(byref(msg), verbose)
                if ret < 0:
                    SysMgr.printErr(\
                        "Fail to initialize DLT message")
                    sys.exit(0)

                # check DLT data to be read #
                try:
                    ret = dlt_receiver_receive(byref(dltReceiver), 0)
                    if ret <= 0:
                        continue
                except:
                    sys.exit(0)

                # check DLT data to be read #
                while 1:
                    ret = dltObj.dlt_message_read(\
                        byref(msg), cast(dltReceiver.buf, POINTER(c_char_p)),\
                        c_uint(dltReceiver.bytesRcvd), c_int(0), c_int(verbose))
                    if ret != 0:
                        # move receiver buffer pointer to start of the buffer #
                        ret = dltObj.dlt_receiver_move_to_begin(\
                            byref(dltReceiver))
                        if ret < 0:
                            SysMgr.printErr(\
                                "Fail to move the pointer to receiver buffer")
                            sys.exit(0)

                        break

                    # get data size to be removed #
                    size = msg.headersize + msg.datasize - \
                        sizeof(DltStorageHeader)
                    if msg.found_serialheader:
                        size += DLT_ID_SIZE

                    # remove message from buffer #
                    if dltObj.dlt_receiver_remove(\
                        byref(dltReceiver), size) < 0:
                        SysMgr.printErr(\
                            "Fail to remove data from buffer")
                        sys.exit(0)

                    # print DLT message #
                    if verbose:
                        dltObj.dlt_message_print_ascii(\
                            byref(msg), byref(buf), \
                            c_uint32(msg.headersize), c_int(verbose))

                    # set storage info #
                    if msg.standardheader.contents.htyp & DLT_HTYP_WEID:
                        dltObj.dlt_set_storageheader(\
                            msg.storageheader, msg.headerextra.ecu)
                    else:
                        dltObj.dlt_set_storageheader(\
                            msg.storageheader, c_char_p(''.encode()))

                    DltAnalyzer.handleMessage(dltObj, msg, buf, mode, verbose)
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printWarn(\
                    "Fail to process DLT message", True, reason=True)
                continue

        # free message #
        dltObj.dlt_message_free(msg, verbose)





class Debugger(object):
    """ Debugger for ptrace """

    globalEvent = None
    gLockObj = None
    gLockPath = None
    dbgInstance = None

    def __init__(self, pid=None, execCmd=None, attach=True, mode=None):
        self.comm = None
        self.mode = mode
        self.status = 'enter'
        self.runStatus = False
        self.attached = attach
        self.execCmd = execCmd
        self.arch = arch = SysMgr.getArch()
        self.skipInst = 5
        self.syscall = ''
        self.bufferedStr = ''
        self.mapFd = None
        self.pmap = None
        self.prevPmap = None
        self.needMapScan = True
        self.initPtrace = False
        self.initWaitpid = False
        self.initPvr = False
        self.initPvw = False
        self.supportGetRegset = True
        self.supportSetRegset = True
        self.supportProcessVmRd = True
        self.supportProcessVmWr = False

        self.args = []
        self.values = []
        self.fileList = []
        self.addrList = []
        self.callstack = []
        self.totalCall = long(0)
        self.syscallAddr = None
        self.callTable = {}
        self.fileTable = {}
        self.bpList = {}
        self.exceptBpList = {}
        self.targetBpList = {}
        self.targetBpFileList = {}
        self.ldInjected = False
        self.libcLoaded = False
        self.dftBpFileList = {}
        self.dftBpSymList = {\
            'mmap': 0,\
            'mmap64': 0,\
            'munmap': 0,\
            'prctl': 0,\
            'pthread_setname_np': 0,\
        }

        self.backtrace = {
            'x86': self.getBacktrace_X86,
            'x64': self.getBacktrace_X86,
            'arm': self.getBacktrace_ARM,
            'aarch64': self.getBacktrace_AARCH64,
        }
        self.btList = None
        self.btStr = None
        self.prevBtList = None
        self.prevBtStr = None

        self.lockObj = None
        self.tempPage = None

        self.peekIdx = ConfigMgr.PTRACE_TYPE.index('PTRACE_PEEKTEXT')
        self.pokeIdx = ConfigMgr.PTRACE_TYPE.index('PTRACE_POKEDATA')
        self.tkillIdx = ConfigMgr.sysList.index('sys_tkill')

        plist = ConfigMgr.PTRACE_TYPE
        self.contCmd = plist.index('PTRACE_CONT')
        self.getregsCmd = plist.index('PTRACE_GETREGS')
        self.setregsCmd = plist.index('PTRACE_SETREGS')
        self.syscallCmd = plist.index('PTRACE_SYSCALL')
        self.sysemuCmd = plist.index('PTRACE_SYSEMU')
        self.singlestepCmd = plist.index('PTRACE_SINGLESTEP')

        # set breakpoint variables #
        if self.arch == 'arm' or \
            self.arch == 'aarch64':
            self.brkInst = b'\xFE\xDE\xFF\xE7'
            self.prevInstOffset = 0
        else:
            self.brkInst = b'\xCC'
            self.prevInstOffset = 1

        # check ptrace scope #
        if Debugger.checkPtraceScope() < 0:
            raise Exception()

        # get ctypes object #
        SysMgr.importPkgItems('ctypes')

        if not SysMgr.loadLibcObj():
            raise Exception('no libc')

        # define member classes #
        '''
struct iovec {
    ptr_t iov_base; /* Starting address */
    size_t iov_len; /* Length in bytes */
};
        '''
        class iovec(Structure):
            _fields_ = (
                ('iov_base', c_void_p),
                ('iov_len', c_size_t)
            )
        self.iovec = iovec
        self.iovec_ptr = iovec_ptr = POINTER(iovec)

        '''
struct msghdr {
    void            *msg_name;  /* ptr to socket address structure */
    int             msg_namelen;    /* size of socket address structure */
    struct iov_iter msg_iter;   /* data */
    void            *msg_control;   /* ancillary data */
    __kernel_size_t msg_controllen; /* ancillary data buffer length */
    unsigned int    msg_flags;  /* flags on received message */
    struct kiocb    *msg_iocb;  /* ptr to iocb for async requests */
};
        '''
        class msghdr(Structure):
            _fields_ = (
                ('msg_name', c_void_p),
                ('msg_namelen', c_uint),
                ('msg_iov', iovec_ptr),
                ('msg_iovlen', c_size_t),
                ('msg_control', c_void_p),
                ('msg_controllen', c_size_t),
                ('msg_flags', c_int)
            )
        self.msghdr = msghdr
        self.msghdr_ptr = POINTER(msghdr)

        '''
struct mmsghdr {
    struct msghdr msg_hdr;  /* Message header */
    unsigned int  msg_len;  /* Number of received bytes for header */
};
        '''
        class mmsghdr(Structure):
            _fields_ = (
                ('msg_hdr', msghdr),
                ('msg_len', c_uint)
            )
        self.mmsghdr = mmsghdr
        self.mmsghdr_ptr = POINTER(mmsghdr)

        '''
struct cmsghdr {
   size_t cmsg_len;    /* Data byte count, including header
			  (type is socklen_t in POSIX) */
   int    cmsg_level;  /* Originating protocol */
   int    cmsg_type;   /* Protocol-specific type */
/* followed by
  unsigned char cmsg_data[]; */
};
        '''
        class cmsghdr(Structure):
            _fields_ = (
                ('cmsg_len', c_size_t),
                ('cmsg_level', c_int),
                ('cmsg_type', c_int)
            )
        self.cmsghdr = cmsghdr
        self.cmsghdr_ptr = cmsghdr_ptr = POINTER(cmsghdr)

        class user_regs_struct(Structure):
            def getdict(struct): # pylint: disable=no-self-argument
                return dict((field, getattr(struct, field)) \
                    for field, _ in struct._fields_)

            if arch == 'powerpc':
                _fields_ = (
                    ("gpr0", c_ulong),
                    ("gpr1", c_ulong),
                    ("gpr2", c_ulong),
                    ("gpr3", c_ulong),
                    ("gpr4", c_ulong),
                    ("gpr5", c_ulong),
                    ("gpr6", c_ulong),
                    ("gpr7", c_ulong),
                    ("gpr8", c_ulong),
                    ("gpr9", c_ulong),
                    ("gpr10", c_ulong),
                    ("gpr11", c_ulong),
                    ("gpr12", c_ulong),
                    ("gpr13", c_ulong),
                    ("gpr14", c_ulong),
                    ("gpr15", c_ulong),
                    ("gpr16", c_ulong),
                    ("gpr17", c_ulong),
                    ("gpr18", c_ulong),
                    ("gpr19", c_ulong),
                    ("gpr20", c_ulong),
                    ("gpr21", c_ulong),
                    ("gpr22", c_ulong),
                    ("gpr23", c_ulong),
                    ("gpr24", c_ulong),
                    ("gpr25", c_ulong),
                    ("gpr26", c_ulong),
                    ("gpr27", c_ulong),
                    ("gpr28", c_ulong),
                    ("gpr29", c_ulong),
                    ("gpr30", c_ulong),
                    ("gpr31", c_ulong),
                    ("nip", c_ulong),
                    ("msr", c_ulong),
                    ("orig_gpr3", c_ulong),
                    ("ctr", c_ulong),
                    ("link", c_ulong),
                    ("xer", c_ulong),
                    ("ccr", c_ulong),
                    ("mq", c_ulong),  # FIXME: ppc64 => softe
                    ("trap", c_ulong),
                    ("dar", c_ulong),
                    ("dsisr", c_ulong),
                    ("result", c_ulong),
                )

            elif arch == 'arm':
                _fields_ = tuple(("r%i" % reg, c_ulong) for reg in range(18))

            elif arch == 'aarch64':
                _fields_ = tuple(("r%i" % reg, c_ulong) for reg in range(35))

            elif arch == 'x64':
                _fields_ = (
                    ("r15", c_ulong),
                    ("r14", c_ulong),
                    ("r13", c_ulong),
                    ("r12", c_ulong),
                    ("rbp", c_ulong),
                    ("rbx", c_ulong),
                    ("r11", c_ulong),
                    ("r10", c_ulong),
                    ("r9", c_ulong),
                    ("r8", c_ulong),
                    ("rax", c_ulong),
                    ("rcx", c_ulong),
                    ("rdx", c_ulong),
                    ("rsi", c_ulong),
                    ("rdi", c_ulong),
                    ("orig_rax", c_ulong),
                    ("rip", c_ulong),
                    ("cs", c_ulong),
                    ("eflags", c_ulong),
                    ("rsp", c_ulong),
                    ("ss", c_ulong),
                    ("fs_base", c_ulong),
                    ("gs_base", c_ulong),
                    ("ds", c_ulong),
                    ("es", c_ulong),
                    ("fs", c_ulong),
                    ("gs", c_ulong)
                )

            elif arch == 'x86':
                _fields_ = (
                    ("ebx", c_ulong),
                    ("ecx", c_ulong),
                    ("edx", c_ulong),
                    ("esi", c_ulong),
                    ("edi", c_ulong),
                    ("ebp", c_ulong),
                    ("eax", c_ulong),
                    ("ds", c_ushort),
                    ("__ds", c_ushort),
                    ("es", c_ushort),
                    ("__es", c_ushort),
                    ("fs", c_ushort),
                    ("__fs", c_ushort),
                    ("gs", c_ushort),
                    ("__gs", c_ushort),
                    ("orig_eax", c_ulong),
                    ("eip", c_ulong),
                    ("cs", c_ushort),
                    ("__cs", c_ushort),
                    ("eflags", c_ulong),
                    ("esp", c_ulong),
                    ("ss", c_ushort),
                    ("__ss", c_ushort),
                )

        # running #
        if self.checkPid(pid) >= 0:
            self.pid = pid
            self.isRunning = True

            if self.isInRun() is None:
                SysMgr.printErr('Fail to find %s thread' % pid)
                sys.exit(0)

            # update comm #
            if not self.comm:
                self.comm = SysMgr.getComm(self.pid, cache=True)

            if attach:
                ret = self.attach(verb=True)
                if ret < 0:
                    sys.exit(0)
        # execute #
        elif self.execCmd:
            self.execute(self.execCmd)
            self.isRunning = False
        # ready #
        else:
            self.pid = None
            self.isRunning = False

        # set register variables #
        self.regs = user_regs_struct()
        self.tempRegs = user_regs_struct()
        self.regsDict = None

        # save instances #
        Debugger.dbgInstance = self

        self.iovecObj = self.iovec(\
            iov_base=addressof(self.regs),\
            iov_len=sizeof(self.regs))

        self.tempIovecObj = self.iovec(\
            iov_base=addressof(self.tempRegs),\
            iov_len=sizeof(self.tempRegs))



    def __del__(self):
        if not self.attached:
            return

        if not self.isAlive():
            return

        # kill childs #
        if hasattr(self, 'childList'):
            SysMgr.killChilds(sig=signal.SIGINT, childs=self.childList)
            del self.childList

        # detach target #
        self.detach()

        # continue target #
        try:
            if self.isStopped():
                os.kill(self.pid, signal.SIGCONT)
        except:
            SysMgr.printSigError(self.pid, 'SIGCONT')
            return



    @staticmethod
    def getGlobalLock(name=None, size=0):
        if Debugger.gLockObj:
            return Debugger.gLockObj

        # create a global lock based on file #
        try:
            SysMgr.importPkgItems('fcntl')

            if os.path.isdir(SysMgr.tmpPath):
                dirpath = SysMgr.tmpPath
            else:
                dirpath = SysMgr.cacheDirPath

            if not name:
                name = SysMgr.pid

            Debugger.gLockPath = '%s/guider_%s.lock' % (dirpath, name)
            Debugger.gLockObj = open(Debugger.gLockPath, 'w')

            if size != 0:
                Debugger.gLockObj.truncate(size)

        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Fail to create %s for lock" % Debugger.gLockPath, True)

            if not SysMgr.forceEnable:
                sys.exit(0)

        return Debugger.gLockObj



    def readArgs(self):
        arch = self.arch
        regs = self.regs

        if arch == 'aarch64':
            return (regs.r0, regs.r1, regs.r2,\
                    regs.r3, regs.r4, regs.r5, regs.r6, regs.r7)
        elif arch == 'arm':
            return (regs.r0, regs.r1, regs.r2,\
                    regs.r3, regs.r4, regs.r5, regs.r6)
        elif arch == 'x64':
            return (regs.rdi, regs.rsi, regs.rdx,\
                    regs.r10, regs.r8, regs.r9)
        elif arch == 'x86':
            return (regs.ebx, regs.ecx, regs.edx,\
                    regs.esi, regs.edi, regs.ebp)
        elif arch == 'powerpc':
            return (regs.gpr3, regs.gpr4, regs.gpr5,\
                    regs.gpr6, regs.gpr7, regs.gpr8)
        else:
            return None



    def writeArgs(self, argList):
        arch = self.arch
        nrArg = len(argList)

        if len(argList) == 0:
            return

        for idx, val in enumerate(argList):
            if val is None or \
                val == '':
                continue

            if arch == 'aarch64':
                if idx == 0:
                    self.regs.r0 = val
                elif idx == 1:
                    self.regs.r1 = val
                elif idx == 2:
                    self.regs.r2 = val
                elif idx == 3:
                    self.regs.r3 = val
                elif idx == 4:
                    self.regs.r4 = val
                elif idx == 5:
                    self.regs.r5 = val
                elif idx == 6:
                    self.regs.r6 = val
                elif idx == 7:
                    self.regs.r7 = val
            elif arch == 'x64':
                if idx == 0:
                    self.regs.rdi = val
                elif idx == 1:
                    self.regs.rsi = val
                elif idx == 2:
                    self.regs.rdx = val
                elif idx == 3:
                    self.regs.rcx = val
                elif idx == 4:
                    self.regs.r8 = val
                elif idx == 5:
                    self.regs.r9 = val
            elif arch == 'arm':
                if idx == 0:
                    self.regs.r0 = val
                elif idx == 1:
                    self.regs.r1 = val
                elif idx == 2:
                    self.regs.r2 = val
                elif idx == 3:
                    self.regs.r3 = val
                elif idx == 4:
                    self.regs.r4 = val
                elif idx == 5:
                    self.regs.r5 = val
                elif idx == 6:
                    self.regs.r6 = val
            elif arch == 'x86':
                if idx == 0:
                    self.regs.ebx = val
                elif idx == 1:
                    self.regs.ecx = val
                elif idx == 2:
                    self.regs.edx = val
                elif idx == 3:
                    self.regs.esi = val
                elif idx == 4:
                    self.regs.edi = val
                elif idx == 5:
                    self.regs.ebp = val
            elif arch == 'powerpc':
                if idx == 0:
                    self.regs.gpr3 = val
                elif idx == 1:
                    self.regs.gpr4 = val
                elif idx == 2:
                    self.regs.gpr5 = val
                elif idx == 3:
                    self.regs.gpr6 = val
                elif idx == 4:
                    self.regs.gpr7 = val
                elif idx == 5:
                    self.regs.gpr8 = val
            else:
                return



    def setPid(self, pid):
        if self.checkPid(pid) < 0:
            SysMgr.printErr('Fail to set PID %s' % pid)
            return -1

        self.pid = pid
        return 0



    def getPid(self):
        return self.pid



    def convRetArgs(self, argList):
        for idx, item in enumerate(deepcopy(argList)):
            if type(item) is str and item.startswith('@'):
                try:
                    argList[idx] = self.retList[item[1:]]
                except:
                    pass

        return argList



    def executeCmd(self, cmdList, sym=None, args=[]):
        def printCmdErr(cmdset, cmd):
            if cmd == 'print':
                cmdformat = "PRINT:VAR"
            elif cmd == 'exec':
                cmdformat = "COMMAND"
            elif cmd == 'ret':
                cmdformat = "VAL"
            elif cmd == 'getarg':
                cmdformat = "REG:REG"
            elif cmd == 'setarg':
                cmdformat = "REG#VAL:REG#VAl"
            elif cmd == 'wrmem':
                cmdformat = "ADDR|REG:VAL:SIZE"
            elif cmd == 'rdmem':
                cmdformat = "ADDR|REG:SIZE"
            elif cmd == 'jump':
                cmdformat = "SYMBOL|ADDR#ARG0#ARG1"
            elif cmd == 'usercall':
                cmdformat = "USERCALL:FUNC#ARG0#ARG1"
            elif cmd == 'syscall':
                cmdformat = "SYSCALL:FUNC#ARG0#ARG1"
            elif cmd == 'load':
                cmdformat = "LOAD:PATH"
            elif cmd == 'save':
                cmdformat = "SAVE:NAME:VAL:TYPE"
            elif cmd == 'start':
                cmdformat = "START"
            elif cmd == 'stop':
                cmdformat = "STOP"
            elif cmd == 'exit':
                cmdformat = "EXIT"

            SysMgr.printErr(\
                "Wrong command '%s', input in the format {%s:%s}" % \
                    (cmdset, cmd, cmdformat))
            sys.exit(0)

        if type(cmdList) is not list:
            return cmdList

        newCmdList = list()

        for cmdval in cmdList:
            # parse cmd set #
            repeat = True
            cmdset = cmdval.split(':', 1)
            cmd = cmdset[0]

            # check repeat #
            if cmd == 'oneshot':
                repeat = False
                if len(cmdset) == 1:
                    continue
                cmdset = cmdval.split(':', 2)[1:]
                cmd = cmdset[0]

            # execute a command #
            try:
                cmdstr = '%8s' % cmd

                if cmd == 'print':
                    if len(cmdset) == 1:
                        self.printContext(newline=True)
                    else:
                        var = cmdset[1]
                        try:
                            data = self.retList[var]
                        except:
                            data = 'N/A'

                        SysMgr.printPipe(\
                            "\n[%s] %s = %s" % (cmdstr, var, data), \
                                newline=False, flush=True)

                elif cmd == 'exec':
                    if len(cmdset) == 1:
                        printCmdErr(cmdval, cmd)

                    SysMgr.printPipe(\
                        "\n[%s] %s\n" % (cmdstr, '; '.join(cmdset[1:])),\
                             newline=False, flush=True)

                    # execute commands #
                    for item in cmdset[1].split(':'):
                        command = item
                        if command.endswith('&'):
                            command = command[:-1]
                            wait = False
                        else:
                            wait = True

                        param = command.split()

                        self.execBgCmd(execCmd=param, mute=False, wait=wait)

                elif cmd == 'ret':
                    if len(cmdset) == 1:
                        printCmdErr(cmdval, cmd)

                    # get return value #
                    try:
                        ret = long(cmdset[1])
                    except SystemExit:
                        sys.exit(0)
                    except:
                        SysMgr.printErr(\
                            "Wrong return value %s" % ret)
                        continue

                    # get return address #
                    wordSize = ConfigMgr.wordSize
                    if self.lr:
                        targetAddr = self.lr
                    else:
                        targetAddr = self.fp + wordSize
                        if targetAddr % wordSize == 0:
                            targetAddr = \
                                self.accessMem(self.peekIdx, targetAddr)
                        else:
                            targetAddr = \
                                self.readMem(targetAddr, retWord=True)

                    SysMgr.printPipe(\
                        "\n[%s] %x" % (cmdstr, ret), \
                            newline=False, flush=True)

                    # set register values #
                    self.setRetVal(ret)
                    self.setPC(targetAddr)
                    self.setRegs()
                    self.updateRegs()

                elif cmd == 'setarg':
                    if len(cmdset) == 1:
                        printCmdErr(cmdval, cmd)

                    # get argument info #
                    nrMax = 0
                    argStr = ''
                    argSet = {}
                    origArgs = args
                    argList = cmdset[1].split(':')

                    # convert args for previous return #
                    argList = self.convRetArgs(argList)

                    for item in argList:
                        idx, val = item.split('#')
                        idx = long(idx)
                        try:
                            val = long(val)
                        except:
                            val = long(val, 16)
                        argSet[idx] = val
                        if nrMax < idx:
                            nrMax = idx
                        argStr += '%s: %s(%s) -> %s(%s), ' % \
                            (idx, hex(origArgs[idx]), origArgs[idx], \
                                hex(val), val)

                    # complete output string #
                    if len(argStr) == 0:
                        res = ''
                    else:
                        res = argStr[:argStr.rfind(',')]

                    # make a new argument list #
                    argList = [None] * (nrMax+1)
                    for idx, val in argSet.items():
                        # convert args for previous return #
                        val = self.convRetArgs([val])

                        argList[long(idx)] = val[0]

                    SysMgr.printPipe(\
                        "\n[%s] %s" % (cmdstr, res),\
                            newline=False, flush=True)

                    # set register values #
                    self.writeArgs(argList)
                    self.setRegs()
                    self.updateRegs()

                elif cmd == 'getarg':
                    if len(cmdset) == 1:
                        printCmdErr(cmdval, cmd)

                    # get argument info #
                    argStr = ''
                    argList = cmdset[1].split(':')

                    # convert args for previous return #
                    argList = self.convRetArgs(argList)

                    for item in argList:
                        try:
                            val = args[long(item)]
                        except SystemExit:
                            sys.exit(0)
                        except:
                            val = 'None'

                        # update return #
                        self.retList[item] = str(val)
                        self.prevReturn = str(val)

                        argStr += '%s: %s(%s), ' % (item, hex(val), val)

                    # complete output string #
                    if len(argStr) == 0:
                        res = ''
                    else:
                        res = argStr[:argStr.rfind(',')]

                    SysMgr.printPipe(\
                        "\n[%s] %s" % (cmdstr, res),\
                            newline=False, flush=True)

                elif cmd == 'wrmem':
                    if len(cmdset) == 1:
                        printCmdErr(cmdval, cmd)

                    # get argument info #
                    memset = cmdset[1].split(':')
                    if len(memset) != 2 and len(memset) != 3:
                        printCmdErr(cmdval, cmd)

                    # convert args for previous return #
                    memset = self.convRetArgs(memset)

                    # get addr #
                    try:
                        addr = long(memset[0])
                    except:
                        addr = long(memset[0], 16)

                    # get value #
                    val = memset[1].encode()

                    # get size #
                    if len(memset) == 3:
                        size = long(memset[2])
                    else:
                        size = len(val)

                    # increase size #
                    if len(val) < size:
                        val += b' ' * (size - len(val))

                    # convert address from registers #
                    try:
                        addr = args[addr]
                    except:
                        pass

                    # get address #
                    if UtilMgr.isNumber(addr):
                        try:
                            addr = long(addr, 16)
                        except:
                            addr = long(addr)
                    else:
                        SysMgr.printErr(\
                            "Wrong addr value %s" % addr)
                        continue

                    SysMgr.printPipe(\
                        "\n[%s] %s: %s(%sbyte)" % \
                            (cmdstr, hex(addr), [val[:size]], size),\
                                newline=False, flush=True)

                    # set register values #
                    ret = self.writeMem(addr, val, size)
                    if ret == -1:
                        SysMgr.printErr(\
                            "Fail to write '%s' to %s" % (val, hex(addr)))
                        continue

                elif cmd == 'rdmem':
                    if len(cmdset) == 1:
                        printCmdErr(cmdval, cmd)

                    # get argument info #
                    memset = cmdset[1].split(':')
                    if len(memset) != 1 and len(memset) != 2:
                        printCmdErr(cmdval, cmd)

                    # convert args for previous return #
                    memset = self.convRetArgs(memset)

                    # get addr #
                    try:
                        addr = long(memset[0])
                    except:
                        addr = long(memset[0], 16)

                    # get size #
                    if len(memset) == 2:
                        size = long(memset[1])
                    else:
                        size = 32

                    # convert address from registers #
                    try:
                        addr = args[addr]
                    except SystemExit:
                        sys.exit(0)
                    except:
                        pass

                    # get address #
                    if UtilMgr.isNumber(addr):
                        try:
                            addr = long(addr, 16)
                        except:
                            addr = long(addr)
                    else:
                        SysMgr.printErr("wrong addr %s" % addr)
                        continue

                    # get memory value #
                    ret = self.readMem(addr, size)

                    # update return #
                    self.retList[addr] = str(ret)
                    self.prevReturn = str(ret)

                    if ret == -1:
                        SysMgr.printErr(\
                            "Fail to read from %s" % hex(addr))
                        continue

                    SysMgr.printPipe(\
                        "\n[%s] %s: %s(%sbyte)" % \
                            (cmdstr, hex(addr), [ret], size),\
                                newline=False, flush=True)

                elif cmd == 'start':
                    SysMgr.printPipe(\
                        "\n[%s]\n" % (cmdstr), newline=False, flush=True)

                    SysMgr.customCmd = None

                    self.loadSymbols()
                    self.updateBpList()

                elif cmd == 'save':
                    if len(cmdset) == 1:
                        printCmdErr(cmdval, cmd)

                    cmdlist = cmdset[1].split(':')
                    var = cmdlist[0]

                    if len(cmdlist) == 1:
                        data = self.prevReturn
                    else:
                        data = cmdlist[1]
                        if not data:
                            data = self.prevReturn

                        # convert type #
                        if len(cmdlist) == 2:
                            data = long(data)
                        elif len(cmdlist) == 3:
                            dtype = cmdlist[2]
                            if dtype == 'float' or dtype == 'double':
                                data = float(data)
                            elif dtype == 'string':
                                data = str(data)

                    self.retList[var] = data

                    output = "\n[%s] %s = %s" % (cmdstr, var, data)
                    SysMgr.printPipe(output, newline=False, flush=True)

                elif cmd == 'load':
                    if len(cmdset) == 1:
                        printCmdErr(cmdval, cmd)

                    # remove all berakpoints #
                    self.removeAllBreakpoint(verb=False)

                    # convert args for previous return #
                    cmdset = self.convRetArgs(cmdset)

                    # get function info #
                    binary = cmdset[1]
                    ret = self.dlopen(binary)
                    if ret is None:
                        ret = 'FAIL'
                    else:
                        # update return #
                        self.prevReturn = str(ret)

                        ret = hex(ret)

                    output = "\n[%s] %s(%s)" % (cmdstr, binary, ret)
                    SysMgr.printPipe(output, newline=False, flush=True)

                    # inject all breakpoints again #
                    self.loadSymbols()
                    self.updateBpList(verb=False)

                elif cmd == 'syscall':
                    if len(cmdset) == 1:
                        printCmdErr(cmdval, cmd)

                    # get function info #
                    func = cmdset[1].split('#')
                    val = func[0]
                    if len(func) > 1:
                        argList = func[1:]

                        # convert args for previous return #
                        argList = self.convRetArgs(argList)

                        argStr = ', '.join(list(map(str, argList)))
                        argStr = '(%s)' % argStr
                    else:
                        argList = []
                        argStr = '()'

                    output = "\n[%s] %s%s" % (cmdstr, val, argStr)

                    SysMgr.printPipe(output, newline=False, flush=True)

                    # remove a breakpoint for syscall #
                    self.removeBreakpoint(self.getSyscallAddr())

                    # call function $
                    ret = self.remoteSyscall(val, argList)
                    if ret is None:
                        ret = 0

                    # update return #
                    self.retList[val] = str(ret)
                    self.prevReturn = str(ret)

                    SysMgr.printPipe(\
                        ' = %s(%s)' % (hex(ret), ret), \
                            newline=False, flush=True)

                    # inject a breakpoint for syscall again #
                    self.injectBreakpoint(self.getSyscallAddr())

                elif cmd == 'usercall':
                    if len(cmdset) == 1:
                        printCmdErr(cmdval, cmd)

                    # get function info #
                    func = cmdset[1].split('#')
                    val = func[0]
                    if len(func) > 1:
                        argList = func[1:]

                        # convert args for previous return #
                        argList = self.convRetArgs(argList)

                        argStr = ', '.join(list(map(str, argList)))
                        argStr = '(%s)' % argStr
                    else:
                        argList = []
                        argStr = '()'

                    # get address #
                    if UtilMgr.isNumber(val):
                        try:
                            addr = long(val)
                        except:
                            addr = long(val, 16)
                    else:
                        ret = self.getAddrBySymbol(val)
                        if not ret:
                            SysMgr.printErr("No found %s" % val)
                            continue
                        elif len(ret) > 1:
                            self.printSymbolList(ret)

                        addr = ret[0][0]

                    output = "\n[%s] %s(%x)%s" % (cmdstr, val, addr, argStr)

                    if sym == val or \
                        self.pc == addr:
                        skip = True
                        output = "%s (SKIP)" % output
                    else:
                        skip = False

                    if not skip:
                        # remove all berakpoints #
                        self.removeAllBreakpoint(verb=False)

                    SysMgr.printPipe(output, newline=False, flush=True)

                    if not skip:
                        # call function $
                        ret = self.remoteUsercall(addr, argList)
                        if ret is None:
                            ret = 0

                        # update return #
                        self.retList[val] = str(ret)
                        self.prevReturn = str(ret)

                        SysMgr.printPipe(\
                            ' = %s(%s)' % \
                                (hex(ret), ret), newline=False, flush=True)

                        # inject all breakpoints again #
                        self.updateBpList(verb=False)

                elif cmd == 'jump':
                    if len(cmdset) == 1:
                        printCmdErr(cmdval, cmd)

                    # get function info #
                    func = cmdset[1].split('#')
                    val = func[0]
                    if len(func) > 1:
                        argList = func[1:]
                        args = ', '.join(argList)
                        args = '(%s)' % args
                    else:
                        argList = []
                        args = '()'

                    # convert args for previous return #
                    argList = self.convRetArgs(argList)

                    # convert type to integer #
                    argList = list(map(long, argList))

                    # get address #
                    if UtilMgr.isNumber(val):
                        try:
                            addr = long(val)
                        except:
                            addr = long(val, 16)
                    else:
                        ret = self.getAddrBySymbol(val)
                        if not ret:
                            SysMgr.printErr("No found %s" % val)
                            continue
                        elif len(ret) > 1:
                            self.printSymbolList(ret)

                        addr = ret[0][0]

                    output = "\n[%s] %s(%x) -> %s(%x)%s" % \
                        (cmdstr, sym, self.pc, val, addr, args)

                    if sym == val or \
                        self.pc == addr:
                        skip = True
                        output = "%s (SKIP)" % output
                    else:
                        skip = False

                    SysMgr.printPipe(output, newline=False, flush=True)

                    # set register values #
                    if not skip:
                        self.setPC(addr)
                        self.writeArgs(argList)
                        self.setRegs()
                        self.updateRegs()

                elif cmd == 'sleep':
                    if len(cmdset) == 1:
                        val = 1
                    else:
                        val = float(cmdset[1])

                    SysMgr.printPipe(\
                        "\n[%s] %g sec" % \
                            (cmdstr, val), newline=False, flush=True)

                    time.sleep(val)

                elif cmd == 'stop':
                    SysMgr.printPipe(\
                        "\n[%s]\n" % (cmdstr), newline=False, flush=True)

                    SysMgr.blockSignal(signal.SIGINT, act='unblock')
                    SysMgr.waitEvent(exit=True)

                elif cmd == 'kill':
                    SysMgr.printPipe(\
                        "\n[%s]\n" % (cmdstr), newline=False, flush=True)

                    self.kill()

                    sys.exit(0)

                elif cmd == 'exit':
                    SysMgr.printPipe(\
                        "\n[%s]\n" % (cmdstr), newline=False, flush=True)
                    sys.exit(0)

                else:
                    raise Exception("No command supported")
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "Fail to handle '%s' command" % cmd, True)
                sys.exit(0)

            # re-register command #
            if repeat:
                newCmdList.append(cmdval)

        SysMgr.printPipe()

        return newCmdList



    def setTraceme(self):
        cmd = ConfigMgr.PTRACE_TYPE.index('PTRACE_TRACEME')
        return self.ptrace(cmd)



    def execBgCmd(self, execCmd, mute=True, wait=True):
        pid = SysMgr.createProcess()
        if pid < 0:
            return pid
        elif pid > 0:
            if wait:
                os.waitpid(pid, 0)
            return

        # execute #
        SysMgr.executeProcess(cmd=execCmd, mute=mute)

        # execute fail #
        os._exit(0)



    def execute(self, execCmd, mute=True):
        pid = SysMgr.createProcess()
        if pid == 0:
            self.pid = os.getpid()

            # set tracee flag #
            self.setTraceme()

            # execute #
            SysMgr.executeProcess(cmd=execCmd, mute=mute)

            # execute fail #
            os._exit(0)
        else:
            self.pid = pid



    def removeBpFileByAddr(self, addr):
        fname = self.getFileFromMap(addr)
        if not fname:
            return

        fcache = ElfAnalyzer.getObject(fname)
        if not fcache:
            return

        for item in fcache.sortedAddrTable:
            self.removeBreakpoint(addr + item)



    def removeAllBreakpoint(self, tgid=None, verb=True):
        if not tgid:
            tgid = self.pid

        if verb:
            SysMgr.printStat(\
                r"start removing %s breakpoints from %s(%s) process..." % \
                    (UtilMgr.convNum(len(self.bpList)), \
                        SysMgr.getComm(tgid, cache=True), tgid))

        # remove all breakpoints #
        targetBpList = list(self.bpList.keys())
        for idx, addr in enumerate(targetBpList):
            if verb:
                UtilMgr.printProgress(idx, len(targetBpList))
            self.removeBreakpoint(addr)

        if verb:
            UtilMgr.deleteProgress()



    def removeBreakpoint(self, addr):
        if addr in self.bpList:
            savedData = self.bpList[addr]['data']
        else:
            SysMgr.printWarn(\
                'No breakpoint with addr %s' % hex(addr).rstrip('L'))
            return None

        # write original data #
        if savedData and \
            not savedData.startswith(self.brkInst):
            self.writeMem(addr, savedData, skipCheck=True)

        # change breakpoint status #
        self.bpList[addr]['set'] = False

        data = self.bpList[addr]
        symbol = data['symbol']
        filename = data['filename']
        reins = data['reins']

        if SysMgr.warnEnable:
            SysMgr.printWarn(\
                'Removed the breakpoint %s(%s) from %s(%s)' % \
                    (hex(addr).rstrip('L'), symbol, self.comm, self.pid))

        return (symbol, filename, reins)



    def convertFilterValue(self, origCmdSet):
        cmdSet = list()
        for cmd in origCmdSet:
            cmds = cmd.split(':')
            if cmds[0] != 'filter' or \
                len(cmds) < 4 or \
                cmds[1].startswith('*'):
                cmdSet.append(cmd)
                continue

            val = cmds[3]
            if val.isdigit():
                val = long(val)
            else:
                try:
                    val = long(val, 16)
                except:
                    SysMgr.printErr(\
                        "Fail to recognize %s as a number" % val, True)
                    sys.exit(0)

            cmds[3] = str(val)
            newCmds = ':'.join(cmds)
            cmdSet.append(newCmds)

        return cmdSet



    def injectBpList(self, symlist, binlist=None, verb=True):
        if len(symlist) == 0:
            symlist.append('**')
        else:
            oldlist = list(symlist)
            symlist = list()
            for sym in oldlist:
                if sym.startswith('|'):
                    symlist.append('**%s' % sym)
                else:
                    symlist.append(sym)

        addrList = []
        cmdList = []

        # add default breakpoints such as mmap #
        for lib in list(self.dftBpFileList.keys()):
            # add all symbols of loader #
            if not self.isRunning and not self.ldInjected and \
                os.path.basename(lib).startswith('ld-'):
                ret = self.getAddrBySymbol('', binary=lib, inc=True)

                for item in ret:
                    ldaddr, ldsym, ldlib = item
                    self.injectBreakpoint(\
                        ldaddr, ldsym, fname=ldlib, reins=True)

                    # register exceptional address #
                    self.exceptBpList[ldaddr] = 0

                self.ldInjected = True
                continue

            # add specific default symbols #
            for dsym in list(self.dftBpSymList.keys()):
                ret = self.getAddrBySymbol(dsym, binary=lib)
                if not ret:
                    continue

                addr = ret[0][0]
                ret = self.injectBreakpoint(\
                    addr, dsym, fname=lib, reins=True)

                # register exceptional address #
                self.exceptBpList[addr] = 0

        # add breakpoints requested by user #
        for value in symlist:
            # parse symbol and commands #
            valueList = value.split('|')
            value = valueList[0]
            if len(valueList) > 1:
                # convert value to decimal #
                cmdSet = self.convertFilterValue(valueList[1:])
            else:
                cmdSet = None

            # address #
            if UtilMgr.isNumber(value):
                try:
                    addr = long(value, 16)
                except:
                    addr = long(value)
                ret = self.getSymbolInfo(addr)
                addrList.append([addr, ret[0], ret[1]])
                cmdList.append(cmdSet)
            # symbol #
            else:
                symbol, inc, start, end = ElfAnalyzer.getFilterFlags(value)

                ret = self.getAddrBySymbol(\
                    symbol, binary=binlist, inc=inc, start=start, end=end)
                if not ret:
                    # execution mode #
                    if self.execCmd or \
                        value == '' or \
                        value in self.dftBpSymList:
                        continue

                    # no binary on map #
                    if binlist:
                        found = False
                        for binary in binlist:
                            if binary in self.pmap:
                                found = True
                                break
                        if not found:
                            SysMgr.printErr(\
                                "Fail to find [ %s ] on map table" % \
                                    ', '.join(binlist))
                            sys.exit(0)

                    # no symbol #
                    SysMgr.printErr(\
                        "Fail to find address for '%s'" % value)
                    sys.exit(0)
                else:
                    addrList += ret
                    for cnt in range(0, len(ret)):
                        cmdList.append(cmdSet)

        if len(addrList) == 0:
            return

        # print target process name #
        tgid = SysMgr.getTgid(self.pid)
        if verb:
            SysMgr.printStat(\
                r"start injecting %s breakpoints for %s(%s) process..." % \
                    (UtilMgr.convNum(len(addrList)), \
                        SysMgr.getComm(tgid, cache=True), tgid))

        # add new breakpoints #
        for idx, item in enumerate(addrList):
            UtilMgr.printProgress(idx, len(addrList))

            if type(item) is list:
                addr, symbol, fname = item
            else:
                continue

            # inject a breakpoint #
            ret = self.injectBreakpoint(\
                addr, symbol, fname=fname, reins=True, cmd=cmdList[idx])

            # remove the address from exception list #
            self.exceptBpList.pop(addr, None)

        UtilMgr.deleteProgress()

        return True



    def checkFilterCond(self, filterCmd, args):
        def printErr(cmd):
            SysMgr.printErr(\
                "Wrong command '%s', input in the format {%s:%s}" % \
                    (cmd, 'filter', 'ADDR|REG:OP:VAL:SIZE'))

        if not filterCmd:
            return True

        for cmd in filterCmd:
            cmdset = cmd.split(':', 1)
            if len(cmdset) == 1:
                printErr(cmd)
                return False

            # get argument info #
            memset = cmdset[1].split(':')
            if len(memset) < 3 or len(memset) > 4:
                printErr(cmd)
                return False

            addr = memset[0]
            if addr[0] == '*':
                ref = True
                addr = long(addr[1:])
            else:
                ref = False
                addr = long(addr)

            op = memset[1]
            val = memset[2]
            if len(memset) == 4:
                size = long(memset[3])
            else:
                size = 0

            # convert address from registers #
            try:
                addr = args[addr]
            except SystemExit:
                sys.exit(0)
            except:
                pass

            # get address #
            if UtilMgr.isNumber(addr):
                try:
                    addr = long(addr, 16)
                except:
                    addr = long(addr)
            else:
                SysMgr.printErr(\
                    "Wrong addr %s" % addr)
                return False

            # get value from memory #
            if ref:
                ret = self.readMem(addr, size)
                if ret == -1:
                    SysMgr.printErr(\
                        "Fail to read from %s" % addr)
                    return False
            # get value from register #
            else:
                ret = addr

            # set size as value length #
            if size == 0:
                size = len(val)

            # check value #
            # == #
            if op.upper() == 'EQ':
                if ref:
                    if ret.decode()[:size] != val:
                        return False
                else:
                    if ret != long(val):
                        return False
            # != #
            elif op.upper() == 'DF':
                if ref:
                    if ret.decode()[:size] == val:
                        return False
                else:
                    if ret == long(val):
                        return False

            # in #
            elif op.upper() == 'INC':
                if ref:
                    if not val in ret.decode()[:size]:
                        return False

            # <= or >= #
            elif op.upper() == 'BT' or op.upper() == 'LT':
                if not UtilMgr.isNumber(val):
                    printErr(cmd)
                    return False

                try:
                    val = long(val)
                except:
                    val = long(val, 16)

                if op.upper() == 'BT' and ret < val:
                    return False
                elif op.upper() == 'LT' and ret > val:
                    return False

        return True



    def injectBreakpoint(\
        self, addr, sym=None, fname=None, size=1, reins=False, cmd=None):
        # get original instruction #
        if addr in self.bpList:
            if self.bpList[addr]['set']:
                if not sym:
                    sym = self.bpList[addr]['symbol']
                SysMgr.printWarn((\
                    'Fail to inject a breakpoint to %s(%s) for %s(%s) '
                    'because it is already injected by myself') % \
                        (hex(addr).rstrip('L'), sym, self.comm, self.pid))
                return False
            else:
                origWord = self.bpList[addr]['data']
                if self.bpList[addr]['reins'] != reins:
                    self.bpList[addr]['reins'] = reins
                self.bpList[addr]['set'] = True
        # a new breakpoint #
        else:
            # read data #
            if addr % ConfigMgr.wordSize:
                origWord = self.readMem(addr)
            else:
                origWord = self.accessMem(self.peekIdx, addr)
                if origWord > 0:
                    origWord = UtilMgr.convWord2Str(origWord)
                else:
                    origWord = None

            if not origWord:
                return False

            # check filter command #
            filterCmd = []
            if cmd:
                newCmd = list(cmd)
                for item in list(newCmd):
                    if item.startswith('filter'):
                        filterCmd.append(item)
                        newCmd.remove(item)
                cmd = newCmd

            # backup data #
            self.bpList[addr] = {
                'data': origWord,
                'number': len(self.bpList),
                'symbol': sym,
                'reins': reins,
                'filename': fname,
                'cmd': cmd,
                'filter': filterCmd,
                'set': True,
            }

        # build trap instruction #
        inst = self.brkInst * size

        # update symbol #
        if not sym:
            sym = self.bpList[addr]['symbol']

        # check instructions whether it is already injected #
        if origWord.startswith(inst):
            if addr in self.bpList and \
                self.bpList[addr]['data'] != inst:
                origWord = self.bpList[addr]['data']
            else:
                SysMgr.printWarn((\
                    'Fail to inject a breakpoint to %s(%s) for %s(%s) '
                    'because it is already injected by another task') % \
                        (hex(addr).rstrip('L'), sym, self.comm, self.pid))
                return False

        # inject trap code #
        ret = self.writeMem(addr, inst, skipCheck=True)

        if ret < 0:
            SysMgr.printWarn(\
                'Fail to inject a breakpoint to %s(%s) for %s(%s)' % \
                    (hex(addr).rstrip('L'), sym, self.comm, self.pid))
            return False
        elif ret == 0:
            if SysMgr.warnEnable:
                SysMgr.printWarn(\
                    'Added a new breakpoint %s(%s)[%s] to %s(%s)' % \
                        (hex(addr).rstrip('L'), sym, fname, \
                            self.comm, self.pid))

        return True



    def attach(self, pid=None, verb=False):
        if not pid:
            pid = self.pid

        if self.checkPid(pid) < 0:
            SysMgr.printWarn(\
                'Fail to attach %s(%s) to guider(%s) because of wrong pid' % \
                    (self.comm, pid, SysMgr.pid), verb)
            return -1

        # attach to the thread #
        plist = ConfigMgr.PTRACE_TYPE
        cmd = plist.index('PTRACE_ATTACH')
        ret = self.ptrace(cmd)
        if ret != 0:
            SysMgr.printWarn('Fail to attach %s(%s) to guider(%s)' % \
                (self.comm, pid, SysMgr.pid), verb)
            return -1
        else:
            SysMgr.printWarn(\
                'Attached %s(%s) to guider(%s)' % \
                    (self.comm, pid, SysMgr.pid))
            self.attached = True
            return 0



    def stop(self, pid=None, thread=True):
        if not pid:
            pid = self.pid

        if self.checkPid(pid) < 0:
            SysMgr.printWarn(\
                'Fail to stop %s(%s) because of wrong pid' % \
                    (self.comm, pid))
            return -1

        # send signal to a thread #
        try:
            if not thread:
                raise Exception()

            return SysMgr.syscall(self.tkillIdx, pid, signal.SIGSTOP)
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printWarn(\
                "Fail to stop %s(%s)" % (self.comm, pid), reason=True)

        # send signal to a process #
        try:
            os.kill(pid, signal.SIGSTOP)
            return 0
        except:
            SysMgr.printSigError(pid, 'SIGSTOP')
            return -1



    def free(self, addr):
        # get function address #
        symbol = 'free'
        func = self.getAddrBySymbol(symbol, one=True)
        if not func:
            return None

        # set args #
        args = [addr]

        # call free $
        ret = self.remoteUsercall(func, args)
        if ret < 0:
            SysMgr.printErr(\
                "Fail to free %s memory for %s(%s)" % \
                    (hex(addr), self.comm, self.pid))
            return None

        return ret



    def convRemoteArgs(self, args):
        freelist = []
        for idx, item in enumerate(deepcopy(args)):
            if type(item) is not str:
                continue
            elif not item.isdigit() or \
                (item.startswith('"') and item.endswith('"')):
                try:
                    args[idx] = long(item, 16)
                except:
                    item = item.strip('"')

                    addr = self.calloc(string=item, temp=True)
                    if not addr:
                        sys.exit(0)

                    args[idx] = long(addr)
                    freelist.append(addr)
            else:
                args[idx] = long(item)

        return args, freelist



    def calloc(self, size=None, string=None, temp=False):
        # get function address #
        symbol = 'calloc'
        func = self.getAddrBySymbol(symbol, one=True)
        if not func:
            return None

        # check size #
        if not size:
            if string:
                size = len(string) + 1
            else:
                SysMgr.printErr(\
                    "Fail to alloc memory for %s(%s) because no size" % \
                        (self.comm, self.pid))
                return None

        # use a temporary page #
        if temp:
            addr = self.getTempPage()
        # use a new memory segment #
        else:
            # set args #
            args = [1, size]

            # call calloc $
            addr = self.remoteUsercall(func, args)
            if addr < 0:
                SysMgr.printErr(\
                    "Fail to alloc %s size of memory for %s(%s)" % \
                        (UtilMgr.convNum(size), self.comm, self.pid))
                return None

        # copy string to memory #
        if string:
            ret = self.writeMem(addr, string.encode())
            if ret == -1:
                SysMgr.printErr(\
                    "Fail to write '%s' to %s" % (string, hex(addr)))
                return None

        return addr



    def getTempPage(self):
        if not self.tempPage:
            self.tempPage = self.mmap()
        return self.tempPage



    def dlclose(self, addr):
        # get function address #
        func = '__libc_dlclose'

        # set args #
        args = [addr]

        # call dlclose #
        ret = self.remoteUsercall(func, args)

        return ret



    def dlopen(self, fname, flags=None):
        # check fname #
        if not os.path.exists(fname):
            SysMgr.printErr(\
                "Fail to find %s for %s(%s)" % \
                    (fname, self.comm, self.pid))
            return None

        # get function address #
        func = '__libc_dlopen_mode'

        '''
        # alloc a memory segment for file name string #
        addr = self.getTempPage()
        if not addr:
            SysMgr.printErr("Fail to allocate a new page")
            return None

        # copy file name string to the new page #
        fname += '\0'
        ret = self.writeMem(addr, fname.encode())
        if ret == -1:
            SysMgr.printErr(\
                "Fail to write '%s' to %s" % (fname, hex(addr)))
            return None
        '''

        if not flags:
            flags = 1 # RTLD_LAZY #

        # set args #
        args = [fname, flags]

        # call dlopen #
        ret = self.remoteUsercall(func, args)
        if ret:
            self.loadSymbols()

        return ret



    def getSyscallAddr(self):
        if not self.syscallAddr:
            self.syscallAddr = self.getAddrBySymbol('syscall', one=True)

        return self.syscallAddr



    def remoteUsercall(self, usercall, args=[], wait=True):
        # convert arguments in advance to prevent nested remote calls #
        args, freelist = self.convRemoteArgs(args)

        # get target info #
        procInfo = '%s(%s)' % (self.comm, self.pid)

        # get original regset #
        if not self.updateRegs():
            return None

        # get backup regset #
        self.backupRegs()
        origPc = self.pc

        '''
        # change access permission on a page pointed by PC #
        ret = self.mprotect(self.pc)
        if ret == -1:
            SysMgr.printErr(\
                "Fail to change access permission on %s page for %s" % \
                    (hex(self.pc), procInfo))
            return None
        '''

        # set usercall address #
        if type(usercall) is long:
            func = usercall
        elif type(usercall) is str:
            # get function address #
            func = self.getAddrBySymbol(usercall, one=True)
            if not func:
                return None
        else:
            SysMgr.printErr(\
                "Fail to recognize %s as a function for %s" % \
                    (usercall, procInfo), True)
            return None
        setattr(self.regs, self.retreg, func)

        # set args #
        self.writeArgs(args)

        # set trap for return #
        if self.arch == 'arm' or self.arch == 'aarch64':
            self.setLR(0)
        elif self.arch == 'x64':
            # align sp - wordSize to a multiple of 16
            wordSize = ConfigMgr.wordSize
            newSP = self.sp
            while 1:
                if (newSP - wordSize * 2) & 0xF == 0:
                    break
                newSP -= wordSize
            newSP -= wordSize
            self.setSP(newSP)
            ret = self.writeMem(newSP, b'\x00' * wordSize)
        elif self.arch == 'x86':
            # toDo: save all args to stack and set trap #
            SysMgr.printErr(\
                "Fail to set trap for return because %s is not supported" % \
                    self.arch)
            sys.exit(0)

        # update PC to target function addr #
        self.setPC(func)

        # apply register set #
        self.setRegs()

        # call function #
        self.cont()
        if not wait:
            return None
        ret = self.waitpid()
        stat = self.getStatus(ret[1])

        # read regs to check results #
        if not self.updateRegs():
            return None
        retVal = self.getRetVal()

        # restore regs #
        self.setRegs(temp=True)
        self.restoreRegs()

        # free memory for string #
        for addr in freelist:
            self.free(addr)

        return retVal



    def remoteSyscall(self, syscall, args=[]):
        # get original regset #
        if not self.updateRegs():
            return

        # get backup regset #
        self.backupRegs()

        # set syscall number #
        if type(syscall) is long:
            sysid = syscall
        elif type(syscall) is str:
            syscall = syscall.lower()
            if not syscall.startswith('sys_'):
                syscall = 'sys_%s' % syscall

            if syscall == 'sys_mmap':
                sysid = ConfigMgr.getMmapId()
            else:
                try:
                    sysid = ConfigMgr.sysList.index(syscall)
                except:
                    SysMgr.printErr("Fail to find %s" % syscall, True)
                    return
        else:
            SysMgr.printErr(\
                "Fail to recognize syscall %s" % syscall, True)
            return
        setattr(self.regs, self.retreg, sysid)

        # convert arguments #
        args, freelist = self.convRemoteArgs(args)

        # set args #
        self.writeArgs([sysid] + args)

        # set PC to syscall function addr #
        addr = self.getSyscallAddr()
        if not addr:
            SysMgr.printErr(\
                "Fail to find syscall address")
            return
        self.setPC(addr)

        # apply register set #
        self.setRegs()

        # execute syscall #
        self.ptrace(self.syscallCmd)
        ret = self.waitpid()
        stat = self.getStatus(ret[1])

        # read regs and change the 6th argument #
        if not self.updateRegs():
            return
        self.writeArgs(args)
        self.setRegs()

        # continue and stop at return #
        self.ptrace(self.syscallCmd)
        ret = self.waitpid()
        stat = self.getStatus(ret[1])

        # read regs to check results #
        if not self.updateRegs():
            return
        ret = self.getRetVal()

        # restore regs #
        self.setRegs(temp=True)
        self.restoreRegs()

        # free memory for string #
        for addr in freelist:
            self.free(addr)

        return ret



    def mmap(self, size=4096, perm='rwx'):
        # set prot #
        prot = 0
        perm = perm.lower()
        if 'r' in perm:
            prot |= 0x1
        if 'w' in perm:
            prot |= 0x2
        if 'x' in perm:
            prot |= 0x4

        # set flags #
        flags = 0x22

        return self.remoteSyscall('mmap', [0, size, prot, flags, 0, 0])



    def mprotect(self, maddr, size=4096, perm='rwx'):
        # align address #
        offset = maddr % SysMgr.pageSize
        if offset > 0:
            maddr -= offset

        # set prot #
        prot = 0
        perm = perm.lower()
        if 'r' in perm:
            prot |= 0x1
        if 'w' in perm:
            prot |= 0x2
        if 'x' in perm:
            prot |= 0x4

        return self.remoteSyscall('sys_mprotect', [maddr, size, prot])



    def kill(self):
        plist = ConfigMgr.PTRACE_TYPE
        cmd = plist.index('PTRACE_KILL')
        ret = self.ptrace(cmd)
        if ret != 0:
            SysMgr.printWarn(\
                'Fail to kill %s(%s)' % (self.comm, self.pid))
            return -1
        else:
            SysMgr.printWarn(\
                'Killed %s(%s)' % (self.comm, self.pid))
            return 0



    def cont(self, pid=None, check=False, sig=0):
        if not self.attached:
            return 0

        if not pid:
            pid = self.pid

        if self.checkPid(pid) < 0:
            SysMgr.printWarn(\
                'Fail to continue %s(%s) because of wrong pid' % \
                    (self.comm, pid))
            return -1

        # check target is running #
        try:
            os.kill(pid, 0)
        except SystemExit:
            sys.exit(0)
        except:
            if not self.isAlive():
                errMsg = \
                    'Fail to continue %s(%s) because it is terminated' % \
                        (self.comm, pid)
                SysMgr.printWarn(errMsg)
                return -1

        # check target status #
        if check:
            cnt = 1000
            while 1:
                ret = self.ptrace(self.contCmd, 0, sig)
                if ret != 0:
                    cnt -= 1
                    time.sleep(0.001)
                    if cnt > 0 and self.isAlive():
                        continue

                    errMsg = \
                        'Fail to continue %s(%s) because it is terminated' % \
                            (self.comm, pid)
                    SysMgr.printErr(errMsg)
                    return -1
                return 0

        # continue target thread #
        ret = self.ptrace(self.contCmd, 0, sig)
        if ret != 0:
            SysMgr.printWarn(\
                'Fail to continue %s(%s)' % (self.comm, pid), reason=True)
            return -1

        return 0



    def doDetach(self, pid):
        if not pid:
            pid = self.pid

        self.attached = False

        plist = ConfigMgr.PTRACE_TYPE
        cmd = plist.index('PTRACE_DETACH')
        ret = self.ptrace(cmd, pid=pid)
        if ret != 0:
            SysMgr.printWarn(\
                'Fail to detach %s(%s) from guider(%s)' % \
                    (self.comm, pid, SysMgr.pid))
            return -1
        else:
            SysMgr.printWarn(\
                'Detached %s(%s) from guider(%s)' % \
                    (self.comm, pid, SysMgr.pid))
            return 0



    def detach(self, only=False, pid=None):
        if only:
            return self.doDetach(pid)

        if not self.attached:
            return

        if hasattr(self, 'pid'):
            pid = self.pid
        else:
            return

        # kill target process executed #
        if hasattr(self, 'isRunning'):
            if not self.isRunning:
                try:
                    os.kill(self.pid, signal.SIGKILL)
                except:
                    SysMgr.printSigError(pid, 'SIGKILL')

                return 0

        # check the process is running #
        try:
            os.kill(pid, 0)
        except:
            return -1

        return self.doDetach(pid)



    def checkPid(self, pid):
        if not pid:
            return -1
        elif not UtilMgr.isNumber(pid):
            return -1
        elif pid <= 0:
            return -1
        else:
            return 0



    def accessMem(self, cmd, addr, data=0):
        wordSize = ConfigMgr.wordSize

        if addr < wordSize:
            SysMgr.printWarn((\
                "Fail to access %s memory "
                "because of wrong address") % hex(addr).rstrip('L'))
            return -1

        if addr % wordSize:
            SysMgr.printWarn((\
                "Fail to access %s memory "
                "because of unaligned address") % hex(addr).rstrip('L'))
            return -1

        return self.ptrace(cmd, addr, data)



    def writeMem(self, addr, data, size=0, skipCheck=False):
        ret = long(0)
        wordSize = ConfigMgr.wordSize

        if addr < wordSize:
            SysMgr.printWarn((\
                "Fail to write to %s memory "
                "because of wrong address") % hex(addr).rstrip('L'))
            return None

        # update size #
        if size == 0 or size > len(data):
            size = len(data)

        if self.supportProcessVmWr:
            try:
                # prepare process_vm_writev syscall #
                process_vm_writev = SysMgr.libcObj.process_vm_writev

                if not self.initPvw:
                    SysMgr.libcObj.process_vm_writev.restype = c_size_t
                    SysMgr.libcObj.process_vm_writev.argtypes = \
                        [c_int, self.iovec_ptr, c_size_t, \
                            self.iovec_ptr, c_size_t, c_ulong]
                    self.initPvw = True

                # create params #
                pid = self.pid

                try:
                    lbuf = (c_char*size)()
                    memmove(byref(lbuf), data, len(data))
                    liov = (self.iovec*1)()[0]
                    liov.iov_base = cast(lbuf, c_void_p)
                    liov.iov_len = size

                    riov = (self.iovec*1)()[0]
                    riov.iov_base = c_void_p(addr)
                    riov.iov_len = size
                except SystemExit:
                    sys.exit(0)
                except:
                    return None

                # do syscall #
                ret = process_vm_writev(pid, liov, 1, riov, 1, 0)
                return ret
            except SystemExit:
                sys.exit(0)
            except:
                self.supportProcessVmWr = False

        # check address alignment #
        offset = addr % wordSize

        # handle interger-type data #
        if not skipCheck and UtilMgr.isNumber(data):
            if offset == 0:
                if size == 0:
                    size = 1
                for idx in range(0, size):
                    ret = self.accessMem(\
                        self.pokeIdx, addr + (idx * wordSize), data)
                    if ret < 0:
                        break
                return ret
            else:
                data = UtilMgr.convWord2Str(long(data))
                if not data:
                    return -1

                # converting integer-type data #
                if 0 <= size <= 1:
                    size = wordSize
                elif size > 1:
                    data = data * size
                    size *= wordSize

        # convert string to bytes #
        if not skipCheck:
            if UtilMgr.isString(data):
                data = UtilMgr.encodeStr(data)
            elif type(data) is not bytes:
                SysMgr.printErr((\
                    "Fail to recognize data to write because "
                    "%s type is not supported") % type(data))
                return -1

        # trim data #
        modWord = len(data) % wordSize
        if modWord > 0:
            data += b'0' * (wordSize - modWord)

        # back up data #
        origData = data[:size]
        origSize = size

        # handle not aligned part #
        if offset > 0:
            addr -= offset
            size += offset

        # read words from target address space #
        data = b''
        tempAddr = addr
        while size > 0:
            word = self.readMem(tempAddr)
            if word is None:
                return -1

            data += word

            size -= wordSize
            tempAddr += wordSize

        # update original data #
        fdata = data[:offset] + origData + data[offset+origSize:]

        # convert type from bytes to word #
        for idx in range(0, len(fdata), wordSize):
            data = UtilMgr.convStr2Word(fdata[idx:idx+wordSize])

            ret = self.accessMem(self.pokeIdx, addr+idx, data)
            if ret == -1:
                break

        return ret



    def updateBpList(self, verb=True):
        if self.mode != 'break':
            return

        # update file list #
        fileList = SysMgr.getOption('T')
        if fileList:
            fileList = list(set(fileList.split(',')))
            self.targetBpFileList.update(dict.fromkeys(fileList, 0))

        # update symbol list #
        if SysMgr.customCmd is None:
            funcFilter = []
        else:
            funcFilter = list(set(SysMgr.customCmd))
            self.targetBpList.update(dict.fromkeys(funcFilter, 0))

        # add per-process breakpoints #
        self.injectBpList(\
            symlist=funcFilter, binlist=fileList, verb=verb)



    def readMem(self, addr, size=0, retWord=False):
        wordSize = ConfigMgr.wordSize

        if not addr:
            return None

        if addr < wordSize:
            SysMgr.printWarn((\
                "Fail to read from %s memory "
                "because of wrong address") % hex(addr).rstrip('L'))
            return None

        # check size #
        if size == 0:
            size = wordSize

        if self.supportProcessVmRd:
            try:
                # prepare process_vm_readv syscall #
                process_vm_readv = SysMgr.libcObj.process_vm_readv

                if not self.initPvr:
                    SysMgr.libcObj.process_vm_readv.restype = c_size_t
                    SysMgr.libcObj.process_vm_readv.argtypes = \
                        [c_int, self.iovec_ptr, c_size_t, \
                            self.iovec_ptr, c_size_t, c_ulong]
                    self.initPvr = True

                # create params #
                pid = self.pid

                try:
                    lbuf = (c_char*size)()
                    liov = (self.iovec*1)()[0]
                    liov.iov_base = cast(byref(lbuf), c_void_p)
                    liov.iov_len = size

                    riov = (self.iovec*1)()[0]
                    riov.iov_base = c_void_p(addr)
                    riov.iov_len = size
                except SystemExit:
                    sys.exit(0)
                except:
                    return None

                # do syscall #
                ret = process_vm_readv(pid, liov, 1, riov, 1, 0)
                if ret > 0:
                    return memoryview(lbuf).tobytes()
                else:
                    return None
            except SystemExit:
                sys.exit(0)
            except:
                self.supportProcessVmRd = False

        # define return list #
        data = bytes()

        # handle not aligned part #
        offset = addr % wordSize
        if offset > 0:
            addr -= offset
            size += offset

        # read words from target address space #
        while size > 0:
            # read a word #
            word = self.accessMem(self.peekIdx, addr)
            if word == -1:
                SysMgr.printErr(\
                    "Fail to read memory %s from %s(%s)" % \
                        (hex(addr).rstrip('L'), self.comm, self.pid))
                return None

            if retWord:
                return word

            # convert a word to a byte string #
            word = UtilMgr.convWord2Str(word)
            if not word:
                return None

            if size < wordSize:
                data += word[:size]
            else:
                data += word

            size -= wordSize
            addr += wordSize

        return data[offset:]



    def readCString(self, addr, chunk=256):
        ret = b''
        while 1:
            string = self.readMem(addr, chunk)
            try:
                idx = string.index(b'\0')
                ret += string[:idx]
                return ret
            except SystemExit:
                sys.exit(0)
            except:
                if string:
                    ret += string

                if len(ret) > SysMgr.pageSize:
                    return ret



    def readMultiMsgHdr(self, addr, vlen):
        msgInfo = {}
        for idx in range(0, vlen):
            offset = idx * sizeof(self.mmsghdr)
            # read msghdr structure #
            ret = self.readMem(addr + offset, sizeof(self.mmsghdr))
            if not ret:
                continue

            # cast struct mmsghdr #
            header = cast(ret, self.mmsghdr_ptr)

            # get msg info #
            msglen = header.contents.msg_len
            msgaddr = addressof(header.contents.msg_hdr)
            ret = self.readMsgHdr(obj=msgaddr)
            if not ret:
                continue

            # add msghdr to list #
            msgInfo[idx] = ret

        if not msgInfo:
            return addr

        return msgInfo



    def readMsgHdr(self, addr=None, obj=None):
        if not addr and not obj:
            return None

        # read msghdr structure #
        if not obj:
            ret = self.readMem(addr, sizeof(self.msghdr))
            if not ret:
                return addr
        else:
            ret = obj

        # cast struct msghdr #
        msginfo = {}
        header = cast(ret, self.msghdr_ptr)

        # get msg info #
        namelen = long(header.contents.msg_namelen)
        msginfo['msg_namelen'] = namelen
        if SysMgr.optStrace or namelen == 0:
            msginfo['msg_name'] = 'NULL'
        else:
            msginfo['msg_name'] = \
                self.readMem(header.contents.msg_name, namelen).\
                    decode('latin-1')

        # get iov header info #
        iovaddr = cast(\
            header.contents.msg_iov, c_void_p).value
        iovlen = long(header.contents.msg_iovlen)

        if not SysMgr.showAll:
            msginfo['msg_iov'] = '0x{0:02x}'.format(iovaddr)
        else:
            msginfo['msg_iov'] = {}

            # get iov info #
            for idx in range(0, iovlen):
                offset = idx * sizeof(self.iovec)

                # get iov object #
                iovobj = self.readMem(\
                    iovaddr+offset, sizeof(self.iovec))
                iovobj = cast(iovobj, self.iovec_ptr)

                # get iov size #
                iovobjlen = long(iovobj.contents.iov_len)
                if iovobjlen == 0:
                    continue

                msginfo['msg_iov'][idx] = {}

                # get iov data #
                iovobjbase = iovobj.contents.iov_base
                iovobjdata = self.readMem(iovobjbase, iovobjlen)

                # encode to base64 #
                if SysMgr.encodeB64Enable:
                    iovobjdata = UtilMgr.encodeBase64(iovobjdata)
                    if sys.version_info >= (3, 0):
                        iovobjdata = iovobjdata.decode('latin-1')

                # save size and data #
                msginfo['msg_iov'][idx]['len'] = iovobjlen
                msginfo['msg_iov'][idx]['data'] = iovobjdata

        # get msg_flags #
        flag = header.contents.msg_flags
        msginfo['msg_flags'] = flag

        # ignore cmsg info #
        return msginfo

        # get socket object #
        socket = SysMgr.getPkg('socket', False)
        if not socket:
            return msginfo

        # get control info #
        control = header.contents.msg_control
        controllen = long(header.contents.msg_controllen)
        msginfo['msg_control'] = {}
        msginfo['msg_control']['len'] = controllen

        if not SysMgr.showAll:
            msginfo['msg_control']['addr'] = control
        elif controllen >= sizeof(self.cmsghdr):
            control = self.readMem(header.contents.msg_control, controllen)
            controlobj = cast(control, self.cmsghdr_ptr)

            cmsglen = long(controlobj.contents.cmsg_len)
            cmsglevel = controlobj.contents.cmsg_level
            cmsgtype = controlobj.contents.cmsg_type

            msginfo['msg_control']['cmsglen'] = cmsglen
            if socket and cmsglevel == socket.SOL_SOCKET:
                msginfo['msg_control']['cmsglevel'] = 'SOL_SOCKET'
            else:
                msginfo['msg_control']['cmsglevel'] = cmsglevel
            try:
                msginfo['msg_control']['cmsgtype'] = \
                    ConfigMgr.CMSG_TYPE[cmsgtype]
            except:
                msginfo['msg_control']['cmsgtype'] = cmsgtype

        return msginfo



    def convertValue(self, argtype, argname, value, seq=0, ref=True, argset={}):
        syscall = self.syscall

        # toDo: convert a integer or mask values #

        # handle sendmsg / recvmsg #
        if syscall == "sendmsg" or syscall == "recvmsg":
            if ref and argname == "msg":
                try:
                    return self.readMsgHdr(value)
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printWarn(\
                        "Fail to get msghdr for %s" % syscall, True, reason=True)

        # handle sendmmsg / recvmmsg #
        if syscall == "sendmmsg" or syscall == "recvmmsg":
            if argname == 'vlen':
                try:
                    if 'msg' in argset:
                        ret = self.readMultiMsgHdr(argset['msg'], value)
                        if ret != argset['msg']:
                            self.changeArg('msg', ret)
                    return value
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printWarn(\
                        "Fail to get mmsghdr for %s" % syscall, True, reason=True)

        # handle special syscalls #
        if syscall == "execve":
            if argname in ("argv", "envp"):
                # toDo: handle double pointer values #
                return value

        if ref and argtype == "const char *" and \
            (argname.endswith("name") or argname.endswith("path")):
            # toDo: add more argnames #
            return self.readCString(self.values[seq])

        if syscall == "socketcall":
            if argname == "call":
                try:
                    return ConfigMgr.SOCKETCALL[value]
                except:
                    return value
            elif argname == "args":
                # toDo: handle socket call args #
                return value

        if syscall.startswith('mmap') or syscall == 'mprotect':
            if argname == 'prot':
                return UtilMgr.getFlagString(\
                    value, ConfigMgr.PROT_TYPE)
            elif argname == 'flags':
                return UtilMgr.getFlagString(\
                    value, ConfigMgr.MAP_TYPE)

        if syscall.startswith('fcntl'):
            if argname == 'cmd':
                return ConfigMgr.FCNTL_TYPE[value]

        if syscall == 'open':
            if argname == 'flags':
                return UtilMgr.getFlagString(\
                    value, ConfigMgr.OPEN_TYPE)

        if argname == 'whence':
            return ConfigMgr.SEEK_TYPE[int(value)]

        if syscall == 'access':
            if argname == 'mode':
                return UtilMgr.getFlagString(\
                    value, ConfigMgr.PERM_TYPE)

        if syscall == 'clone':
            if argname == 'flags':
                return UtilMgr.getFlagString(\
                    value, ConfigMgr.CLONE_TYPE)

        if argname == 'behavior' and \
            syscall.startswith('madvise'):
            try:
                return ConfigMgr.MADV_TYPE[int(value)]
            except:
                return value

        if ref and argname == "buf" and \
            (syscall == "write" or syscall == "read"):
            if self.values[2] > self.pbufsize:
                length = self.pbufsize
            else:
                length = self.values[2]

            # read string from address #
            ret = self.readMem(value, length)
            if ret:
                value = ret

            try:
                return repr(value)[1:-1]
            except:
                return repr(value)

        if argname == "flags" and value:
            if syscall.startswith('send') or \
                syscall.startswith('recv'):
                return UtilMgr.getFlagString(\
                    value, ConfigMgr.MSG_TYPE)

        if argname == "signum" or argname == "sig":
            return ConfigMgr.SIG_LIST[int(value)]

        # remove const prefix #
        if argtype.startswith("const "):
            argtype = argtype[6:]

        # toDo: handle file path #
        pass

        # toDo: handle pointer data type #
        if argtype[-1] == '*':
            return value

        return value



    @staticmethod
    def updateCommFlag(flag=True):
        if not Debugger.globalEvent:
            return

        # set flag value #
        if flag == True:
            value = 1
        else:
            value = 0

        if sys.version_info < (3, 0, 0):
            value = bytes(value)

        Debugger.globalEvent[0] = value # pylint: disable=unsupported-assignment-operation



    @staticmethod
    def needUpdateComm():
        if not Debugger.globalEvent:
            return False

        ret = Debugger.globalEvent[0] # pylint: disable=unsubscriptable-object
        if ret == b'1' or 1:
            return True
        else:
            return False



    @staticmethod
    def onAlarm(signum, frame):
        if Debugger.dbgInstance:
            Debugger.dbgInstance.printIntervalSummary()

        SysMgr.updateTimer()



    def printIntervalSummary(self):
        def resetStats():
            # initialize syscall timetable #
            self.syscallTimeStat = dict()
            self.breakcallTimeStat = dict()

            # reset data #
            self.totalCall = long(0)
            self.callTable = dict()
            SysMgr.clearPrint()

        def checkInterval():
            if SysMgr.repeatCount == 0:
                return

            SysMgr.progressCnt += 1
            if SysMgr.repeatCount <= SysMgr.progressCnt:
                sys.exit(0)

        def finishPrint():
            # print stats #
            SysMgr.printTopStats()

            # check and update repeat count #
            checkInterval()

            resetStats()

        if self.multi and len(self.callTable) == 0:
            resetStats()
            return

        # check user input #
        SysMgr.waitUserInput(\
            wait=0.000001, msg="Press enter key...")

        SysMgr.updateUptime()

        # set time #
        current = time.time()
        diff = current - self.last
        self.last = current

        # update comm #
        self.comm = SysMgr.getComm(self.pid, cache=True)

        # print summary table #
        if self.mode == 'syscall':
            ctype = 'Syscall'
            addInfo = 'Count'
            sampleStr = ''
        elif self.mode == 'break':
            ctype = 'Breakcall'
            addInfo = 'Path'
            sampleStr = ' [SampleTime: %g]' % self.sampleTime
        else:
            ctype = 'Usercall'
            addInfo = 'Path'
            sampleStr = ' [SampleTime: %g]' % self.sampleTime

        nrTotal = float(self.totalCall)
        convert = UtilMgr.convNum

        # get CPU Usage #
        cpuUsage = self.getCpuUsage()
        ttime = cpuUsage[0] / diff
        utime = cpuUsage[1] / diff
        stime = cpuUsage[2] / diff
        cpuStr = '%d%%(Usr:%d%%/Sys:%d%%)' % (ttime, utime, stime)

        # add CPU time info #
        self.cpuUsageList.append([ttime, utime, stime])

        if not SysMgr.showAll and SysMgr.cpuEnable:
            floatTotalUsage = ttime / 100
            floatUserUsage = utime / 100
            floatSysUsage = stime / 100
        else:
            floatTotalUsage = 1
            floatUserUsage = 1
            floatSysUsage = 1

        if self.comm:
            comm = self.comm
        else:
            comm = '??'

        ret = SysMgr.addPrint((\
            '[Top %s Info] [Time: %f] [Interval: %g] [NrSamples: %s] '
            '[Target: %s(%s)] [CPU: %s]%s \n%s\n') % \
                (ctype, SysMgr.uptime, diff, \
                convert(self.totalCall), comm, self.pid, \
                cpuStr, sampleStr, twoLine), newline=2)
        if not ret:
            finishPrint()

        ret = SysMgr.addPrint(\
            '{0:^7} | {1:^144}\n{2:<1}\n'.format(\
                'Usage', 'Function [%s]' % addInfo, twoLine), newline=2)
        if not ret:
            finishPrint()

        cnt = long(0)
        isBtPrinted = False
        for sym, value in sorted(\
            self.callTable.items(), key=lambda x:x[1]['cnt'], reverse=True):
            if sym[0] == '/':
                sym = '??'

            try:
                per = value['cnt'] / nrTotal * 100 * floatTotalUsage
            except:
                break

            if per < 1 and \
                not SysMgr.showAll:
                break

            # stat #
            if self.mode == 'syscall':
                try:
                    total, tmax = self.syscallTimeStat[sym]
                    average = total / value['cnt']
                except:
                    total = average = tmax = long(0)

                addVal = \
                    "Cnt: %s, Tot: %.6f, Avg: %.6f, Max: %.6f, Err: %s" % \
                        (convert(value['cnt']), \
                            total, average, tmax, convert(value['err']))
            elif self.mode == 'break':
                try:
                    prev, total, tmin, tmax = self.breakcallTimeStat[sym]
                    avg = total / value['cnt']
                except:
                    prev = total = tmin = tmax = avg = long(0)

                addVal = \
                    'Path: %s, Cnt: %s, Avg: %.6f, Min: %.6f, Max: %.6f' % \
                        (value['path'], convert(value['cnt']), avg, tmin, tmax)
            else:
                addVal = 'Path: %s, Cnt: %s' % \
                    (value['path'], convert(value['cnt']))

            if SysMgr.checkCutCond():
                break

            ret = SysMgr.addPrint(\
                '{0:>7} | {1:<144}\n'.format(\
                    '%.1f%%' % per, '%s [%s]' % (sym, addVal)))
            if not ret:
                break

            cnt += 1

            # backtrace #
            if len(value['backtrace']) > 0:
                for bt, cnt in sorted(\
                    value['backtrace'].items(), \
                    key=lambda x:x[1], reverse=True):

                    bper = cnt / float(value['cnt']) * 100
                    if bper < 1 and \
                        not SysMgr.showAll:
                        break

                    nline = bt.count('\n') + 1
                    if SysMgr.checkCutCond(nline):
                        finishPrint()
                        return

                    ret = SysMgr.addPrint(\
                        '{0:>17} | {1:<1}\n'.format(\
                            '%.1f%%' % bper, bt), newline=nline)
                    if not ret:
                        break

            if SysMgr.funcDepth > 0:
                isBtPrinted = True
                ret = SysMgr.addPrint('%s\n' % oneLine)
                if not ret:
                    break

        if cnt == 0:
            SysMgr.addPrint('\tNone\n')

        if not isBtPrinted:
            SysMgr.addPrint('%s\n' % oneLine)

        # print stats #
        finishPrint()

        # print progress #
        if SysMgr.repeatCount > 0:
            UtilMgr.printProgress(\
                SysMgr.progressCnt, SysMgr.repeatCount)



    def changeArg(self, name, value):
        for idx, item in enumerate(self.args):
            if item[1] == name:
                self.args[idx][2] = value
                return True
        return False



    def addArg(self, type, name, value):
        self.args.append([type, name, value])



    def clearArgs(self):
        self.args = []



    def getAnonVrangeByOffset(self, offset, fname=None):
        if not fname in self.pmap:
            return

        vstart = self.pmap[fname]['vstart']
        vend = self.pmap[fname]['vend']

        # get ELF object #
        fcache = ElfAnalyzer.getObject(fname)
        if not fcache:
            return [0, 0]

        ret = fcache.getAnonRangeByOffset(offset)
        if not ret:
            return [0, 0]

        # check executable type #
        if not ElfAnalyzer.isRelocFile(fname):
            start = ret[0]
            end = ret[1]
        else:
            start = vstart + ret[0]
            end = vstart + ret[1]

        return [start, end]



    def getVrangeBySymbol(self, symbol, fname=None):
        if not fname in self.pmap:
            return

        vstart = self.pmap[fname]['vstart']
        vend = self.pmap[fname]['vend']

        # get ELF object #
        fcache = ElfAnalyzer.getObject(fname)
        if not fcache:
            return [0, 0]

        ret = fcache.getRangeBySymbol(symbol)
        if not ret:
            return [0, 0]

        # check executable type #
        if not ElfAnalyzer.isRelocFile(fname):
            start = ret[0]
            end = ret[1]
        else:
            start = vstart + ret[0]
            end = vstart + ret[1]

        return [start, end]



    def loadSymbols(self):
        # get list of process mapped files #
        self.pmap = FileAnalyzer.getProcMapInfo(\
            self.pid, self.mapFd, onlyExec=True)
        if not self.pmap or \
            self.pmap == self.prevPmap:
            return False
        else:
            self.prevPmap = self.pmap

        # register default libraries #
        for fpath in list(self.pmap.keys()):
            fname = os.path.basename(fpath)
            if fname.startswith('ld-'):
                self.dftBpFileList[fpath] = 0
            elif fname.startswith('libc-') or \
                fname == 'libc.so':
                self.libcLoaded = True
                self.dftBpFileList[fpath] = 0
            elif fname.startswith('libpthread'):
                self.dftBpFileList[fpath] = 0

        # load file-mapped objects #
        for mfile in list(self.pmap.keys()):
            try:
                eobj = ElfAnalyzer.getObject(mfile)
                if eobj:
                    eobj.mergeSymTable()
            except SystemExit:
                sys.exit(0)
            except:
                pass

        # update file and addr lists from memory map #
        self.fileList, self.addrList = self.getAddrLists()
        if len(self.fileList) == 0:
            SysMgr.printWarn(\
                'Fail to get file list on memory map')

        return True



    def getSymbolInfo(self, vaddr):
        if not vaddr or vaddr < 0:
            return None

        if not self.pid:
            SysMgr.printErr("Fail to get PID to get symbol")
            return None

        # check of maps fd #
        if not self.mapFd:
            self.mapFd = FileAnalyzer.getMapFd(self.pid)
            if not self.mapFd:
                return None

        # scan process memory map #
        if self.needMapScan:
            if self.loadSymbols():
                self.updateBpList(verb=False)
            self.needMapScan = False

        # get file name by address #
        fname = self.getFileFastFromMap(vaddr)
        if not fname:
            SysMgr.printWarn(\
                'Fail to get file name via addr %s' % \
                    hex(vaddr).rstrip('L'))
            return None

        vstart = self.pmap[fname]['vstart']
        vend = self.pmap[fname]['vend']

        # get offset in the file #
        offset = vaddr - vstart
        if offset < 0:
            # set variable to rescan process map #
            self.needMapScan = True

            SysMgr.printWarn((\
                'Fail to get offset in %s via %s '
                'because of wrong memory map') % \
                    (fname, hex(vaddr).rstrip('L')))
            return ['??', fname, '??', '??', '??']

        # get ELF object #
        fcache = ElfAnalyzer.getObject(fname)
        if not fcache:
            return ['??', fname, '??', '??', '??']

        # check executable type #
        if not ElfAnalyzer.isRelocFile(fname):
            offset = vaddr

        try:
            sym = fcache.getSymbolByOffset(offset)
            return [sym, fname, hex(offset).rstrip('L'), vstart, vend]
        except SystemExit:
            sys.exit(0)
        except:
            return ['??', fname, '??', '??', '??']



    def getAddrLists(self):
        fileList = []
        addrList = []

        if not self.pmap:
            return [], []

        for f, item in sorted(\
            self.pmap.items(), key=lambda x: x[1]['vend']):
            fileList.append(f)
            addrList.append(item['vend'])

        return fileList, addrList



    def getFileFromMap(self, vaddr):
        if not self.pmap:
            return None

        try:
            vaddr = long(vaddr)
        except:
            return None

        for fname, value in self.pmap.items():
            if value['vstart'] == vaddr:
                return fname

        return None



    def getFileFastFromMap(self, vaddr):
        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

        try:
            idx = bisect_left(self.addrList, vaddr)
            return self.fileList[idx]
        except SystemExit:
            sys.exit(0)
        except:
            return None



    def printContext(\
        self, regs=True, bt=True, deref=True, args=None, newline=False):
        if not regs and not bt:
            return

        if newline:
            prefix = '\n'
        else:
            prefix = ''

        try:
            taskInfo = '%s(%s)' % (self.comm, self.pid)
        except:
            taskInfo = '??(%s)' % self.pid

        isPrinted = False

        # print register #
        if regs:
            # set regsdict #
            if not self.regsDict:
                self.regsDict = self.regs.getdict()

            if not isPrinted:
                SysMgr.addPrint('%s%s\n' % (prefix, twoLine))
                isPrinted = True

            SysMgr.addPrint(\
                '\tRegister Info [%s]\n%s\n' % (taskInfo, oneLine))

            for reg, val in sorted(self.regsDict.items()):
                if deref and val:
                    rvalue = self.readMem(val)
                    if rvalue:
                        try:
                            rvalue = '"%s"' % rvalue.decode("utf-8")
                            rvalue = re.sub('\W+','', rvalue)
                        except:
                            rvalue = hex(UtilMgr.convStr2Word(rvalue))
                            rvalue = rvalue.rstrip('L')
                    else:
                        rvalue = '?'
                else:
                    rvalue = '?'

                SysMgr.addPrint(\
                    '%s: %x [%s]\n' % (reg, val, rvalue))

            SysMgr.addPrint('%s\n' % twoLine)

        # print backtrace #
        if bt:
            backtrace = self.getBacktrace(cur=True)
            if len(backtrace) > 0:
                if not isPrinted:
                    SysMgr.addPrint('%s%s\n' % (prefix, twoLine))
                    isPrinted = True

                SysMgr.addPrint(\
                    '\tBacktrace Info [%s]\n%s\n' % (taskInfo, oneLine))

                for item in backtrace:
                    SysMgr.addPrint(\
                        '%s(%s)[%s]\n' % \
                            (hex(item[0]).rstrip('L'), item[1], item[2]))

                SysMgr.addPrint('%s\n' % twoLine)

        if SysMgr.printFile:
            self.callPrint.append(SysMgr.bufferString)
        else:
            SysMgr.doPrint(newline=False, clear=True)

        SysMgr.clearPrint()



    def setRetVal(self, val, temp=False):
        try:
            if temp:
                ret = setattr(self.tempRegs, self.retreg, val)
            else:
                ret = setattr(self.regs, self.retreg, val)

            return True
        except SystemExit:
            sys.exit(0)
        except:
            return False



    def getRetVal(self, temp=False):
        try:
            if temp:
                ret = getattr(self.tempRegs, self.retreg)
            else:
                ret = getattr(self.regs, self.retreg)

            return c_long(ret).value
        except SystemExit:
            sys.exit(0)
        except:
            return None



    def getNrSyscall(self):
        try:
            return getattr(self.regs, self.sysreg)
        except SystemExit:
            sys.exit(0)
        except:
            return None



    def addCall(self, sym):
        self.callstack.append([self.sp, sym])



    def updateCallstack(self, sym):
        while 1:
            if len(self.callstack) == 0:
                return
            elif self.callstack[-1][0] > self.sp or \
                self.callstack[-1][0] >= self.prevSp or \
                self.callstack[-1][1] == sym:
                self.callstack.pop()
            else:
                return



    def addSample(\
        self, sym, filename, realtime=False, bt=None, err=None):
        if err:
            # increase err count #
            try:
                self.callTable[sym]['err'] += 1
            except:
                pass

            return

        if realtime:
            self.totalCall += 1

            if not SysMgr.showAll and bt:
                # remove anonymous symbol #
                while 1:
                    if sym != '??':
                        break
                    elif len(bt) == 0:
                        break
                    elif bt[0][1] == '??':
                        bt.pop(0)
                        continue
                    else:
                        sym = bt[0][1]
                        filename = bt[0][2]
                        bt.pop(0)
                        break

                # remove contiguous symbol #
                while 1:
                    if len(bt) == 0:
                        break
                    elif sym == bt[0][1] and filename == bt[0][2]:
                        bt.pop(0)
                        continue
                    break

            # check wait status #
            if self.mode == 'sample' and \
                not self.runStatus:
                sym = 'WAIT(%s)' % sym

            # add backtrace #
            if bt:
                btString = self.getBacktraceString(bt, default=20)
            else:
                btString = None

            # add symbol table #
            if sym in self.callTable:
                self.callTable[sym]['cnt'] += 1
            else:
                self.callTable[sym] = {
                    'cnt': 1,
                    'path': filename,
                    'err': long(0),
                    'backtrace': dict()
                }

            # increase count of callstack #
            if btString:
                try:
                    self.callTable[sym]['backtrace'][btString] += 1
                except SystemExit:
                    sys.exit(0)
                except:
                    if sym in self.callTable:
                        self.callTable[sym]['backtrace'][btString] = 1

            # add file table #
            try:
                self.fileTable[filename]['cnt'] += 1
            except:
                self.fileTable[filename] = dict()
                self.fileTable[filename]['cnt'] = 1

            if not SysMgr.printFile:
                return

        self.callList.append([sym, self.current, filename])



    def checkSymbol(self, sym, newline=False, bt=None):
        if not SysMgr.customCmd or \
            SysMgr.printFile:
            return

        if sym in SysMgr.customCmd:
            sys.stdout.write('\n')

            if SysMgr.showAll:
                # print register set #
                self.printContext(newline=newline)

                # print backtrace #
                try:
                    if not bt:
                        bt = self.getBacktrace()
                except:
                    pass

            # disable timer #
            signal.alarm(0)

            SysMgr.waitUserInput(wait=0, \
                msg="%s() is detected! Press enter to continue..." % sym)

            # enable timer #
            SysMgr.updateTimer()



    def getBacktraceString(self, bt, default=0, maximum=0):
        if self.btStr:
            return self.btStr

        btString = ''
        prevSym = None
        prevFile = None

        cnt = 0
        pos = default

        if maximum == 0:
            maximum = len(oneLine)

        if default == 0:
            indentString = ''
        else:
            indentString = ' ' * default

        for item in bt:
            # remove redundant symbols #
            if prevSym == item[1] and prevFile == item[2]:
                cnt += 1
                continue
            else:
                prevSym = item[1]
                prevFile = item[2]

            # check redundant symbols #
            if cnt > 0:
                cntStr = ' * %s' % (cnt+1)
                cnt = 0
            else:
                cntStr = ''

            # build a new string #
            newString = ' <- %s[%s]%s' % (item[1], item[2], cntStr)
            if len(newString) + pos > maximum:
                newString = '\n%s%s' % (indentString, newString)
                pos = default + len(newString)
            else:
                pos += len(newString)

            # add a symbol to backtrace #
            btString = '%s%s' % (btString, newString)

        if btString == '':
            self.btStr = '??'
        else:
            self.btStr = btString

        return self.btStr



    def checkInterval(self):
        # continue target thread #
        if self.cont(check=True) < 0:
            sys.exit(0)

        # wait for sampling time #
        time.sleep(self.sampleTime)

        # check run status #
        self.runStatus = self.isInRun()

        # stop target thread #
        if self.stop() < 0:
            sys.exit(0)



    def getBacktrace(self, limit=32, cur=False):
        try:
            if not self.btList:
                self.btList = self.backtrace[SysMgr.arch](limit, cur)

            return self.btList
        except SystemExit:
            sys.exit(0)
        except:
            return None



    def getBacktrace_X86(self, limit=32, cur=False):
        nextFp = self.fp
        btList = []
        wordSize = ConfigMgr.wordSize

        if cur and self.pc:
            btList.insert(0, self.pc)

        while 1:
            if not nextFp or \
                nextFp < self.sp:
                break

            # check max length #
            if len(btList) >= limit:
                break

            try:
                # read return address #
                targetAddr = nextFp + wordSize
                if targetAddr % wordSize == 0:
                    value = self.accessMem(self.peekIdx, targetAddr)
                else:
                    value = self.readMem(targetAddr, retWord=True)

                # add call address #
                if value > 0:
                    try:
                        btList.append(long(value))
                    except SystemExit:
                        sys.exit(0)
                    except:
                        pass

                # read next FP #
                if nextFp % wordSize == 0:
                    nextFp = self.accessMem(self.peekIdx, nextFp)
                else:
                    nextFp = self.readMem(nextFp, retWord=True)

                if nextFp <= 0:
                    break
            except SystemExit:
                sys.exit(0)
            except:
                break

        return self.convertAddrList(btList)



    def getBacktrace_ARM(self, limit=32, cur=False):
        nextFp = self.fp
        nextLr = self.lr
        wordSize = ConfigMgr.wordSize

        if nextLr:
            btList = [nextLr]
        else:
            btList = []

        if cur and self.pc:
            btList.insert(0, self.pc)

        savedLr = nextLr

        while 1:
            if not nextLr or \
                not nextFp or \
                nextLr & 0x1:
                break

            # check max length #
            if len(btList) >= limit:
                break

            # get FP and LR #
            try:
                nextAddr = nextFp + wordSize

                if nextAddr % wordSize == 0:
                    nextLr = self.accessMem(self.peekIdx, nextAddr)
                else:
                    nextLr = self.readMem(nextAddr, retWord=True)

                if nextFp % wordSize == 0:
                    nextFp = self.accessMem(self.peekIdx, nextFp)
                else:
                    nextFp = self.readMem(nextFp, retWord=True)

                if nextFp <= 0:
                    break
            except SystemExit:
                sys.exit(0)
            except:
                break

            # add address to list #
            if nextLr and savedLr != nextLr:
                btList.append(nextLr)
                savedLr = nextLr

        return self.convertAddrList(btList)



    def getBacktrace_AARCH64(self, limit=32, cur=False):
        nextFp = self.fp
        nextLr = self.lr
        btList = [nextLr]
        wordSize = ConfigMgr.wordSize

        if cur:
            btList.insert(0, self.pc)

        savedLr = nextLr

        while 1:
            if not nextLr or \
                not nextFp or \
                nextLr & 0x1:
                break

            # check max length #
            if len(btList) >= limit:
                break

            # get FP and LR #
            try:
                nextAddr = nextFp + wordSize

                if nextAddr % wordSize == 0:
                    nextLr = self.accessMem(self.peekIdx, nextAddr)
                else:
                    nextLr = self.readMem(nextAddr, retWord=True)

                if nextFp % wordSize == 0:
                    nextFp = self.accessMem(self.peekIdx, nextFp)
                else:
                    nextFp = self.readMem(nextFp, retWord=True)

                if nextFp <= 0:
                    break
            except SystemExit:
                sys.exit(0)
            except:
                break

            # add address to list #
            if savedLr != nextLr:
                btList.append(nextLr)
                savedLr = nextLr

        return self.convertAddrList(btList)



    def convertAddrList(self, btList):
        # get symbol and file from address #
        clist = []
        for addr in btList:
            res = self.getSymbolInfo(addr)
            if res:
                clist.append([addr, res[0], res[1]])
            else:
                clist.append([addr, '??', '??'])

        return clist



    def addStat(self, sym):
        # apply stat #
        try:
            prev, ttotal, tmin, tmax = self.breakcallTimeStat[sym]

            tdiff = self.current - prev

            ttotal += tdiff

            if tmax < tdiff:
                tmax = tdiff

            if tmin == 0 or \
                tmin > tdiff:
                tmin = tdiff

            self.breakcallTimeStat[sym] = \
                [self.current, ttotal, tmin, tmax]
        except SystemExit:
            sys.exit(0)
        except:
            self.breakcallTimeStat[sym] = [self.current, 0, 0, 0]



    def getBacktraceTree(self, diffstr, tinfo, cont=True):
        backtrace = self.getBacktrace()
        depth = len(backtrace)
        diffindent = ' ' * len(diffstr)
        tinfoindent = ' ' * len(tinfo)

        # check contiguous tree presentation #
        if cont:
            commonPos = -1
            if len(self.targetBpList) == 0:
                for item in reversed(self.prevStack):
                    try:
                        if item == backtrace[commonPos]:
                            commonPos -= 1
                            continue
                        break
                    except:
                        break
        else:
            commonPos = -1

        if commonPos == -1:
            commonPos = 0
            stack = backtrace
        else:
            stack = backtrace[:commonPos]

        self.prevStack = backtrace

        btString = ''
        for sidx, item in enumerate(reversed(stack)):
            btString += '\n%s %s%s%s/%s [%s]' % \
                (diffindent, tinfoindent, \
                    (sidx-(commonPos)) * '  ', \
                    item[1], hex(item[0]).rstrip('L'), item[2])
        return btString, depth



    def runExecMode(self):
        # get register set of target #
        if not self.updateRegs():
            sys.exit(0)

        # print context #
        self.printContext(newline=True)

        # read args #
        args = self.readArgs()

        # execute remote commands #
        for cmd in SysMgr.customCmd:
            if cmd:
                self.executeCmd([cmd], None, args=args)



    def handleBreakpoint(self, printStat=False, checkArg=None):
        # get register set of target #
        if not self.updateRegs():
            sys.exit(0)

        # set rewind address #
        origPC = self.pc
        addr = self.pc - self.prevInstOffset
        origAddr = addr

        # get breakpoint addr #
        if addr not in self.bpList:
            # handle strange instructions #
            if addr+1 in self.bpList:
                addr += 1
            elif addr-1 in self.bpList:
                addr -= 1
            else:
                if self.loadSymbols():
                    self.updateBpList(verb=False)

            '''
            # toDo: update breakpoint list including original data
                    through shared memory of the process mapped new files
            '''

            # check memory map again #
            if addr not in self.bpList:
                SysMgr.printErr(\
                    "Fail to get address %s in breakpoint list of %s(%s)" % \
                        (hex(origAddr).rstrip('L'), self.comm, self.pid))

                sys.exit(0)

        # pick breakpoint info #
        sym = self.bpList[addr]['symbol']
        fname = self.bpList[addr]['filename']

        # update memory map and load new objects #
        if self.needMapScan or \
            (not self.libcLoaded and sym.startswith('__libc_')):
            if self.loadSymbols():
                self.updateBpList(verb=False)
            self.needMapScan = False

        # check memory map calls #
        if sym.startswith('mmap') and self.readArgs()[4] > 0:
            self.needMapScan = True
        elif sym.startswith('munmap'):
            unmapAddr = self.readArgs()[0]
            self.removeBpFileByAddr(unmapAddr)
            self.needMapScan = True

        # update comm #
        if self.needUpdateComm():
            comm = SysMgr.getComm(self.pid, cache=True)
            if self.comm != comm:
                self.comm = comm
                Debugger.updateCommFlag(False)

        # check comm change calls #
        if sym == 'pthread_setname_np':
            Debugger.updateCommFlag()
        elif sym == 'prctl':
            param = self.readArgs()[0]
            if param in ConfigMgr.PRCTL_TYPE and \
                ConfigMgr.PRCTL_TYPE[param] == "PR_SET_NAME":
                Debugger.updateCommFlag()

        # print context info #
        if printStat and not addr in self.exceptBpList and \
            (not self.targetBpFileList or fname in self.targetBpFileList):
            # read args #
            args = self.readArgs()

            # check filter #
            filterCmd = self.bpList[addr]['filter']
            if self.checkFilterCond(filterCmd, args):
                # build arguments string #
                argstr = '(%s)' % ','.join(list(map(hex, args)))

                # top mode #
                if self.isRealtime:
                    if SysMgr.funcDepth > 0:
                        backtrace = self.getBacktrace(cur=True)
                    else:
                        backtrace = None

                    self.addSample(\
                        sym, fname, realtime=True, bt=backtrace)

                    self.addStat(sym)
                # trace mode #
                else:
                    if self.multi:
                        tinfo = '%s(%s) ' % (self.comm, self.pid)
                    else:
                        tinfo = ''

                    # get diff time #
                    diffstr = '%3.6f' % (self.current - self.start)

                    # build backtrace string #
                    if SysMgr.funcDepth > 0:
                        if SysMgr.showAll:
                            cont = False
                        else:
                            cont = True
                        btstr, depth = \
                            self.getBacktraceTree(diffstr, tinfo, cont)
                        indent = '  ' * depth
                    else:
                        btstr = indent = ''

                    # build current symbol string #
                    callString = '\n%s %s%s%s/%s%s [%s]' % \
                        (diffstr, tinfo, indent, sym, \
                            hex(addr).rstrip('L'), argstr, fname)

                    # file output #
                    if SysMgr.printFile:
                        self.addSample(sym, fname)

                        # print history #
                        if SysMgr.showAll:
                            if btstr:
                                callString = '%s%s' % (btstr, callString)
                            self.callPrint.append(callString)
                    # console output #
                    else:
                        # print string #
                        if btstr:
                            SysMgr.printPipe(btstr, newline=False)
                        SysMgr.printPipe(callString, newline=False)

                    # check command #
                    cmd = self.bpList[addr]['cmd']
                    if cmd:
                        self.bpList[addr]['cmd'] = \
                            self.executeCmd(cmd, sym, args=args)

        # apply register set to rewind IP #
        if self.pc == origPC:
            self.setPC(addr)
            self.setRegs()

        # lock between processes #
        nrLock = self.bpList[addr]['number']
        self.lock(nrLock)

        # remove breakpoint #
        ret = self.removeBreakpoint(addr)
        if ret is None:
            self.unlock(nrLock)
            return

        # pick breakpoint info #
        sym, fname, reins = ret

        # check reinstall option #
        if not reins:
            self.unlock(nrLock)
            return

        if self.pc == origPC:
            # continue processing an instruction #
            if self.arch == 'arm':
                # PTRACE_SINGLESTEP is removed on ARM #
                self.cont()
                self.stop()
            else:
                ret = self.ptrace(self.singlestepCmd)
                if ret != 0:
                    SysMgr.printErr(\
                        'Fail to continue %s(%s) to reinstall a breakpoint' % \
                            (self.comm, self.pid))
                    sys.exit(0)

            # check process #
            ret = self.waitpid()
            stat = self.getStatus(ret[1])
            if SysMgr.isTermSignal(stat) or stat == -1:
                SysMgr.printErr(\
                    'Fail to wait for %s(%s) to reinstall a breakpoint' % \
                        (self.comm, self.pid))
                sys.exit(0)

        # register this breakpoint again #
        ret = self.injectBreakpoint(\
            addr, sym, fname=fname, reins=reins)
        if not ret:
            SysMgr.printWarn(\
                "Fail to inject breakpoint to %s(%s) for %s(%s)" % \
                    (sym, addr, self.comm, self.pid))
            sys.exit(0)

        # unlock between processes #
        self.unlock(nrLock)



    def handleTrapEvent(self, stat):
        previous = self.status
        self.status = self.mode

        # interprete user function call #
        if self.mode == 'inst' or self.mode =='sample':
            self.handleUsercall()
        elif self.mode == 'break':
            # block signal #
            SysMgr.blockSignal(signal.SIGINT, act='block')

            try:
                self.handleBreakpoint(printStat=SysMgr.printEnable)
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printWarn(\
                    "Fail to handle a breakpoint", True, reason=True)

            if self.cont(check=True) < 0:
                sys.exit(0)

            # unblock signal #
            SysMgr.blockSignal(signal.SIGINT, act='unblock')

        self.status = previous



    def handleSignal(self, sig):
        if not SysMgr.printEnable:
            return

        # check signal filter #
        if SysMgr.customCmd:
            found = False
            for signame in SysMgr.customCmd:
                if signame.upper() == ConfigMgr.SIG_LIST[sig]:
                    found = True
                    break
            if not found:
                return

        # get diff time #
        diff = self.current - self.start

        if self.multi:
            tinfo = '%s(%s) ' % (self.comm, self.pid)
        else:
            tinfo = ''

        try:
            signame = ConfigMgr.SIG_LIST[sig]
        except:
            signame = 'UNKNOWN(%s)' % sig

        callString = '\n%3.6f %s[%s]' % \
            (diff, tinfo, signame)

        SysMgr.printPipe(callString)

        # print backtrace #
        if not self.isRealtime and SysMgr.funcDepth > 0:
            # get register set of target #
            if not self.updateRegs():
                sys.exit(0)

            self.printContext(regs=False)



    def handleUsercall(self):
        # get register set of target #
        if not self.updateRegs():
            sys.exit(0)

        # check previous function boundary #
        if self.prevCallInfo:
            if (not self.isRealtime and \
                self.pc >= self.prevCallInfo[2] and \
                self.pc <= self.prevCallInfo[3]) or \
                (self.isRealtime and \
                    self.pc == self.prevCallInfo[5]):

                # add sample #
                if self.isRealtime:
                    self.addSample(\
                        self.prevCallInfo[0], self.prevCallInfo[1], \
                        realtime=True, bt=self.prevCallInfo[4])
                elif SysMgr.printFile:
                    self.addSample(\
                        self.prevCallInfo[0], self.prevCallInfo[1])

                return

        # get symbol info #
        ret = self.getSymbolInfo(self.pc)
        if type(ret) is list:
            sym, fname, offset, fstart, fend = ret
        else:
            sym = ret
            fname = '??'
            offset = '??'
            fstart = '??'
            fend = '??'

        # get backtrace #
        if self.isRealtime and \
            SysMgr.funcDepth > 0:
            backtrace = self.getBacktrace(SysMgr.funcDepth)
        else:
            backtrace = None

        # print unknown call address #
        if fname == '??':
            if self.isRealtime:
                self.addSample('??', fname, realtime=True, bt=backtrace)
            elif SysMgr.printFile:
                self.addSample('??', fname, bt=backtrace)
            return

        # check contiguous unknown symbol #
        if sym == '??' and self.prevCallInfo:
            if self.prevCallInfo[0] == sym:
                return
            elif self.prevCallInfo[0].startswith('mmap'):
                # enable memory update flag #
                self.needMapScan = True

        # update callstack #
        if self.isRealtime:
            direction = ''
            symstr = sym

            # save current call info as previous call #
            self.prevCallInfo = [sym, fname, 0, 0, backtrace, self.pc]

            self.addSample(sym, fname, realtime=True, bt=backtrace)
        else:
            # get filter addr #
            try:
                # symbol range #
                if sym != '??':
                    vstart, vend = self.getVrangeBySymbol(sym, fname)
                # anon range #
                else:
                    vstart, vend = self.getAnonVrangeByOffset(offset, fname)
            except SystemExit:
                sys.exit(0)
            except:
                vstart = vend = long(0)

            # save current call info as previous call #
            self.prevCallInfo = [sym, fname, vstart, vend, backtrace, self.pc]

            self.updateCallstack(sym)

            # check call relationship #
            if not self.sp or not self.prevSp:
                direction = '(??)'

                self.addCall(sym)
            elif sym == 'PLT':
                direction = '(--)'

                self.addCall(sym)
            elif self.sp > self.prevSp:
                direction = '(<-)'
            else:
                direction = '(->)'

                self.addCall(sym)

            symstr = '%s%s' % (' ' * 4 * len(self.callstack), sym)

            # get time diff #
            diff = self.current - self.start

            # build call string #
            callString = '%3.6f %s %s [%s + %s] [%s]' % \
                (diff, symstr , direction, fname, \
                    offset, hex(self.sp).rstrip('L'))

            # backup callString #
            self.prevCallString = callString

            if SysMgr.printFile:
                self.addSample(sym, fname)

                if SysMgr.showAll:
                    self.callPrint.append(callString)
            else:
                SysMgr.printPipe(\
                    '\n%s' % callString, newline=False, flush=True)

        # backup register #
        self.prevSp = self.sp

        # check symbol #
        if SysMgr.customCmd:
            onlySym = sym.split('@')[0]
            self.checkSymbol(onlySym)



    def getArgs(self, ref=True):
        proto = ConfigMgr.SYSCALL_PROTOTYPES

        # get argument values from register #
        regstr = self.readArgs()

        # get data types #
        self.rettype, formats = proto[self.syscall]

        # get values #
        self.values = \
            [value for value, format in zip(regstr, formats)]

        seq = long(0)
        argset = {}
        for value, format in zip(regstr, formats):
            # get type and name of a argument #
            argtype, argname = format
            argset[argname] = value

            # convert argument value #
            value = self.convertValue(argtype, argname, value, seq, ref, argset)
            if value is not None:
                self.addArg(argtype, argname, value)

            seq += 1



    def convArgs(self):
        args = []

        # converting arguments #
        self.getArgs()

        # pick values from argument list #
        for idx, arg in enumerate(self.args):
            if arg[0].endswith('*'):
                # convert pointer to values #
                if UtilMgr.isString(arg[2]):
                    text = UtilMgr.decodeArg(arg[2])

                    # check output length #
                    if not (SysMgr.printFile or SysMgr.showAll) and \
                        len(text) > self.pbufsize:
                        text = r'"%s..."' % text[:self.pbufsize]
                    else:
                        text = r'"%s"' % text[:-1]
                else:
                    text = arg[2]
            elif arg[0].endswith('int') or arg[0].endswith('long'):
                try:
                    text = long(arg[2])
                except:
                    text = arg[2]
            else:
                text = arg[2]

            # append an arg to list #
            args.append(text)

        return args



    def isDeferrableCall(self, name):
        if name == 'read' or \
            name == 'recvmsg' or \
            name == 'recvmmsg' or \
            name == 'recv' or \
            name == 'readv' or \
            name == 'readlink' or \
            name == 'recvfrom' or \
            name == 'clock_gettime' or \
            name == 'getgroups' or \
            name == 'getgroups16' or \
            name == 'gethostname' or \
            name == 'getitimer' or \
            name == 'getpeername' or \
            name == 'gettimeofday' or \
            name == 'getsockname' or \
            name == 'process_vm_readv':
            return True
        else:
            return False



    def handleSyscallOutput(self, args, deferrable=False):
        # get diff time #
        diff = self.current - self.start

        # get backtrace #
        if SysMgr.funcDepth > 0:
            backtrace = self.getBacktrace(SysMgr.funcDepth, cur=True)
            bts = '\n%s%s ' % \
                (' ' * 20, self.getBacktraceString(backtrace, default=20))
        else:
            backtrace = None
            bts = ''

        # print context in JSON format #
        if SysMgr.jsonOutputEnable:
            jsonData = {
                "type": "enter",
                "time": self.current,
                "timediff": diff,
                "name": self.syscall,
                "tid": self.pid,
                "comm": self.comm,
                "backtrace": bts,
                "args": dict(),
            }

            # marshaling args #
            for idx, arg in enumerate(self.args):
                if len(args) > 0:
                    jsonData['args'][arg[1]] = args[idx]
                else:
                    jsonData['args'][arg[1]] = arg[2]

            try:
                SysMgr.printPipe(\
                    str(UtilMgr.convDict2Str(jsonData, pretty=False)))
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "Fail to convert %s to JSON for marshalling" % [jsonData], True)
            return

        if not self.isRealtime or SysMgr.showAll:
            # convert args to string ##
            if len(args) > 0:
                argText = ', '.join(str(arg) for arg in args)
            else:
                argText = ', '.join(str(arg[2]) for arg in self.args)

            # build call string #
            if deferrable:
                callString = '%s) %s' % (argText, bts)
            else:
                callString = \
                    '%3.6f %s(%s) %s(%s) %s' % \
                        (diff, self.comm, self.pid, self.syscall, argText, bts)

        # print call info #
        if self.isRealtime:
            self.addSample(\
                self.syscall, '??', realtime=True, bt=backtrace)
        elif SysMgr.printFile:
            self.addSample(self.syscall, '??', bt=backtrace)
        else:
            ttyColsOrig = SysMgr.ttyCols

            if SysMgr.showAll or SysMgr.funcDepth > 0:
                SysMgr.ttyCols = long(0)
            else:
                callString = '%s ' % callString[:self.pbufsize]

            if deferrable:
                prefix = ''
            else:
                prefix = '\n'

            SysMgr.printPipe(\
                '%s%s' % (prefix, callString), newline=False, flush=True)

            SysMgr.ttyCols = ttyColsOrig

        # print call history #
        if SysMgr.showAll and SysMgr.printFile:
            if deferrable:
                callString = '%s%s' % (self.bufferedStr, callString)
            self.callPrint.append(callString)

        # check symbol #
        if SysMgr.customCmd:
            self.checkSymbol(self.syscall, newline=True, bt=backtrace)



    def handleDefSyscall(self):
        self.status = 'exit'

        if self.getRegs(temp=True) != 0:
            sys.exit(0)

        # set return value from register #
        args = []
        retval = self.getRetVal(temp=True)
        if retval < 0:
            # get arguments from previous register set #
            self.getArgs(ref=False)
        else:
            args = self.convArgs()

        self.handleSyscallOutput(args, deferrable=True)



    def handleSyscall(self):
        # skip useless return processing #
        if self.status == 'skip':
            self.status = 'enter'
            return

        # check deferrable #
        if self.status == 'deferrable':
            self.handleDefSyscall()

        # ignore return #
        if SysMgr.optStrace and self.status == 'exit':
            self.status = 'enter'
            self.clearArgs()
            return

        # get register set #
        if not self.updateRegs():
            sys.exit(0)

        # get syscall number #
        nrSyscall = self.getNrSyscall()

        # check syscall condition #
        if len(SysMgr.syscallList) > 0 and \
            not nrSyscall in SysMgr.syscallList:
            #self.cmd = self.sysemuCmd
            self.status = 'skip'
            return

        try:
            proto = ConfigMgr.SYSCALL_PROTOTYPES
            self.syscall = name = ConfigMgr.sysList[nrSyscall][4:]
        except:
            return

        # get diff time #
        diff = self.current - self.start

        # enter #
        if self.status == 'enter':
            # set next status #
            self.status = 'exit'

            # check wait condition #
            if self.wait:
                return

            # check prototype #
            if name not in proto:
                SysMgr.printWarn(\
                    "Fail to get args info of %s" % name, True)
                return

            args = []

            # convert args except for top mode #
            if self.isRealtime:
                self.syscallTime[name] = self.current
            else:
                if self.isDeferrableCall(name):
                    self.status = 'deferrable'

                    if SysMgr.jsonOutputEnable:
                        return

                    # build call string #
                    callString = '%3.6f %s(%s) %s(' % \
                        (diff, self.comm, self.pid, name)

                    if SysMgr.printFile:
                        self.bufferedStr = callString
                    else:
                        SysMgr.printPipe(\
                            '\n%s' % callString, newline=False, flush=True)

                    return

                args = self.convArgs()

            self.handleSyscallOutput(args)

            # check syscall condition #
            if len(SysMgr.syscallList) > 0:
                self.clearArgs()

            return

        # exit #
        elif self.status == 'exit':
            # set next status #
            self.status = 'enter'

            # get diff time #
            if self.isRealtime:
                # get diff #
                try:
                    diff = self.current - self.syscallTime[name]
                except:
                    diff = long(0)

                # apply diff #
                try:
                    ttotal, tmax = self.syscallTimeStat[name]
                    ttotal += diff

                    if tmax < diff:
                        tmax = diff

                    self.syscallTimeStat[name] = [ttotal, tmax]
                except SystemExit:
                    sys.exit(0)
                except:
                    self.syscallTimeStat[name] = [diff, diff]

            # set return value from register #
            retval = self.getRetVal()

            # check wait condition #
            if self.wait:
                if self.wait == name and \
                    retval == 0:
                    # unset wait condition #
                    self.wait = None
                return

            # convert error code #
            if retval < 0:
                try:
                    err = '%s (%s)' % \
                        (ConfigMgr.ERR_TYPE[abs(retval+1)], \
                            os.strerror(abs(retval)))

                    self.addSample(name, '??', err=retval)
                except SystemExit:
                    sys.exit(0)
                except:
                    err = ''
            else:
                err = ''

            # convert type #
            try:
                rtype = proto[name][0]
                if '*' in rtype:
                    retval = '0x%s' % long(str(retval), 16)
            except SystemExit:
                sys.exit(0)
            except:
                pass

            # print context in JSON format #
            if SysMgr.jsonOutputEnable:
                jsonData = {
                    "type": "exit",
                    "time": self.current,
                    "timediff": diff,
                    "name": name,
                    "tid": self.pid,
                    "comm": self.comm,
                    "backtrace": self.prevBtStr,
                    "ret": str(retval),
                    "err": err,
                }

                SysMgr.printPipe(\
                    str(UtilMgr.convDict2Str(jsonData, pretty=False)))

                self.clearArgs()

                return

            # build call string #
            callString = '= %s %s' % (retval, err)

            if SysMgr.printFile:
                if SysMgr.showAll and \
                    len(self.callPrint) > 0:
                    self.callPrint[-1] = '%s%s' % \
                        (self.callPrint[-1], callString)
            elif self.isRealtime:
                pass
            else:
                SysMgr.printPipe(callString, newline=False, flush=True)

            self.clearArgs()

        else:
            SysMgr.printErr(\
                'Fail to recognize syscall status')



    def getStatList(self, retstr=False, status=False):
        try:
            self.statFd.seek(0)
            stat = self.statFd.readlines()[0]
        except SystemExit:
            sys.exit(0)
        except:
            try:
                statPath = "%s/%s/task/%s/stat" % \
                    (SysMgr.procPath, self.pid, self.pid)
                self.statFd = open(statPath, 'r')
                stat = self.statFd.readlines()[0]
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printOpenWarn(statPath)
                return None

        if retstr:
            return stat

        try:
            if status:
                return stat.split(') ', 1)[1][0]
            else:
                return stat.split(')')[1].split()
        except SystemExit:
            sys.exit(0)
        except:
            return None



    def isAlive(self):
        stat = self.getStatList(status=True)
        if not stat:
            return None

        if stat == 'Z':
            return False
        else:
            return True



    def isStopped(self):
        stat = self.getStatList(status=True)
        if not stat:
            return None

        # check status #
        if stat == 'T' or stat =='t':
            return True
        else:
            return False



    def isInRun(self):
        stat = self.getStatList(status=True)
        if not stat:
            return None

        # check status #
        if stat == 'R' or stat == 't':
            return True
        else:
            return False



    def getCpuUsage(self):
        stat = self.getStatList(retstr=True)
        if not stat:
            SysMgr.printWarn(\
                "Fail to get CPU usage for %s(%s)" % \
                    (self.comm, self.pid))
            return [0, 0, 0]

        # check stat change #
        if self.prevStat == stat:
            return [0, 0, 0]

        self.prevStat = stat

        # convert string to list #
        statList = stat.split(')')[1].split()

        # get total CPU time #
        utime = long(statList[self.utimeIdx-2])
        stime = long(statList[self.stimeIdx-2])
        ttime = utime + stime

        prevUsage = self.prevCpuStat

        if self.prevCpuStat == None:
            ret = [0, 0, 0]
        else:
            ret = [ttime - prevUsage[0],
                utime - prevUsage[1],
                stime - prevUsage[2]]

        self.prevCpuStat = [ttime, utime, stime]

        return ret



    def printSymbolList(self, slist):
        if not slist or \
            not SysMgr.warnEnable:
            return

        string = ['%s(%s/%s)' % \
            (item[1], item[2], hex(item[0]).rstrip('L')) for item in slist]

        SysMgr.printWarn(\
            "Found multiple symbols [ %s ]" % ', '.join(string))



    def getAddrBySymbol(\
        self, symbol, binary=None, inc=False, start=False, end=False, one=False):
        # check memory map #
        if not self.pmap:
            self.loadSymbols()

        addrList = []
        addrDict = {}

        for mfile in list(self.pmap.keys()):
            if binary and not mfile in binary:
                continue

            fcache = ElfAnalyzer.getObject(mfile)
            if fcache:
                offset = fcache.getOffsetBySymbol(\
                    symbol, inc=inc, start=start, end=end)
                if type(offset) is str:
                    offset = long(offset, 16)

                    if ElfAnalyzer.isRelocFile(mfile):
                        if offset in addrDict:
                            continue
                        addrList.append(\
                            [self.pmap[mfile]['vstart']+offset, symbol, mfile])
                    else:
                        if offset in addrDict:
                            continue
                        addrList.append([offset, symbol, mfile])

                    addrDict[offset] = True
                    continue
                elif type(offset) is not list:
                    continue

                for item in offset:
                    sym = item[0]
                    offset = long(item[1], 16)
                    if ElfAnalyzer.isRelocFile(mfile):
                        if offset in addrDict:
                            continue

                        addrList.append(\
                            [self.pmap[mfile]['vstart']+offset, sym, mfile])
                    else:
                        if offset in addrDict:
                            continue

                        addrList.append([offset, sym, mfile])

                    addrDict[offset] = True

        # return address #
        if len(addrList) == 0:
            return None
        elif len(addrList) > 1:
            self.printSymbolList(addrList)

        # return address for 1st item #
        if one:
            if addrList:
                return addrList[0][0]
            else:
                SysMgr.printErr(\
                    "Fail to find %s symbol for %s(%s)" % \
                        (symbol, self.comm, self.pid))
                return None

        return addrList



    def lock(self, pos=-1):
        if self.lockObj:
            if pos > -1:
                lockf(self.lockObj, LOCK_EX, 1, pos, 0) # pylint: disable=undefined-variable
            else:
                lockf(self.lockObj, LOCK_EX) # pylint: disable=undefined-variable

            return True
        else:
            return False



    def unlock(self, pos=-1):
        if self.lockObj:
            if pos > -1:
                lockf(self.lockObj, LOCK_UN, 1, pos, 0) # pylint: disable=undefined-variable
            else:
                lockf(self.lockObj, LOCK_UN) # pylint: disable=undefined-variable

            return True
        else:
            return False



    def handoverNewTarget(self):
        # get tid of new task #
        tid = self.getEventMsg()

        if self.mode == 'break':
            # check lock #
            if not self.lockObj:
                self.lockObj = \
                    Debugger.getGlobalLock(self.pid, len(self.bpList))

            # stop the target #
            self.stop()

        if SysMgr.masterPid == 0:
            chMid = True
        else:
            chMid = False

        # create a new process to trace a new task #
        pid = SysMgr.createProcess(isDaemon=True, chMid=chMid)
        # original tracee #
        if pid > 0:
            self.detach(only=True)
            self.detach(only=True, pid=tid)
            self.attach()
        # new tracee #
        elif pid == 0:
            self.pid = tid
            self.attach()
            self.initValues()
            signal.alarm(SysMgr.intervalEnable)
        else:
            return

        # set trace event #
        self.ptraceEvent(self.traceEventList)

        # set attributes for multiprocess #
        self.multi = True
        if not SysMgr.printFile:
            SysMgr.printStreamEnable = True



    def initValues(self):
        # default info #
        self.traceEventList = [\
            'PTRACE_O_TRACESYSGOOD',\
            'PTRACE_O_TRACECLONE',
            'PTRACE_O_TRACEFORK',
            'PTRACE_O_TRACEVFORK',
        ]

        # stat variables #
        self.comm = SysMgr.getComm(self.pid, cache=True)
        self.start = self.last = time.time()
        self.statFd = None
        self.prevStat = None
        self.prevCpuStat = None
        self.arch = SysMgr.getArch()
        self.sysreg = ConfigMgr.SYSREG_LIST[self.arch]
        self.retreg = ConfigMgr.RET_LIST[self.arch]
        self.commIdx = ConfigMgr.STAT_ATTR.index("COMM")
        self.utimeIdx = ConfigMgr.STAT_ATTR.index("UTIME")
        self.stimeIdx = ConfigMgr.STAT_ATTR.index("STIME")

        # register variables #
        self.pc = None
        self.lr = None
        self.sp = None
        self.fp = None
        self.prevCallInfo = None
        self.prevSp = None
        self.prevDepth = 0

        # call variables #
        self.prevCallString = ''
        self.stack = list()
        self.prevStack = list()
        self.childList = list()
        self.callList = list()
        self.callPrint = list()
        self.cpuUsageList = list()
        self.syscallTime = dict()
        self.syscallTimeStat = dict()
        self.breakcallTimeStat = dict()
        self.retList = dict()
        self.prevReturn = -1



    def runEventLoop(self):
        # enter trace loop #
        while 1:
            # save backtrace info #
            self.prevBtList = self.btList
            self.prevBtStr = self.btStr
            self.btList = self.btStr = None

            # set status #
            if self.status == 'stop':
                self.status = 'enter'
            elif self.status == 'ready':
                pass
            else:
                # wait for sample calls #
                if self.mode == 'sample':
                    self.checkInterval()
                elif self.mode == 'break' or \
                    self.mode == 'signal':
                    pass
                # skip instructions for performance #
                elif self.mode == 'inst' and self.skipInst > 0:
                    for i in range(0, self.skipInst):
                        self.ptrace(self.cmd)
                # setup trap #
                else:
                    self.ptrace(self.cmd)

            try:
                # wait process #
                rid, ostat = self.waitpid()

                # update time #
                self.current = time.time()

                if not SysMgr.optStrace:
                    # handle clone event #
                    if self.isCloned(ostat):
                        self.handoverNewTarget()
                        continue

                    # handle fork event #
                    if self.isForked(ostat):
                        if self.mode == 'syscall':
                            self.handoverNewTarget()
                        continue

                # get status of process #
                stat = self.getStatus(ostat)

                # handle signal #
                if self.mode == 'signal':
                    self.handleSignal(stat)

                    self.cont(sig=stat)
                    if self.cont(check=True, sig=stat) < 0:
                        sys.exit(0)
                    continue

                # trap #
                if stat == signal.SIGTRAP:
                    # after execve() #
                    if self.status == 'ready':
                        self.initValues()

                        self.ptraceEvent(self.traceEventList)

                        if self.cmd:
                            self.ptrace(self.cmd)

                        self.status = 'enter'

                        if self.mode == 'break':
                            # load symbols again #
                            if self.loadSymbols():
                                self.updateBpList()

                            if self.cont(check=True) < 0:
                                sys.exit(0)

                        continue

                    # usercall / breakcall #
                    elif self.mode == 'break' or self.mode == 'inst':
                        self.handleTrapEvent(ostat)

                # breakpoint event for ARM #
                elif stat == signal.SIGILL and \
                    self.mode == 'break':
                    self.handleTrapEvent(ostat)

                # syscall #
                elif stat == signal.SIGTRAP | 0x80:
                    # filter syscall #
                    if self.mode != 'syscall':
                        continue

                    # interprete syscall context #
                    self.handleSyscall()

                # stop signal #
                elif stat == signal.SIGSTOP:
                    if self.mode == 'sample':
                        self.handleTrapEvent(ostat)
                        continue

                    self.status = 'stop'
                    SysMgr.printWarn(\
                        'Blocked %s(%s) because of %s' % \
                        (self.comm, self.pid, ConfigMgr.SIG_LIST[stat]))

                    if self.mode == 'break':
                        if self.cont(check=True) < 0:
                            sys.exit(0)
                        continue

                    # set up trap again #
                    if self.mode == 'syscall':
                        self.ptraceEvent(['PTRACE_O_TRACESYSGOOD'])

                        self.ptrace(self.cmd)

                    continue

                # kill / segv signal #
                elif SysMgr.isTermSignal(stat):
                    # print context info #
                    self.printContext()

                    SysMgr.printErr(\
                        'Terminated %s(%s) because of %s' % \
                            (self.comm, self.pid, ConfigMgr.SIG_LIST[stat]))

                    if SysMgr.isTopMode():
                        SysMgr.waitEvent()

                    sys.exit(0)

                # exit #
                elif stat == -1:
                    if self.status == 'exit':
                        SysMgr.printPipe(' ')

                    SysMgr.printErr(\
                        'Terminated %s(%s)' % (self.comm, self.pid))

                    if SysMgr.isTopMode() and self.totalCall:
                        SysMgr.waitEvent()

                    sys.exit(0)

                # other #
                else:
                    SysMgr.printWarn(\
                        'Detected %s(%s) with %s' % \
                        (self.comm, self.pid, ConfigMgr.SIG_LIST[stat]))

                    if self.mode == 'sample':
                        self.handleTrapEvent(ostat)

                    # continue target from signal stop #
                    if self.mode != 'syscall':
                        if self.cont(check=True, sig=stat) < 0:
                            sys.exit(0)
            except SystemExit:
                return
            except:
                if self.isAlive():
                    SysMgr.printWarn(\
                        'Detected %s(%s) with error' % \
                            (self.comm, self.pid), reason=True)

                    if self.mode == 'break':
                        if self.cont(check=True) < 0:
                            sys.exit(0)

                    continue

                SysMgr.printErr(\
                    "Terminated tracing %s(%s)" % \
                        (self.comm, self.pid))

                return



    def trace(\
        self, mode='syscall', wait=None,\
            multi=False, lock=None, bpList={}, exceptBpList={},\
            targetBpList={}, targetBpFileList={}):

        # index variables #
        self.sigTrapFlag = signal.SIGTRAP | \
            ConfigMgr.PTRACE_EVENT_TYPE.index('PTRACE_EVENT_EXEC') << 8
        self.sigCloneFlag = signal.SIGTRAP | \
            ConfigMgr.PTRACE_EVENT_TYPE.index('PTRACE_EVENT_CLONE') << 8
        self.sigForkFlag = signal.SIGTRAP | \
            ConfigMgr.PTRACE_EVENT_TYPE.index('PTRACE_EVENT_FORK') << 8
        self.sigVforkFlag = signal.SIGTRAP | \
            ConfigMgr.PTRACE_EVENT_TYPE.index('PTRACE_EVENT_VFORK') << 8

        # initialize variables #
        self.initValues()

        # apply common breakpoint list #
        self.targetBpList = targetBpList
        self.targetBpFileList = targetBpFileList

        # context variables #
        self.cmd = None
        self.wait = wait
        self.mode = mode
        self.multi = multi
        self.lockObj = lock
        self.current = time.time()
        self.pbufsize = SysMgr.ttyCols >> 1

        # sampling variables #
        self.sampleTime = long(0)

        # disable extended ascii #
        SysMgr.encodeEnable = False

        # register my instance #
        SysMgr.addExitFunc(Debugger.destroyDebugger, [self])

        # check realtime mode #
        if SysMgr.isTopMode():
            self.isRealtime = True
        else:
            self.isRealtime = False

        # set tracing attribute #
        if self.isRealtime:
            # get first CPU usage #
            self.getCpuUsage()

            # set alarm handler #
            signal.signal(signal.SIGALRM, Debugger.onAlarm)

            if self.mode == 'sample':
                # set sampling rate to 100 us #
                sampleTime = SysMgr.getOption('T')
                if sampleTime:
                    try:
                        self.sampleTime = \
                            long(sampleTime) / float(1000000)
                    except:
                        SysMgr.printErr(\
                            "Fail to set sampling time", True)
                        sys.exit(0)
                else:
                    self.sampleTime = 0.0001

                if not self.multi:
                    SysMgr.printInfo(\
                        'Do sampling every %g second' % self.sampleTime)

            # set default interval #
            if not SysMgr.findOption('R') or \
                not SysMgr.intervalEnable:
                SysMgr.intervalEnable = 1
        else:
            # set timer handler #
            if SysMgr.intervalEnable:
                signal.signal(signal.SIGALRM, SysMgr.exitHandler)

            # inst #
            if SysMgr.isUtraceMode() and \
                SysMgr.funcDepth > 0:
                # set sampling rate for instruction #
                self.skipInst = SysMgr.funcDepth

                SysMgr.printInfo(\
                    'Do sampling every %s instrunctions' % \
                        UtilMgr.convNum(SysMgr.funcDepth))

        # prepare environment for the running target #
        if self.isRunning:
            # check the process is running #
            try:
                os.kill(self.pid, 0)
            except SystemExit:
                sys.exit(0)
            except:
                ereason = SysMgr.getErrMsg()
                if ereason != '0':
                    SysMgr.printErr(\
                        'Fail to trace %s(%s) because %s' % \
                            (self.comm, self.pid, ereason))
                sys.exit(0)

            # load user symbols #
            if (mode != 'syscall' and mode != 'signal') or \
                SysMgr.funcDepth > 0:
                try:
                    self.loadSymbols()
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printErr(\
                        "Fail to load symbols", True)
                    sys.exit(0)

            # print target task info #
            if SysMgr.printEnable:
                SysMgr.printInfo(\
                    "Start profiling %s(%d)" % (self.comm, self.pid))

            ret = self.ptraceEvent(self.traceEventList)

            # handle current user symbol #
            if (self.mode == 'inst' or \
                self.mode == 'sample') and \
                not SysMgr.isTopMode():
                try:
                    self.handleUsercall()
                except SystemExit:
                    sys.exit(0)
                except:
                    return
        # set trap event type for the new target #
        else:
            self.ptraceEvent(['PTRACE_O_TRACEEXEC'])
            self.status = 'ready'

        # select trap command #
        if self.mode == 'syscall':
            self.cmd = self.syscallCmd
        elif self.mode == 'inst':
            self.cmd = self.singlestepCmd
            if self.arch == 'arm':
                SysMgr.printErr(\
                    "Not supported on %s" % self.arch.upper())
                sys.exit(0)
        elif self.mode == 'sample':
            self.cmd = None
        elif self.mode == 'break':
            if self.isRunning:
                # register breakpoint data #
                self.bpList = bpList
                self.exceptBpList = exceptBpList

                # check thread status #
                stat = self.getStatList(status=True)
                if not stat:
                    SysMgr.printErr(\
                        'Terminated %s(%s)' % (self.comm, self.pid))
                elif stat == 'S':
                    SysMgr.syscall(self.tkillIdx, self.pid, signal.SIGCONT)
        elif self.mode == 'signal':
            if self.isStopped():
                if self.cont(check=True):
                    sys.exit(0)
        elif self.mode == 'remote':
            self.runExecMode()
            sys.exit(0)
        else:
            SysMgr.printErr(\
                "Fail to recognize trace mode '%s'" % self.mode)
            sys.exit(0)

        # register summary callback #
        SysMgr.addExitFunc(Debugger.printSummary, [self])

        # set timer #
        if SysMgr.printEnable:
            signal.alarm(SysMgr.intervalEnable)

        # run loop #
        self.runEventLoop()



    @staticmethod
    def destroyDebugger(instance):
        Debugger.dbgInstance = None

        # remove breakpoints #
        if not instance.isAlive() or \
            SysMgr.inputParam or \
            len(instance.bpList) == 0:
            instance.__del__()
            return

        # stop target #
        if not instance.isStopped():
            instance.stop()
            instance.waitpid()

        # get current register set #
        if instance.mode == 'break':
            # notify termination to master process #
            if SysMgr.masterPid > 0:
                os.kill(SysMgr.masterPid, signal.SIGINT)

            while 1:
                ret = instance.updateRegs()
                if not ret:
                    if not instance.isAlive():
                        return
                    time.sleep(SysMgr.waitDelay)
                    continue
                break
        else:
            ret = False

        if ret:
            addr = instance.pc - instance.prevInstOffset

            # apply register set to rewind IP #
            if addr in instance.bpList:
                instance.setPC(addr)
                instance.setRegs()

            # check main thread #
            tgid = long(SysMgr.getTgid(instance.pid))

            # define progress file path #
            progressPath = '%s/task_%s.done' % (SysMgr.cacheDirPath, tgid)

            # the thread group leader #
            if tgid == instance.pid:
                origPrintFlag = SysMgr.printEnable
                SysMgr.printEnable = True

                instance.removeAllBreakpoint(tgid)

                SysMgr.printEnable = origPrintFlag

                # remove lock file #
                try:
                    os.remove(Debugger.gLockPath)
                except:
                    pass

                # create a progress file #
                os.open(progressPath, os.O_CREAT, 0o777)
            # siblings #
            else:
                # wait for termination of tracer for main thread #
                while 1:
                    if not os.path.exists(progressPath):
                        if not SysMgr.isAlive(tgid):
                            break
                        time.sleep(0.01)
                        continue
                    break

        instance.__del__()



    @staticmethod
    def printCallHistory(instance):
        if len(instance.callPrint) == 0:
            return

        try:
            elapsed = instance.callList[-1][1] - instance.start
        except:
            elapsed = instance.last - instance.start

        nrLine = UtilMgr.convNum(len(instance.callPrint))
        callStr = '\n'.join(instance.callPrint)

        SysMgr.printPipe(\
            '\n[Trace History] [Time: %f] [Line: %s]\n%s\n%s\n%s' %
                (elapsed, nrLine, twoLine, callStr, oneLine))



    @staticmethod
    def printSummary(instance):
        def printSystemStat():
            SysMgr()
            SysMgr.sysInstance.saveSysStat()
            SysMgr.printInfoBuffer()

        # check realtime mode #
        if not SysMgr.printFile:
            return

        instance.last = time.time()

        callTable = dict()
        fileTable = dict()

        # print System Info #
        printSystemStat()

        SysMgr.printInfo(\
            "Start analyzing calls...")

        # iterate the list of call samples #
        for idx, item in enumerate(instance.callList):
            try:
                symbol, timestamp, filename = item

                # convert anonymous call to filename #
                if symbol == '??':
                    symbol = filename

                # add to symbol table #
                try:
                    callTable[symbol]['cnt'] += 1
                except:
                    callTable[symbol] = dict()
                    callTable[symbol]['cnt'] = 1
                    callTable[symbol]['path'] = filename

                UtilMgr.printProgress(idx, len(instance.callList))

                if instance.mode == 'syscall':
                    continue

                # add to file table #
                try:
                    fileTable[filename]['cnt'] += 1
                except:
                    fileTable[filename] = dict()
                    fileTable[filename]['cnt'] = 1
            except SystemExit:
                UtilMgr.deleteProgress()
                return
            except:
                pass

        UtilMgr.deleteProgress()

        # print summary table #
        if instance.mode == 'syscall':
            ctype = 'Syscall'
            addInfo = 'Count'
        elif instance.mode == 'break':
            ctype = 'Breakcall'
            addInfo = 'Path'
        else:
            ctype = 'Usercall'
            addInfo = 'Path'

        if instance.isRealtime:
            mtype = 'Top'
            suffix = '\n'
        else:
            mtype = 'Trace'
            suffix = ''

        # print call table #
        convert = UtilMgr.convNum
        nrTotal = float(len(instance.callList))
        try:
            elapsed = instance.callList[-1][1] - instance.start
        except:
            elapsed = instance.last - instance.start

        # get sample info #
        try:
            maxSample = elapsed / instance.sampleTime
            perSample = '%.1f' % (nrTotal / maxSample * 100)
        except:
            perSample = '100'

        if instance.sampleTime > 0:
            samplingStr = '[Sampling: %g] ' % instance.sampleTime
            sampleRateStr = '(%s%%)' % perSample
        else:
            samplingStr = ''
            sampleRateStr = ''

        nrCpuUsageSample = len(instance.cpuUsageList)
        if nrCpuUsageSample == 0:
            nrCpuUsageSample = 1

        # calculate average CPU usage #
        ttime = utime = stime = 0
        for cpustat in instance.cpuUsageList:
            ttime += cpustat[0]
            utime += cpustat[1]
            stime += cpustat[2]
        ttime /= float(nrCpuUsageSample)
        utime /= float(nrCpuUsageSample)
        stime /= float(nrCpuUsageSample)
        cpuStr = '%d%%(Usr:%d%%/Sys:%d%%)' % (ttime, utime, stime)

        SysMgr.printPipe((\
            '\n[%s %s Summary] [Elapsed: %g] %s[Task: %s(%s)] '
            '[NrSamples: %s%s] [NrSymbols: %s] [CPU: %s] %s') % \
                (mtype, ctype, elapsed, samplingStr, \
                instance.comm, instance.pid, \
                convert(long(nrTotal)), sampleRateStr, \
                convert(len(callTable)), cpuStr, suffix))

        SysMgr.printPipe('%s%s' % (twoLine, suffix))
        SysMgr.printPipe(\
            '{0:^7} | {1:^144}{2:1}'.format(\
                'Usage', 'Function [%s]' % addInfo, suffix))
        SysMgr.printPipe('%s%s' % (twoLine, suffix))

        cnt = long(0)
        for sym, value in sorted(\
            callTable.items(), key=lambda x:x[1]['cnt'], reverse=True):
            if sym[0] == '/':
                sym = '??'

            try:
                per = value['cnt'] / nrTotal * 100
            except:
                break

            if instance.mode == 'syscall':
                addVal = convert(value['cnt'])
            elif instance.mode == 'break':
                addVal = 'Path: %s, Cnt: %s' % (\
                    value['path'], convert(value['cnt']))
            else:
                addVal = value['path']

            SysMgr.printPipe(\
                '{0:>7} | {1:<144}{2:1}'.format(\
                    '%.1f%%' % per, '%s [%s]' % (sym, addVal), suffix))

            cnt += 1

        if cnt == 0:
            SysMgr.printPipe('\tNone%s' % suffix)

        SysMgr.printPipe('%s%s' % (oneLine, suffix))

        if len(fileTable) > 0:
            # print file table #
            SysMgr.printPipe((\
                '\n[%s File Summary] [Elapsed: %g] %s[Task: %s(%s)] '
                '[NrSamples: %s(%s%%)] [NrFiles: %s] [CPU: %s] %s') % \
                    (mtype, elapsed, samplingStr, \
                    instance.comm, instance.pid, \
                    convert(long(nrTotal)), perSample, \
                    convert(len(fileTable)), cpuStr, suffix))
            SysMgr.printPipe('%s%s' % (twoLine, suffix))
            SysMgr.printPipe(\
                '{0:^7} | {1:^144}{2:1}'.format('Usage', 'Path', suffix))
            SysMgr.printPipe('%s%s' % (twoLine, suffix))

            cnt = long(0)
            for filename, value in sorted(\
                fileTable.items(), key=lambda x:x[1]['cnt'], reverse=True):
                try:
                    per = value['cnt'] / nrTotal * 100
                except:
                    break

                SysMgr.printPipe(\
                    '{0:>7} | {1:<144}{2:1}'.format(\
                    '%.1f%%' % per, filename, suffix))

                cnt += 1

            if cnt == 0:
                SysMgr.printPipe('\tNone%s' % suffix)

            SysMgr.printPipe('%s%s' % (oneLine, suffix))

        instance.printCallHistory(instance)

        # check realtime mode #
        if SysMgr.procBuffer == []:
            return

        # print detailed statistics #
        msg = ' Detailed Statistics '
        stars = '*' * long((long(SysMgr.lineLength) - len(msg)) / 2)
        SysMgr.printPipe(\
            '\n\n%s%s%s\n\n' % (stars, msg, stars))
        if SysMgr.procBuffer == []:
            SysMgr.printPipe("\n\tNone%s" % suffix)
        else:
            SysMgr.printPipe(SysMgr.procBuffer)



    @staticmethod
    def checkPtraceScope():
        filePath = \
            '%s/sys/kernel/yama/ptrace_scope' % SysMgr.procPath

        try:
            with open(filePath, 'r') as fd:
                '''
0 - classic ptrace permissions: a process can PTRACE_ATTACH to any other
process running under the same uid, as long as it is dumpable (i.e.
did not transition uids, start privileged, or have called
prctl(PR_SET_DUMPABLE...) already). Similarly, PTRACE_TRACEME is
unchanged.

1 - restricted ptrace: a process must have a predefined relationship
with the inferior it wants to call PTRACE_ATTACH on. By default,
this relationship is that of only its descendants when the above
classic criteria is also met. To change the relationship, an
inferior can call prctl(PR_SET_PTRACER, debugger, ...) to declare
an allowed debugger PID to call PTRACE_ATTACH on the inferior.
Using PTRACE_TRACEME is unchanged.

2 - admin-only attach: only processes with CAP_SYS_PTRACE may use ptrace
with PTRACE_ATTACH, or through children calling PTRACE_TRACEME.

3 - no attach: no processes may use ptrace with PTRACE_ATTACH nor via
PTRACE_TRACEME. Once set, this sysctl value cannot be changed.
                '''
                perm = long(fd.readline()[:-1])
                if perm == 3:
                    SysMgr.printErr((\
                        'Fail to use ptrace because it is not allowed, '
                        'check %s') % filePath)
                    return -1
                return 0
        except:
            return 0



    @staticmethod
    def pauseThreads(tlist):
        def updateTargets(taskList):
            dlist = []
            tlist = list(taskList.keys())

            for tid in tlist:
                if not SysMgr.isAlive(tid):
                    dlist.append(tid)

            for tid in list(set(dlist)):
                SysMgr.printWarn(\
                    'Terminated %s(%s)' % (taskList[tid], tid), True)
                taskList.pop(tid, None)

            return taskList

        SysMgr.checkPerm()

        # check ptrace scope #
        if Debugger.checkPtraceScope() < 0:
            return

        # check thread list #
        if not tlist or len(tlist) == 0:
            SysMgr.printErr(\
                "Fail to recognize tids, use -g option")
            return

        # set alarm #
        signal.signal(signal.SIGALRM, SysMgr.onAlarm)
        signal.alarm(SysMgr.intervalEnable)

        taskList = {}
        lastTid = long(0)
        try:
            for tid in tlist:
                lastTid = long(tid)

                ret = SysMgr.createProcess(mute=True, chPgid=True)
                if ret > 0:
                    comm = SysMgr.getComm(tid)
                    taskList[tid] = comm
                    SysMgr.printInfo("paused %s(%s)" % (comm, lastTid))
                elif ret == 0:
                    dobj = Debugger(pid=lastTid)
                    SysMgr.waitEvent(ignChldSig=False)
                    dobj.__del__()
                    sys.exit(0)
                else:
                    SysMgr.printErr('Fail to create a process')
                    sys.exit(0)

            # wait for user event to continue threads #
            while 1:
                SysMgr.waitEvent(ignChldSig=False, exit=True)
                taskList = updateTargets(taskList)
                SysMgr.updateChilds()
                if SysMgr.isNoChild():
                    break

            SysMgr.printErr("No target threads")
        except SystemExit:
            return
        except:
            SysMgr.printErr(\
                'Fail to pause thread %s' % lastTid, True)



    def getSigInfo(self):
        PTRACE_GETSIGINFO = 0x4202



    def setSigInfo(self):
        PTRACE_SETSIGINFO = 0x4203



    def isForked(self, status):
        stat = status >> 8
        return (stat  == self.sigForkFlag or \
            stat == self.sigVforkFlag)



    def isCloned(self, status):
        stat = status >> 8
        return (stat  == self.sigCloneFlag)



    def getEventMsg(self):
        PTRACE_GETEVENTMSG = 0x4201
        data = c_long(0)
        addr = addressof(data)

        ret = self.ptrace(PTRACE_GETEVENTMSG, data=addr)
        return data.value



    def getStatus(self, status):
        ret = None

        if os.WIFEXITED(status):
            code = os.WEXITSTATUS(status)
            ret = -1

        # Process killed by a signal #
        elif os.WIFSIGNALED(status):
            signum = os.WTERMSIG(status)
            ret = signum

        # Invalid process status #
        elif not os.WIFSTOPPED(status):
            pass

        # Ptrace Event #
        elif status >> 8 == 0:
            ret = status >> 16

        # Process stopped by a signal #
        else:
            signum = os.WSTOPSIG(status)
            ret = signum

        return ret



    def setPC(self, val):
        if self.arch == 'arm':
            self.regs.r15 = val
        elif self.arch == 'aarch64':
            self.regs.r32 = val
        elif self.arch == 'x86':
            self.regs.eip = val
        elif self.arch == 'x64':
            self.regs.rip = val



    def setSP(self, val):
        if self.arch == 'arm':
            self.regs.r13 = val
        elif self.arch == 'aarch64':
            self.regs.r31 = val
        elif self.arch == 'x86':
            self.regs.esp = val
        elif self.arch == 'x64':
            self.regs.rsp = val



    def setLR(self, val):
        if self.arch == 'arm':
            self.regs.r14 = val
        elif self.arch == 'aarch64':
            self.regs.r30 = val



    def setRegs(self, temp=False):
        pid = self.pid
        wordSize = ConfigMgr.wordSize

        # get register set #
        try:
            if not self.supportSetRegset:
                raise Exception()

            cmd = PTRACE_SETREGSET = 0x4205
            NT_PRSTATUS = 1
            nrWords = sizeof(self.regs) * wordSize

            if temp:
                addr = addressof(self.tempIovecObj)
            else:
                addr = addressof(self.iovecObj)

            ret = self.ptrace(cmd, NT_PRSTATUS, addr)
            if ret != 0:
                raise Exception()
        except SystemExit:
            sys.exit(0)
        except:
            self.supportSetRegset = False

            if temp:
                addr = addressof(self.tempRegs)
            else:
                addr = addressof(self.regs)

            cmd = self.setregsCmd

            ret = self.ptrace(cmd, 0, addr)

        # check ret value #
        if ret >= 0:
            return True
        else:
            return False



    def restoreRegs(self):
        memmove(\
            addressof(self.regs), \
            addressof(self.tempRegs), \
            sizeof(self.regs))

        self.updateNamedRegs()



    def backupRegs(self):
        memmove(\
            addressof(self.tempRegs), \
            addressof(self.regs), \
            sizeof(self.regs))



    def getRegs(self, temp=False):
        pid = self.pid
        wordSize = ConfigMgr.wordSize

        # get register set #
        try:
            if not self.supportGetRegset:
                raise Exception()

            if temp:
                addr = addressof(self.tempIovecObj)
            else:
                addr = addressof(self.iovecObj)

            cmd = PTRACE_GETREGSET = 0x4204
            NT_PRSTATUS = 1
            nrWords = sizeof(self.regs) * wordSize

            ret = self.ptrace(cmd, NT_PRSTATUS, addr)
            if ret != 0:
                raise Exception()
        except SystemExit:
            sys.exit(0)
        except:
            self.supportGetRegset = False

            if temp:
                addr = addressof(self.tempRegs)
            else:
                addr = addressof(self.regs)

            cmd = self.getregsCmd

            ret = self.ptrace(cmd, 0, addr)

        if ret != 0:
            SysMgr.printErr(\
                "Fail to get register set of %s(%s)" % \
                    (self.comm, self.pid))

        return ret



    def updateNamedRegs(self):
        if self.arch == 'arm':
            self.fp = self.regs.r11
            self.sp = self.regs.r13
            self.lr = self.regs.r14
            self.pc = self.regs.r15
        elif self.arch == 'aarch64':
            self.fp = self.regs.r29
            self.lr = self.regs.r30
            self.sp = self.regs.r31
            self.pc = self.regs.r32
        elif self.arch == 'x86':
            self.fp = self.regs.ebp
            self.sp = self.regs.esp
            self.pc = self.regs.eip
        elif self.arch == 'x64':
            # no use rbp as frame pointer #
            self.fp = self.regs.rbp
            self.sp = self.regs.rsp
            self.pc = self.regs.rip



    def updateRegs(self):
        ret = self.getRegs()
        if ret != 0:
            return False

        self.updateNamedRegs()

        return True



    def ptraceEvent(self, reqList):
        # define architect-independant constant #
        PTRACE_SETOPTIONS = 0x4200

        option = 0
        plist = ConfigMgr.PTRACE_EVENT_TYPE

        for req in reqList:
            if req == 'PTRACE_O_TRACESYSGOOD':
                option |= 1
            elif req == 'PTRACE_O_TRACEFORK':
                option |= 1 << plist.index('PTRACE_EVENT_FORK')
            elif req == 'PTRACE_O_TRACEVFORK':
                option |= 1 << plist.index('PTRACE_EVENT_VFORK')
            elif req == 'PTRACE_O_TRACECLONE':
                option |= 1 << plist.index('PTRACE_EVENT_CLONE')
            elif req == 'PTRACE_O_TRACEEXEC':
                option |= 1 << plist.index('PTRACE_EVENT_EXEC')
            elif req == 'PTRACE_O_TRACEVFORKDONE':
                option |= 1 << plist.index('PTRACE_EVENT_VFORK_DONE')
            elif req == 'PTRACE_O_TRACEEXIT':
                option |= 1 << plist.index('PTRACE_EVENT_EXIT')
            elif req == 'PTRACE_O_TRACESECCOMP':
                option |= 1 << plist.index('PTRACE_EVENT_SECCOMP')

        return self.ptrace(PTRACE_SETOPTIONS, 0, option)



    def waitpid(self, pid=None):
        # Don't wait on children of other threads in this group #
        __WNOTHREAD = 0x20000000
        # Wait on all children, regardless of type #
        __WALL = 0x40000000
        # Wait only on non-SIGCHLD children #
        __WCLONE = 0x80000000

        # set default option #
        options = __WALL

        ret = 0

        if pid is None:
            pid = self.pid

        try:
            # type converting #
            if not self.initWaitpid:
                SysMgr.libcObj.waitpid.argtypes = \
                    (c_int, POINTER(None), c_int)
                SysMgr.libcObj.waitpid.restype = c_int
                self.initWaitpid = True

            status = c_uint(0)

            while 1:
                try:
                    ret = SysMgr.libcObj.waitpid(\
                        pid, pointer(status), options)
                except SystemExit:
                    sys.exit(0)
                except:
                    pass

                if ret == -1:
                    if not self.isAlive():
                        sys.exit(0)
                    continue

                break

            return ret, status.value
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printWarn(\
                'Fail to call waitpid', reason=True)
            return 0, 0



    def ptrace(self, req, addr=0, data=0, pid=None):
        if not pid:
            pid = self.pid

        '''
        # try to call native ptrace call #
        try:
            return SysMgr.guiderObj.ptrace(req, pid, addr, data)
        except SystemExit:
            sys.exit(0)
        except:
            pass
        '''

        try:
            # type converting #
            if not self.initPtrace:
                SysMgr.libcObj.ptrace.argtypes = \
                    (c_ulong, c_ulong, c_ulong, c_ulong)
                SysMgr.libcObj.ptrace.restype = c_ulong
                self.initPtrace = True

            ret = SysMgr.libcObj.ptrace(req, pid, addr, data)
            if c_long(ret).value == -1:
                return -1
            else:
                return ret
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printWarn(\
                'Fail to call ptrace', reason=True)
            return -1





class EventAnalyzer(object):
    """ Analyzer for event profiling """

    eventData = {}



    def __init__(self):
        pass



    def __del__(self):
        pass



    @staticmethod
    def addEvent(time, event):
        eventData = EventAnalyzer.eventData

        # ramdom event #
        if len(event.split(':')) == 1:
            name = event
            ID = None
        # sequantial event #
        else:
            name = event.split(':')[0]
            ID = event.split(':')[1]

        try:
            eventData[name]
            '''
            {'list': [ID, time, number], \
            'summary': [ID, cnt, avr, min, max, first, last]}
            '''
        except:
            eventData[name] = {'list': [], 'summary': []}

        eventData[name]['list'].append(\
            [ID, time, sum(t[0] == ID for t in eventData[name]['list']) + 1])

        if sum(id[0] == ID for id in eventData[name]['summary']) == 0:
            eventData[name]['summary'].append([ID, 1, -1, -1, -1, time, time])
        else:
            for n in eventData[name]['summary']:
                if n[0] == ID:
                    n[1] += 1
                    n[6] = time
                    break



    @staticmethod
    def printEventInfo():
        eventData = EventAnalyzer.eventData

        if len(eventData) > 0:
            SysMgr.printPipe(\
                "\n[%s] [ Total: %d ]" % ('Event Info', len(eventData)))
            SysMgr.printPipe(twoLine)
            try:
                EventAnalyzer.printEvent()
            except:
                pass
            SysMgr.printPipe(twoLine)



    @staticmethod
    def printEvent():
        eventData = EventAnalyzer.eventData
        startTime = float(SysMgr.startTime)

        for key, value in sorted(\
            eventData.items(), key=lambda x: float(x[1]['summary'][0][5])):
            string = ''
            head = '%10s: [total: %s] [subEvent: %s] ' % \
                (key, len(eventData[key]['list']), \
                    len(eventData[key]['summary']))
            for idx, n in enumerate(sorted(\
                eventData[key]['summary'], key=lambda slist: slist[0])):
                if idx == 0:
                    msg = head
                else:
                    msg = ' ' * len(head)

                if not n[0]:
                    n[0] = 'MAIN'

                try:
                    string = \
                        ('%s[%8s > cnt: %3d, avr: %3d, min: %3d,'
                        'max: %3d, first: %7.3f, last: %7.3f]') % \
                        (msg, n[0], n[1], n[2], n[3], n[4], \
                        float(n[5]) - startTime, float(n[6]) - startTime)
                except:
                    pass

                SysMgr.printPipe("%s" % string)





class MemoryFile(object):
    """ File for memory region """

    def __init__(self, addr, size=4096):
        self.pos = 0
        self.addr = addr
        self.size = size

        self.resize(size)



    def resize(self, size):
        SysMgr.importPkgItems('ctypes')

        self.mem = bytearray(size)
        ptr = (c_char * size).from_buffer(self.mem)

        ret = memmove(ptr, self.addr, size)
        if ret < 0:
            SysMgr.printErr(\
                "Fail to copy memory from %s" % self.addr)
        else:
            self.size = size

        return ret



    def read(self, size):
        des = self.pos + size

        if des > self.size:
            self.resize(des)

        segment = self.mem[self.pos:des]

        self.pos += size

        return bytes(segment)



    def write(self, size):
        pass



    def seek(self, pos):
        self.pos = pos





class ElfAnalyzer(object):
    """ Analyzer for ELF binaries """

    SHF_WRITE = 0x1
    SHF_ALLOC = 0x2
    SHF_EXECINSTR = 0x4
    SHF_MASKPROC = 0xF0000000

    DT_VERSIONTAGNUM = 16

    PT_FLAGS = {
        0: "None",
        1: "E",
        2: "W",
        3: "WE",
        4: "R",
        5: "RE",
        6: "RW",
        7: "RWE"
    }

    PT_TYPE = {
        0: "NULL",
        1: "LOAD",
        2: "DYNAMIC",
        3: "INTERP",
        4: "NOTE",
        5: "SHLIB",
        6: "PHDR",
        7: "TLS",
        8: "NUM",
        0x60000000: "PTLOOS",
        0x6fffffff: "PTHIOS",
        0x70000000: "LOPROC",
        0x7fffffff: "HPROC",
        0x6474e550: "GNU_EH_FRAME",
        0x6474e551: "GNU_STACK",
        0x6474e552: "GNU_RELRO",
    }

    ST_TYPE = {
        0: 'NOTYPE',
        1: 'OBJECT',
        2: 'FUNC',
        3: 'SECTION',
        4: 'FILE',
        5: 'COMMON',
        6: 'TLS',
        7: 'NUM',
        10: 'LOOS',
        12: 'HIOS',
        13: 'LOPROC',
        15: 'HIPROC'
    }


    ST_BIND_TYPE = {
        0: 'LOCAL',
        1: 'GLOBAL',
        2: 'WEAK',
        3: 'NUM',
        10: 'LOOS',
        12: 'HIOS',
        13: 'LOPROC',
        15: 'HIPROC'
    }

    ST_VISIBILITY_TYPE = {
        0: 'DEFAULT',
        1: 'INTERNAL',
        2: 'HIDDEN',
        3: 'PROTECTED'
    }

    SH_TYPE = {
        0:"NULL",
        1:"PROGBITS",
        2:"SYMTAB",
        3:"STRTAB",
        4:"RELA",
        5:"HASH",
        6:"DYNAMIC",
        7:"NOTE",
        8:"NOBITS",
        9:"REL",
        10:"SHLIB",
        11:"DYNSYM",
        12:"NUM",
        14:"INIT_ARRAY",
        15:"FINI_ARRAY",
        16:"PREINIT_ARRAY",
        17:"GROUP",
        18:"SYMTAB_SHNDX",
        19:"NUM",
        0x60000000:"LOOS",
        0x6fffffff:"HIOS",
        0x70000000:"LOPROC",
        0x7fffffff:"HIPROC",
        0x80000000:"LOUSER",
        0xffffffff:"HIUSER",
        0x6ffffff5:"GNU_ATTRIBUTES",
        0x6ffffff6:"GNU_HASH",
        0x6ffffff7:"GNU_LIBLIST",
        0x6ffffff8:"CHECKSUM",
        0x6ffffffa:"LOSUNW",
        0x6ffffffa:"SUNW_move",
        0x6ffffffb:"SUNW_COMDAT",
        0x6ffffffc:"SUNW_syminfo",
        0x6ffffffd:"GNU_verdef",
        0x6ffffffe:"GNU_verneed",
        0x6fffffff:"GNU_versym",
    }

    DT_TYPE = {
        0:"NULL",
        1:"NEEDED",
        2:"PLTRELSZ",
        3:"PLTGOT",
        4:"HASH",
        5:"STRTAB",
        6:"SYMTAB",
        7:"RELA",
        8:"RELASZ",
        9:"RELAENT",
        10:"STRSZ",
        11:"SYMENT",
        12:"INIT",
        13:"FINI",
        14:"SONAME",
        15:"RPATH",
        16:"SYMBOLIC",
        17:"REL",
        18:"RELSZ",
        19:"RELENT",
        20:"PLTREL",
        21:"DEBUG",
        22:"TEXTREL",
        23:"JMPREL",
        24:"BIND_NOW",
        25:"INIT_ARRAY",
        26:"FINI_ARRAY",
        27:"INIT_ARRAYSZ",
        28:"FINI_ARRAYSZ",
        29:"RUNPATH",
        30:"FLAGS",
        31:"ENCODING",
        32:"PREINIT_ARRAY",
        33:"PREINIT_ARRAYSZ",
        34:"NUM ",
        0x36:"PROCNUM",
        0x6000000d:"LOOS",
        0x6ffff000:"HIOS",
        0x70000000:"LOPROC",
        0x7fffffff:"HIPROC",
        0x6ffffd00:"VALRNGLO",
        0x6ffffdf5:"GNU_PRELINKED",
        0x6ffffdf6:"GNU_CONFLICTSZ",
        0x6ffffdf7:"GNU_LIBLISTSZ",
        0x6ffffdf8:"CHECKSUM",
        0x6ffffdf9:"PLTPADSZ",
        0x6ffffdfa:"MOVEENT",
        0x6ffffdfb:"MOVESZ",
        0x6ffffdfe:"SYMINSZ",
        0x6ffffdff:"SYMINENT",
        0x6ffffef5:"GNU_HASH",
        0x6ffffef6:"TLSDESC_PLT",
        0x6ffffef7:"TLSDESC_GOT",
        0x6ffffef8:"GNU_CONFLICT",
        0x6ffffef9:"GNU_LIBLIST",
        0x6ffffefa:"CONFIG",
        0x6ffffefb:"DEPAUDIT",
        0x6ffffefc:"AUDIT",
        0x6ffffefd:"PLTPAD",
        0x6ffffefe:"MOVETAB",
        0x6ffffeff:"SYMINFO",
        0x6ffffff0:"VERSYM",
        0x6ffffff9:"RELACOUNT",
        0x6ffffffa:"RELCOUNT",
        0x6ffffffb:"FLAGS_1",
        0x6ffffffc:"VERDEF",
        0x6ffffffd:"VERDEFNUM",
        0x6ffffffe:"VERNEED",
        0x6fffffff:"VERNEEDNUM",
        0x7ffffffd:"AUXILIARY",
        0x7fffffff:"FILTER",
    }

    DT_VERSYM = 0x6ffffff0
    DT_VERDEF = 0x6ffffffc
    DT_VERNEEDNUM = 0x6fffffff

    EI_TYPE= {
        0:"None",
        1:"Relocatable",
        2:"Executable",
        3:"Shared-object",
        4:"Core",
        0xff00:"Processor-specific",
        0xffff:"Processor-specific",
    }

    EI_OSABI = {
        0:"SYSV",
        1:"HPUX",
        2:"NETBSD",
        3:"LINUX",
        4:"HURD",
        6:"SOLARIS",
        7:"AIX",
        8:"IRIX",
        9:"FREEBSD",
        10:"TRU64",
        11:"MODESTO",
        12:"OPENBSD",
        13:"OPENVMS",
        14:"NSK",
        15:"AROS",
        16:"FENIXOS",
        17:"CLOUD",
        53:"SORTIX",
        64:"ARM_AEABI",
        97:"ARM",
        255:"STANDALONE",
    }

    DT_FLAGS = {
        0x1:"ORIGIN",
        0x2:"SYMBOLIC",
        0x4:"TEXTREL",
        0x8:"BIND_NOW",
        0x10:"STATIC_TLS",
    }

    DT_FLAGS_1 = {
        0x1:"NOW",
        0x2:"GLOBAL",
        0x4:"GROUP",
        0x8:"NODELETE",
        0x10:"LOADFLTR",
        0x20:"INITFIRST",
        0x40:"NOOPEN",
        0x80:"ORIGIN",
        0x100:"DIRECT",
        0x200:"TRANS",
        0x400:"INTERPOSE",
        0x800:"NODEFLIB",
        0x1000:"NODUMP",
        0x2000:"CONFALT",
        0x4000:"ENDFILTEE",
        0x8000:"DISPRELDNE",
        0x10000:"DISPRELPND",
        0x20000:"NODIRECT",
        0x40000:"IGNMULDEF",
        0x80000:"NOKSYMS",
        0x100000:"NOHDR",
        0x200000:"EDITED",
        0x400000:"NORELOC",
        0x800000:"SYMINTPOSE",
        0x1000000:"GLOBAUDIT",
        0x2000000:"SINGLETON",
        0x4000000:"STUB",
        0x8000000:"PIE",
    }

    RELOC_TYPE = {}

    RELOC_TYPE_x86 = {
        0:"R_386_NONE",
        1:"R_386_32",
        2:"R_386_PC32",
        3:"R_386_GOT32",
        4:"R_386_PLT32",
        5:"R_386_COPY",
        6:"R_386_GLOB_DAT",
        7:"R_386_JUMP_SLOT",
        8:"R_386_RELATIVE",
        9:"R_386_GOTOFF",
        10:"R_386_GOTPC",
        11:"R_386_32PLT",
        14:"R_386_TLS_TPOFF",
        15:"R_386_TLS_IE",
        16:"R_386_TLS_GOTIE",
        17:"R_386_TLS_LE",
        18:"R_386_TLS_GD",
        19:"R_386_TLS_LDM",
        20:"R_386_16",
        21:"R_386_PC16",
        22:"R_386_8",
        23:"R_386_PC8",
        24:"R_386_TLS_GD_32",
        25:"R_386_TLS_GD_PUSH",
        26:"R_386_TLS_GD_CALL",
        27:"R_386_TLS_GD_POP",
        28:"R_386_TLS_LDM_32",
        29:"R_386_TLS_LDM_PUSH",
        30:"R_386_TLS_LDM_CALL",
        31:"R_386_TLS_LDM_POP",
        32:"R_386_TLS_LDO_32",
        33:"R_386_TLS_IE_32",
        34:"R_386_TLS_LE_32",
        35:"R_386_TLS_DTPMOD32",
        36:"R_386_TLS_DTPOFF32",
        37:"R_386_TLS_TPOFF32",
        39:"R_386_TLS_GOTDESC",
        40:"R_386_TLS_DESC_CALL",
        41:"R_386_TLS_DESC",
        42:"R_386_IRELATIVE",
        200:"R_386_USED_BY_INTEL_200",
        250:"R_386_GNU_VTINHERIT",
        251:"R_386_GNU_VTENTRY",
    }

    RELOC_TYPE_x64 = {
        0:"R_X86_64_NONE",
        1:"R_X86_64_64",
        2:"R_X86_64_PC32",
        3:"R_X86_64_GOT32",
        4:"R_X86_64_PLT32",
        5:"R_X86_64_COPY",
        6:"R_X86_64_GLOB_DAT",
        7:"R_X86_64_JUMP_SLOT",
        8:"R_X86_64_RELATIVE",
        9:"R_X86_64_GOTPCREL",
        10:"R_X86_64_32",
        11:"R_X86_64_32S",
        12:"R_X86_64_16",
        13:"R_X86_64_PC16",
        14:"R_X86_64_8",
        15:"R_X86_64_PC8",
        16:"R_X86_64_DTPMOD64",
        17:"R_X86_64_DTPOFF64",
        18:"R_X86_64_TPOFF64",
        19:"R_X86_64_TLSGD",
        20:"R_X86_64_TLSLD",
        21:"R_X86_64_DTPOFF32",
        22:"R_X86_64_GOTTPOFF",
        23:"R_X86_64_TPOFF32",
        24:"R_X86_64_PC64",
        25:"R_X86_64_GOTOFF64",
        26:"R_X86_64_GOTPC32",
        27:"R_X86_64_GOT64",
        28:"R_X86_64_GOTPCREL64",
        29:"R_X86_64_GOTPC64",
        30:"R_X86_64_GOTPLT64",
        31:"R_X86_64_PLTOFF64",
        34:"R_X86_64_GOTPC32_TLSDESC",
        35:"R_X86_64_TLSDESC_CALL",
        36:"R_X86_64_TLSDESC",
        37:"R_X86_64_IRELATIVE",
        250:"R_X86_64_GNU_VTINHERIT",
        251:"R_X86_64_GNU_VTENTRY",
    }

    RELOC_TYPE_ARM = {
        0:"R_ARM_NONE",
        1:"R_ARM_PC24",
        2:"R_ARM_ABS32",
        3:"R_ARM_REL32",
        4:"R_ARM_LDR_PC_G0",
        5:"R_ARM_ABS16",
        6:"R_ARM_ABS12",
        7:"R_ARM_THM_ABS5",
        8:"R_ARM_ABS8",
        9:"R_ARM_SBREL32",
        10:"R_ARM_THM_CALL",
        11:"R_ARM_THM_PC8",
        12:"R_ARM_BREL_ADJ",
        13:"R_ARM_SWI24",
        14:"R_ARM_THM_SWI8",
        15:"R_ARM_XPC25",
        16:"R_ARM_THM_XPC22",
        17:"R_ARM_TLS_DTPMOD32",
        18:"R_ARM_TLS_DTPOFF32",
        19:"R_ARM_TLS_TPOFF32",
        20:"R_ARM_COPY",
        21:"R_ARM_GLOB_DAT",
        22:"R_ARM_JUMP_SLOT",
        23:"R_ARM_RELATIVE",
        24:"R_ARM_GOTOFF32",
        25:"R_ARM_BASE_PREL",
        26:"R_ARM_GOT_BREL",
        27:"R_ARM_PLT32",
        28:"R_ARM_CALL",
        29:"R_ARM_JUMP24",
        30:"R_ARM_THM_JUMP24",
        31:"R_ARM_BASE_ABS",
        32:"R_ARM_ALU_PCREL_7_0",
        33:"R_ARM_ALU_PCREL_15_8",
        34:"R_ARM_ALU_PCREL_23_15",
        35:"R_ARM_LDR_SBREL_11_0_NC",
        36:"R_ARM_ALU_SBREL_19_12_NC",
        37:"R_ARM_ALU_SBREL_27_20_CK",
        38:"R_ARM_TARGET1",
        39:"R_ARM_SBREL31",
        40:"R_ARM_V4BX",
        41:"R_ARM_TARGET2",
        42:"R_ARM_PREL31",
        43:"R_ARM_MOVW_ABS_NC",
        44:"R_ARM_MOVT_ABS",
        45:"R_ARM_MOVW_PREL_NC",
        46:"R_ARM_MOVT_PREL",
        47:"R_ARM_THM_MOVW_ABS_NC",
        48:"R_ARM_THM_MOVT_ABS",
        49:"R_ARM_THM_MOVW_PREL_NC",
        50:"R_ARM_THM_MOVT_PREL",
        51:"R_ARM_THM_JUMP19",
        52:"R_ARM_THM_JUMP6",
        53:"R_ARM_THM_ALU_PREL_11_0",
        54:"R_ARM_THM_PC12",
        55:"R_ARM_ABS32_NOI",
        56:"R_ARM_REL32_NOI",
        57:"R_ARM_ALU_PC_G0_NC",
        58:"R_ARM_ALU_PC_G0",
        59:"R_ARM_ALU_PC_G1_NC",
        60:"R_ARM_ALU_PC_G1",
        61:"R_ARM_ALU_PC_G2",
        62:"R_ARM_LDR_PC_G1",
        63:"R_ARM_LDR_PC_G2",
        64:"R_ARM_LDRS_PC_G0",
        65:"R_ARM_LDRS_PC_G1",
        66:"R_ARM_LDRS_PC_G2",
        67:"R_ARM_LDC_PC_G0",
        68:"R_ARM_LDC_PC_G1",
        69:"R_ARM_LDC_PC_G2",
        70:"R_ARM_ALU_SB_G0_NC",
        71:"R_ARM_ALU_SB_G0",
        72:"R_ARM_ALU_SB_G1_NC",
        73:"R_ARM_ALU_SB_G1",
        74:"R_ARM_ALU_SB_G2",
        75:"R_ARM_LDR_SB_G0",
        76:"R_ARM_LDR_SB_G1",
        77:"R_ARM_LDR_SB_G2",
        78:"R_ARM_LDRS_SB_G0",
        79:"R_ARM_LDRS_SB_G1",
        80:"R_ARM_LDRS_SB_G2",
        81:"R_ARM_LDC_SB_G0",
        82:"R_ARM_LDC_SB_G1",
        83:"R_ARM_LDC_SB_G2",
        84:"R_ARM_MOVW_BREL_NC",
        85:"R_ARM_MOVT_BREL",
        86:"R_ARM_MOVW_BREL",
        87:"R_ARM_THM_MOVW_BREL_NC",
        88:"R_ARM_THM_MOVT_BREL",
        89:"R_ARM_THM_MOVW_BREL",
        94:"R_ARM_PLT32_ABS",
        95:"R_ARM_GOT_ABS",
        96:"R_ARM_GOT_PREL",
        97:"R_ARM_GOT_BREL12",
        98:"R_ARM_GOTOFF12",
        99:"R_ARM_GOTRELAX",
        100:"R_ARM_GNU_VTENTRY",
        101:"R_ARM_GNU_VTINHERIT",
        102:"R_ARM_THM_JUMP11",
        103:"R_ARM_THM_JUMP8",
        104:"R_ARM_TLS_GD32",
        105:"R_ARM_TLS_LDM32",
        106:"R_ARM_TLS_LDO32",
        107:"R_ARM_TLS_IE32",
        108:"R_ARM_TLS_LE32",
        109:"R_ARM_TLS_LDO12",
        110:"R_ARM_TLS_LE12",
        111:"R_ARM_TLS_IE12GP",
        112:"R_ARM_PRIVATE_0",
        113:"R_ARM_PRIVATE_1",
        114:"R_ARM_PRIVATE_2",
        115:"R_ARM_PRIVATE_3",
        116:"R_ARM_PRIVATE_4",
        117:"R_ARM_PRIVATE_5",
        118:"R_ARM_PRIVATE_6",
        119:"R_ARM_PRIVATE_7",
        120:"R_ARM_PRIVATE_8",
        121:"R_ARM_PRIVATE_9",
        122:"R_ARM_PRIVATE_10",
        123:"R_ARM_PRIVATE_11",
        124:"R_ARM_PRIVATE_12",
        125:"R_ARM_PRIVATE_13",
        126:"R_ARM_PRIVATE_14",
        127:"R_ARM_PRIVATE_15",
        128:"R_ARM_ME_TOO",
        129:"R_ARM_THM_TLS_DESCSEQ16",
        130:"R_ARM_THM_TLS_DESCSEQ32",
        131:"R_ARM_THM_GOT_BREL12",
        140:"R_ARM_IRELATIVE",
    }

    RELOC_TYPE_AARCH64 = {
        256:"R_AARCH64_NONE",
        257:"R_AARCH64_ABS64",
        258:"R_AARCH64_ABS32",
        259:"R_AARCH64_ABS16",
        260:"R_AARCH64_PREL64",
        261:"R_AARCH64_PREL32",
        262:"R_AARCH64_PREL16",
        263:"R_AARCH64_MOVW_UABS_G0",
        264:"R_AARCH64_MOVW_UABS_G0_NC",
        265:"R_AARCH64_MOVW_UABS_G1",
        266:"R_AARCH64_MOVW_UABS_G1_NC",
        267:"R_AARCH64_MOVW_UABS_G2",
        268:"R_AARCH64_MOVW_UABS_G2_NC",
        269:"R_AARCH64_MOVW_UABS_G3",
        270:"R_AARCH64_MOVW_SABS_G0",
        271:"R_AARCH64_MOVW_SABS_G1",
        272:"R_AARCH64_MOVW_SABS_G2",
        273:"R_AARCH64_LD_PREL_LO19",
        274:"R_AARCH64_ADR_PREL_LO21",
        275:"R_AARCH64_ADR_PREL_PG_HI21",
        276:"R_AARCH64_ADR_PREL_PG_HI21_NC",
        277:"R_AARCH64_ADD_ABS_LO12_NC",
        278:"R_AARCH64_LDST8_ABS_LO12_NC",
        279:"R_AARCH64_TSTBR14",
        280:"R_AARCH64_CONDBR19",
        282:"R_AARCH64_JUMP26",
        283:"R_AARCH64_CALL26",
        284:"R_AARCH64_LDST16_ABS_LO12_NC",
        285:"R_AARCH64_LDST32_ABS_LO12_NC",
        286:"R_AARCH64_LDST64_ABS_LO12_NC",
        287:"R_AARCH64_MOVW_PREL_G0",
        288:"R_AARCH64_MOVW_PREL_G0_NC",
        289:"R_AARCH64_MOVW_PREL_G1",
        290:"R_AARCH64_MOVW_PREL_G1_NC",
        291:"R_AARCH64_MOVW_PREL_G2",
        292:"R_AARCH64_MOVW_PREL_G2_NC",
        293:"R_AARCH64_MOVW_PREL_G3",
        300:"R_AARCH64_MOVW_GOTOFF_G0",
        301:"R_AARCH64_MOVW_GOTOFF_G0_NC",
        302:"R_AARCH64_MOVW_GOTOFF_G1",
        303:"R_AARCH64_MOVW_GOTOFF_G1_NC",
        304:"R_AARCH64_MOVW_GOTOFF_G2",
        305:"R_AARCH64_MOVW_GOTOFF_G2_NC",
        306:"R_AARCH64_MOVW_GOTOFF_G3",
        307:"R_AARCH64_GOTREL64",
        308:"R_AARCH64_GOTREL32",
        309:"R_AARCH64_GOT_LD_PREL19",
        310:"R_AARCH64_LD64_GOTOFF_LO15",
        311:"R_AARCH64_ADR_GOT_PAGE",
        312:"R_AARCH64_LD64_GOT_LO12_NC",
        512:"R_AARCH64_TLSGD_ADR_PREL21",
        513:"R_AARCH64_TLSGD_ADR_PAGE21",
        514:"R_AARCH64_TLSGD_ADD_LO12_NC",
        515:"R_AARCH64_TLSGD_MOVW_G1",
        516:"R_AARCH64_TLSGD_MOVW_G0_NC",
        517:"R_AARCH64_TLSLD_ADR_PREL21",
        518:"R_AARCH64_TLSLD_ADR_PAGE21",
        519:"R_AARCH64_TLSLD_ADD_LO12_NC",
        520:"R_AARCH64_TLSLD_MOVW_G1",
        521:"R_AARCH64_TLSLD_MOVW_G0_NC",
        522:"R_AARCH64_TLSLD_LD_PREL19",
        523:"R_AARCH64_TLSLD_MOVW_DTPREL_G2",
        524:"R_AARCH64_TLSLD_MOVW_DTPREL_G1",
        525:"R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC",
        526:"R_AARCH64_TLSLD_MOVW_DTPREL_G0",
        527:"R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC",
        528:"R_AARCH64_TLSLD_ADD_DTPREL_HI12",
        529:"R_AARCH64_TLSLD_ADD_DTPREL_LO12",
        530:"R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC",
        531:"R_AARCH64_TLSLD_LDST8_DTPREL_LO12",
        532:"R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC",
        533:"R_AARCH64_TLSLD_LDST16_DTPREL_LO12",
        534:"R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC",
        535:"R_AARCH64_TLSLD_LDST32_DTPREL_LO12",
        536:"R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC",
        537:"R_AARCH64_TLSLD_LDST64_DTPREL_LO12",
        538:"R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC",
        539:"R_AARCH64_TLSIE_MOVW_GOTTPREL_G1",
        540:"R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC",
        541:"R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21",
        542:"R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC",
        543:"R_AARCH64_TLSIE_LD_GOTTPREL_PREL19",
        544:"R_AARCH64_TLSLE_MOVW_TPREL_G2",
        545:"R_AARCH64_TLSLE_MOVW_TPREL_G1",
        546:"R_AARCH64_TLSLE_MOVW_TPREL_G1_NC",
        547:"R_AARCH64_TLSLE_MOVW_TPREL_G0",
        548:"R_AARCH64_TLSLE_MOVW_TPREL_G0_NC",
        549:"R_AARCH64_TLSLE_ADD_TPREL_HI12",
        550:"R_AARCH64_TLSLE_ADD_TPREL_LO12",
        551:"R_AARCH64_TLSLE_ADD_TPREL_LO12_NC",
        552:"R_AARCH64_TLSLE_LDST8_TPREL_LO12",
        553:"R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC",
        554:"R_AARCH64_TLSLE_LDST16_TPREL_LO12",
        555:"R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC",
        556:"R_AARCH64_TLSLE_LDST32_TPREL_LO12",
        557:"R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC",
        558:"R_AARCH64_TLSLE_LDST64_TPREL_LO12",
        559:"R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC",
        1024:"R_AARCH64_COPY",
        1025:"R_AARCH64_GLOB_DAT",
        1026:"R_AARCH64_JUMP_SLOT",
        1027:"R_AARCH64_RELATIVE",
        1028:"R_AARCH64_TLS_DTPREL64",
        1029:"R_AARCH64_TLS_DTPMOD64",
        1030:"R_AARCH64_TLS_TPREL64",
        1031:"R_AARCH64_TLS_DTPREL32",
        1032:"R_AARCH64_TLS_DTPMOD32",
        1033:"R_AARCH64_TLS_TPREL32",
    }

    EI_MACHINE_TYPE = {
        0:"No machine",
        1:"AT&T WE 32100",
        2:"SPARC",
        3:"Intel 80386",
        4:"Motorola 68000",
        5:"Motorola 88000",
        6:"Intel MCU",
        7:"Intel 80860",
        8:"MIPS I Architecture",
        9:"IBM System/370 Processor",
        10:"MIPS RS3000 Little-endian",
        11-14:"Reserved for future use",
        15:"Hewlett-Packard PA-RISC",
        16:"Reserved for future use",
        17:"Fujitsu VPP500",
        18:"Enhanced instruction set SPARC",
        19:"Intel 80960",
        20:"PowerPC",
        21:"64-bit PowerPC",
        22:"IBM System/390 Processor",
        23:"IBM SPU/SPC",
        24-35:"Reserved for future use",
        36:"NEC V800",
        37:"Fujitsu FR20",
        38:"TRW RH-32",
        39:"Motorola RCE",
        40:"ARM 32-bit architecture (AARCH32)",
        41:"Digital Alpha",
        42:"Hitachi SH",
        43:"SPARC Version 9",
        44:"Siemens TriCore embedded processor",
        45:"Argonaut RISC Core, Argonaut Technologies Inc.",
        46:"Hitachi H8/300",
        47:"Hitachi H8/300H",
        48:"Hitachi H8S",
        49:"Hitachi H8/500",
        50:"Intel IA-64 processor architecture",
        51:"Stanford MIPS-X",
        52:"Motorola ColdFire",
        53:"Motorola M68HC12",
        54:"Fujitsu MMA Multimedia Accelerator",
        55:"Siemens PCP",
        56:"Sony nCPU embedded RISC processor",
        57:"Denso NDR1 microprocessor",
        58:"Motorola Star*Core processor",
        59:"Toyota ME16 processor",
        60:"STMicroelectronics ST100 processor",
        61:"Advanced Logic Corp. TinyJ embedded processor family",
        62:"AMD x86-64 architecture",
        63:"Sony DSP Processor",
        64:"Digital Equipment Corp. PDP-10",
        65:"Digital Equipment Corp. PDP-11",
        66:"Siemens FX66 microcontroller",
        67:"STMicroelectronics ST9+ 8/16 bit microcontroller",
        68:"STMicroelectronics ST7 8-bit microcontroller",
        69:"Motorola MC68HC16 Microcontroller",
        70:"Motorola MC68HC11 Microcontroller",
        71:"Motorola MC68HC08 Microcontroller",
        72:"Motorola MC68HC05 Microcontroller",
        73:"Silicon Graphics SVx",
        74:"STMicroelectronics ST19 8-bit microcontroller",
        75:"Digital VAX",
        76:"Axis Communications 32-bit embedded processor",
        77:"Infineon Technologies 32-bit embedded processor",
        78:"Element 14 64-bit DSP Processor",
        79:"LSI Logic 16-bit DSP Processor",
        80:"Donald Knuth's educational 64-bit processor",
        81:"Harvard University machine-independent object files",
        82:"SiTera Prism",
        83:"Atmel AVR 8-bit microcontroller",
        84:"Fujitsu FR30",
        85:"Mitsubishi D10V",
        86:"Mitsubishi D30V",
        87:"NEC v850",
        88:"Mitsubishi M32R",
        89:"Matsushita MN10300",
        90:"Matsushita MN10200",
        91:"picoJava",
        92:"OpenRISC 32-bit embedded processor",
        93:"ARC International ARCompact processor (old spelling/synonym: EM_ARC_A5)",
        94:"Tensilica Xtensa Architecture",
        95:"Alphamosaic VideoCore processor",
        96:"Thompson Multimedia General Purpose Processor",
        97:"National Semiconductor 32000 series",
        98:"Tenor Network TPC processor",
        99:"Trebia SNP 1000 processor",
        100:"STMicroelectronics (www.st.com) ST200 microcontroller",
        101:"Ubicom IP2xxx microcontroller family",
        102:"MAX Processor",
        103:"National Semiconductor CompactRISC microprocessor",
        104:"Fujitsu F2MC16",
        105:"Texas Instruments embedded microcontroller msp430",
        106:"Analog Devices Blackfin (DSP) processor",
        107:"S1C33 Family of Seiko Epson processors",
        108:"Sharp embedded microprocessor",
        109:"Arca RISC Microprocessor",
        110:"Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University",
        111:"eXcess: 16/32/64-bit configurable embedded CPU",
        112:"Icera Semiconductor Inc. Deep Execution Processor",
        113:"Altera Nios II soft-core processor",
        114:"National Semiconductor CompactRISC CRX microprocessor",
        115:"Motorola XGATE embedded processor",
        116:"Infineon C16x/XC16x processor",
        117:"Renesas M16C series microprocessors",
        118:"Microchip Technology dsPIC30F Digital Signal Controller",
        119:"Freescale Communication Engine RISC core",
        120:"Renesas M32C series microprocessors",
        121-130:"Reserved for future use",
        131:"Altium TSK3000 core",
        132:"Freescale RS08 embedded processor",
        133:"Analog Devices SHARC family of 32-bit DSP processors",
        134:"Cyan Technology eCOG2 microprocessor",
        135:"Sunplus S+core7 RISC processor",
        136:"New Japan Radio (NJR) 24-bit DSP Processor",
        137:"Broadcom VideoCore III processor",
        138:"RISC processor for Lattice FPGA architecture",
        139:"Seiko Epson C17 family",
        140:"The Texas Instruments TMS320C6000 DSP family",
        141:"The Texas Instruments TMS320C2000 DSP family",
        142:"The Texas Instruments TMS320C55x DSP family",
        143:"Texas Instruments Application Specific RISC Processor, 32bit fetch",
        144:"Texas Instruments Programmable Realtime Unit",
        145-159:"Reserved for future use",
        160:"",
        145-159:"Reserved for future use",
        160:"STMicroelectronics 64bit VLIW Data Signal Processor",
        161:"Cypress M8C microprocessor",
        162:"Renesas R32C series microprocessors",
        163:"NXP Semiconductors TriMedia architecture family",
        164:"QUALCOMM DSP6 Processor",
        165:"Intel 8051 and variants",
        166:"STMicroelectronics STxP7x family of configurable and extensible RISC processors",
        167:"Andes Technology compact code size embedded RISC processor family",
        168:"Cyan Technology eCOG1X family",
        168:"Cyan Technology eCOG1X family",
        169:"Dallas Semiconductor MAXQ30 Core Micro-controllers",
        170:"New Japan Radio (NJR) 16-bit DSP Processor",
        171:"M2000 Reconfigurable RISC Microprocessor",
        172:"Cray Inc. NV2 vector architecture",
        173:"Renesas RX family",
        174:"Imagination Technologies META processor architecture",
        175:"MCST Elbrus general purpose hardware architecture",
        176:"Cyan Technology eCOG16 family",
        177:"National Semiconductor CompactRISC CR16 16-bit microprocessor",
        178:"Freescale Extended Time Processing Unit",
        179:"Infineon Technologies SLE9X core",
        180:"Intel L10M",
        181:"Intel K10M",
        182:"Reserved for future Intel use",
        183:"ARM 64-bit architecture (AARCH64)",
        184:"Reserved for future ARM use",
        185:"Atmel Corporation 32-bit microprocessor family",
        186:"STMicroeletronics STM8 8-bit microcontroller",
        187:"Tilera TILE64 multicore architecture family",
        188:"Tilera TILEPro multicore architecture family",
        189:"Xilinx MicroBlaze 32-bit RISC soft processor core",
        190:"NVIDIA CUDA architecture",
        191:"Tilera TILE-Gx multicore architecture family",
        192:"CloudShield architecture family",
        193:"KIPO-KAIST Core-A 1st generation processor family",
        194:"KIPO-KAIST Core-A 2nd generation processor family",
        195:"Synopsys ARCompact V2",
        196:"Open8 8-bit RISC soft processor core",
        197:"Renesas RL78 family",
        198:"Broadcom VideoCore V processor",
        199:"Renesas 78KOR family",
        200:"Freescale 56800EX Digital Signal Controller (DSC)",
        201:"Beyond BA1 CPU architecture",
        202:"Beyond BA2 CPU architecture",
        203:"XMOS xCORE processor family",
        204:"Microchip 8-bit PIC(r) family",
        205:"Reserved by Intel",
        206:"Reserved by Intel",
        207:"Reserved by Intel",
        208:"Reserved by Intel",
        209:"Reserved by Intel",
        210:"KM211 KM32 32-bit processor",
        211:"KM211 KMX32 32-bit processor",
        212:"KM211 KMX16 16-bit processor",
        213:"KM211 KMX8 8-bit processor",
        214:"KM211 KVARC processor",
        215:"Paneve CDP architecture family",
        216:"Cognitive Smart Memory Processor",
        217:"Bluechip Systems CoolEngine",
        218:"Nanoradio Optimized RISC",
        219:"CSR Kalimba architecture family",
        220:"Zilog Z80",
        221:"Controls and Data Services VISIUMcore processor",
        222:"FTDI Chip FT32 high performance 32-bit RISC architecture",
        223:"Moxie processor family",
        224:"AMD GPU architecture",
        243:"RISC-V",
    }

    cachedFiles = {}
    cachedHeaderFiles = {}
    stripedFiles = {}
    failedFiles = {}
    cachedDemangleTable = {}



    @staticmethod
    def ELF_ST_BIND(i):
        return ((i) >> 4)



    @staticmethod
    def ELF_ST_TYPE(i):
        return ((i)&0x0f)



    @staticmethod
    def ELF_ST_INFO(b, t):
        return ((b)<<4 + ((t)&0x0f))



    @staticmethod
    def ELF_ST_VISIBILITY(i):
        return ((i)&0x3)



    @staticmethod
    def ELF32_R_SYM(i):
        return ((i) >> 8)



    @staticmethod
    def ELF32_R_TYPE(i):
        return ((i)&0xff)



    @staticmethod
    def ELF32_R_INFO(s, t):
        return (((s)<<8)+((t)&0xff))



    @staticmethod
    def ELF64_R_SYM(i):
        return ((i) >> 32)



    @staticmethod
    def ELF64_R_TYPE(i):
        return ((i)&0xffffffff)



    @staticmethod
    def ELF64_R_INFO(s, type):
        return (((s)<<32)+((s)&0xffffffff))



    @staticmethod
    def DT_VERSIONTAGIDX(tag):
        return (ElfAnalyzer.DT_VERNEEDNUM - (tag))



    @staticmethod
    def getHeader(path):
        if path not in ElfAnalyzer.cachedHeaderFiles:
            try:
                ElfAnalyzer.cachedHeaderFiles[path] = \
                    ElfAnalyzer(path, onlyHeader=True)
            except:
                return None

        return ElfAnalyzer.cachedHeaderFiles[path]



    @staticmethod
    def saveObject(obj, path):
        # check cache dir #
        if not os.path.isdir(SysMgr.cacheDirPath):
            try:
                os.makedirs(SysMgr.cacheDirPath)
            except:
                SysMgr.printWarn(\
                    'Fail to make %s directory' % \
                        SysMgr.cacheDirPath, reason=True)

        # build cache path #
        cpath = '%s/%s' % \
            (SysMgr.cacheDirPath, path.replace('/', '_'))

        return UtilMgr.saveObjectToFile(obj, cpath)



    @staticmethod
    def getCachedFilename(path):
        return '%s/%s' % \
            (SysMgr.cacheDirPath, path.replace('/', '_'))



    @staticmethod
    def loadObject(path):
        # build cache path #
        cpath = ElfAnalyzer.getCachedFilename(path)

        # check modified time #
        try:
            otime = os.stat(path).st_ctime
            ctime = os.stat(cpath).st_ctime

            if otime > ctime:
                SysMgr.printWarn(\
                    "The binary '%s' is more recent than the cache '%s'" % \
                        (path, cpath), True)
        except SystemExit:
            sys.exit(0)
        except:
            pass

        # load object from file #
        obj = UtilMgr.loadObjectFromFile(cpath)
        if not obj:
            return None

        # check binary size #
        dpath = obj.path
        if obj.fileSize != os.stat(dpath).st_size:
            return None

        return obj



    @staticmethod
    def getObject(path, raiseExcept=False, fobj=None):
        # load files #
        if path not in ElfAnalyzer.cachedFiles:
            # check black-list #
            if path in ElfAnalyzer.failedFiles:
                return None

            # check exception case #
            if not path.startswith('/'):
                if path == 'vdso':
                    fobj = SysMgr.getVdso()
                elif not os.path.exists(path):
                    return None

            SysMgr.printInfo(\
                "Start loading %s... " % path, suffix=False)

            # return a exceptional file object #
            if fobj:
                SysMgr.printInfo("[Done]", prefix=False, notitle=True)
                return fobj

            # try to load a object from a file #
            fobj = ElfAnalyzer.loadObject(path)
            if fobj:
                ElfAnalyzer.cachedFiles[path] = fobj
                ElfAnalyzer.cachedFiles[path].saved = True
                SysMgr.printInfo("[Cached]", prefix=False, notitle=True)
                return fobj

            # create a new object #
            try:
                raiseExcept = False

                elfObj = ElfAnalyzer(path)
                if not elfObj or not elfObj.ret:
                    raiseExcept = True
                    raise Exception('not an ELF file')

                ElfAnalyzer.cachedFiles[path] = elfObj
                SysMgr.printInfo("[Done]", prefix=False, notitle=True)
            except SystemExit:
                sys.exit(0)
            except:
                ElfAnalyzer.failedFiles[path] = True

                failLog = UtilMgr.convertColor("[Fail]", 'RED')
                SysMgr.printInfo(failLog, prefix=False, notitle=True)

                SysMgr.printWarn(\
                    "Fail to load %s as an ELF object" % path, reason=True)

                if raiseExcept:
                    raise Exception(err)
                else:
                    return None

        # save object cache to file #
        if not ElfAnalyzer.cachedFiles[path].saved:
            ElfAnalyzer.saveObject(ElfAnalyzer.cachedFiles[path], path)
            ElfAnalyzer.cachedFiles[path].saved = True

        return ElfAnalyzer.cachedFiles[path]



    @staticmethod
    def demangleSymbol(symbol, incArg=True):
        origSym = symbol
        symbol = symbol.replace('@@', '@')

        if not SysMgr.demangleEnable:
            return symbol

        # check mangling #
        if not symbol.startswith('_Z'):
            return symbol

        # check cache table #
        if symbol in ElfAnalyzer.cachedDemangleTable:
            return ElfAnalyzer.cachedDemangleTable[symbol]

        # check including version #
        if '@' in symbol:
            symbol, version = symbol.split('@')
            version = '@%s' % version
        else:
            version = ''

        # get ctypes object #
        if not SysMgr.importPkgItems('ctypes', False):
            SysMgr.printWarn((\
                "Fail to import python package: ctypes "
                "to demangle symbol, so that "
                "disable demangle feature"), True)
            SysMgr.demangleEnable = False
            return symbol

        # try to demangle symbol #
        try:
            SysMgr.loadLibcObj()

            # load demangle library #
            if not SysMgr.libdemangleObj:
                SysMgr.libdemangleObj = SysMgr.loadLib(SysMgr.libdemanglePath)

            # declare free() args #
            SysMgr.libcObj.free.argtypes = [c_void_p]

            # declare __cxa_demangle() function pointer #
            funcp = getattr(SysMgr.libdemangleObj, '__cxa_demangle')
            funcp.restype = c_void_p

            status = c_int()
            mSymbol = c_char_p(UtilMgr.encodeStr(symbol))

            # call to demangle symbol #
            ret = funcp(mSymbol, None, None, pointer(status))

            retc = cast(ret, c_char_p)

            # check return status and convert type from bytes to string #
            if status.value == 0:
                try:
                    dmSymbol = str(retc.value.decode())
                except:
                    dmSymbol = str(retc.value)
            elif status.value == -1:
                SysMgr.printWarn(\
                    "Fail to allocate memory to demangle symbol %s" % symbol)
                dmSymbol = symbol
            elif status.value == -2:
                SysMgr.printWarn(\
                    "Fail to demangle invaild symbol %s" % symbol)
                dmSymbol = symbol
            elif status.value == -3:
                SysMgr.printWarn((\
                    "Fail to demangle symbol %s "
                    "because of invalid args") % symbol)
                dmSymbol = symbol
            else:
                SysMgr.printWarn((\
                    "Fail to demangle symbol %s "
                    "because of unknown status %d") % (symbol, status.value))
                dmSymbol = symbol

            # free demangled string array #
            SysMgr.libcObj.free(ret)

            # remove args info #
            if not incArg:
                try:
                    dmSymbol = dmSymbol.split('(', 1)[0]
                except:
                    pass

            demangledSym = '%s%s' % (dmSymbol, version)
            ElfAnalyzer.cachedDemangleTable[origSym] = demangledSym
            return demangledSym
        except SystemExit:
            sys.exit(0)
        except:
            err = SysMgr.getErrMsg()
            SysMgr.printWarn((\
                "Fail to demangle symbol %s because %s "
                "so that disable demangle feature") % \
                    (symbol, err), True)
            SysMgr.demangleEnable = False
            return origSym



    @staticmethod
    def getFilterFlags(symbol):
        inc = start = end = False

        if not symbol:
            inc = start = end = True
        elif symbol[0] == '*' and \
            symbol[-1] == '*':
            symbol = symbol.strip('*')
            inc = True
        elif symbol[0] == '*':
            symbol = symbol.strip('*')
            end = True
        elif symbol[-1] == '*':
            symbol = symbol.strip('*')
            start = True

        return symbol, inc, start, end



    @staticmethod
    def getSymOffset(symbol, binPath, objdumpPath=None):
        syms = []

        if not objdumpPath:
            offset = None

            try:
                binObj = ElfAnalyzer.getObject(binPath)
                if not binObj:
                    raise Exception()

                symbol, inc, start, end = ElfAnalyzer.getFilterFlags(symbol)

                offset = binObj.getOffsetBySymbol(\
                    symbol, inc=inc, start=start, end=end)
            except SystemExit:
                sys.exit(0)
            except:
                pass

            if type(offset) is str:
                offset = long(offset, 16)
                syms.append([offset, symbol, binPath])
            elif type(offset) is list:
                for item in offset:
                    sym = item[0]
                    offset = long(item[1], 16)
                    syms.append([offset, sym, binPath])

            return syms

        # get subprocess object #
        subprocess = SysMgr.getPkg('subprocess')

        args = [objdumpPath, "-C", "-F", "-d", binPath]

        SysMgr.printStat(\
            "start finding %s... [ STOP(Ctrl+c) ]" % (symbol))

        # start objdump process #
        try:
            proc = subprocess.Popen(\
                args, stdout=subprocess.PIPE, \
                stderr=subprocess.PIPE, bufsize=-1)
        except:
            SysMgr.printErr(\
                "Fail to execute %s to get address from binary" % objdumpPath)
            sys.exit(0)

        while 1:
            try:
                # read a line from objdump process #
                line = proc.stdout.readline()
            except:
                SysMgr.printErr(\
                    "Fail to read output from objdump", True)

            # handle error #
            if not line:
                err = proc.stderr.read()
                if len(err) > 0:
                    proc.terminate()
                    SysMgr.printErr(err[err.find(':') + 2:])
                    sys.exit(0)
                break

            # parse line to find offset of symbol #
            line = str(line)
            m = re.match((\
                r'\s*(?P<addr>\S*)\s*\<(?P<symbol>.*)\>\s*\('\
                r'File Offset:\s*(?P<offset>\S*)\s*\)'), line)
            if not m:
                continue

            d = m.groupdict()
            if d['symbol'] == symbol:
                proc.terminate()
                return d['offset']
            elif symbol in d['symbol']:
                syms.append([d['symbol'], d['offset']])

        # check similar list #
        if len(syms) == 0:
            return None
        else:
            return syms



    @staticmethod
    def isRelocFile(path):
        try:
            cachedObject = ElfAnalyzer.getObject(path)
            if not cachedObject:
                raise Exception()

            etype = cachedObject.attr['elfHeader']['type']
            if etype == 'Relocatable' or \
                etype == 'Shared-object':
                return True
            else:
                return False
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printWarn(\
                "Fail to check relocatable format", True)
            return False

        # check file name #
        if '.so' in path or \
            '.ttf' in path or \
            '.pak' in path:
            return True
        else:
            return False



    def mergeSymTable(self, force=False, onlyFunc=True, removeOrig=True):
        # check already merged #
        if len(self.mergedSymTable) > 0 and not force:
            return

        # merge symbol tables #
        tempSymTable = deepcopy(self.attr['symTable'])
        tempSymTable.update(self.attr['dynsymTable'])

        # add PLT symbol #
        if not ElfAnalyzer.isRelocFile(self.path):
            pltinfo = self.getSectionHeader('.plt')
            if pltinfo:
                tempSymTable['PLT'] = {
                        'vis': 'DEFAULT', 'bind': 'GLOBAL', \
                        'value': pltinfo['addr'], 'ndx': 17, \
                        'type': 'OBJECT', 'size': pltinfo['size']}

        self.mergedSymTable = tempSymTable

        # sort and convert table #
        for idx, item in sorted(tempSymTable.items(),\
            key=lambda e: e[1]['value'], reverse=False):

            # skip useless symbol #
            if item['size'] == 0:
                continue

            # skip symbols except for function #
            if onlyFunc and item['type'] != 'FUNC':
                continue

            self.sortedAddrTable.append(item['value'])
            self.sortedSymTable.append([idx, item['size']])

        # remove useless symbols after merge #
        if removeOrig:
            del self.attr['symTable']
            del self.attr['dynsymTable']



    def getRangeBySymbol(self, symbol):
        # use unified symbol table #
        if symbol in self.mergedSymTable:
            val = self.mergedSymTable[symbol]
            return [val['value'], val['value'] + val['size']]
        else:
            return None

        # use each symbol tables #
        if symbol in self.attr['symTable']:
            val = self.attr['symTable'][symbol]
            return [val['value'], val['value'] + val['size']]
        elif symbol in self.attr['dynsymTable']:
            val = self.attr['dynsymTable'][symbol]
            return [val['value'], val['value'] + val['size']]
        else:
            return None



    def getAnonRangeByOffset(self, offset):
        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

        # check symbol table #
        if len(self.sortedSymTable) == 0:
            self.mergeSymTable()

        try:
            if UtilMgr.isString(offset):
                try:
                    offset = long(offset, 16)
                except:
                    offset = long(offset)

            addrTable = self.sortedAddrTable
            symTable = self.sortedSymTable

            # get target index from address table #
            idx = bisect_left(self.sortedAddrTable, offset) - 1
            if idx < 0:
                idx = long(0)

            if addrTable[idx] > offset:
                if idx > 0:
                    start = addrTable[idx-1] + symTable[idx-1][1] + 1
                    end = addrTable[idx] - 1
                else:
                    start = long(0)
                    end = addrTable[idx] - 1
            else:
                start = addrTable[idx] + symTable[idx][1] + 1
                end = addrTable[idx + 1] - 1

            return [start, end]
        except SystemExit:
            sys.exit(0)
        except:
            return [0, 0]



    def getSymbolByOffset(self, offset):
        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

        # check symbol table #
        if len(self.sortedSymTable) == 0:
            self.mergeSymTable()

        try:
            if UtilMgr.isString(offset):
                try:
                    offset = long(offset, 16)
                except:
                    offset = long(offset)

            addrTable = self.sortedAddrTable
            symTable = self.sortedSymTable

            # get target index from address table #
            idx = bisect_left(self.sortedAddrTable, offset) - 1
            if idx < 0:
                idx = long(0)

            while 1:
                if addrTable[idx] > offset:
                    return '??'

                # set symbol scope to size #
                if True:
                    maxAddr = addrTable[idx] + symTable[idx][1]
                # set symbol scope to next one's start offset #
                else:
                    maxAddr = addrTable[idx+1]

                if offset >= addrTable[idx] and offset <= maxAddr:
                    return symTable[idx][0]

                idx += 1
        except SystemExit:
            sys.exit(0)
        except:
            return '??'



    def getOffsetBySymbol(self, symbol, inc=False, start=False, end=False):
        # check symbol table #
        if len(self.sortedSymTable) == 0:
            self.mergeSymTable()

        clist = list()

        # get offset or symbol list #
        try:
            for idx, val in enumerate(self.sortedSymTable):
                target = val[0].split('@')[0]
                if (start and target.startswith(symbol)) or \
                    (end and target.endswith(symbol)) or \
                    (inc and symbol in target):
                    clist.append(\
                        [val[0], hex(self.sortedAddrTable[idx]).rstrip('L')])
                elif (symbol == val[0] or symbol == target):
                    return hex(self.sortedAddrTable[idx]).rstrip('L')
        except:
            return None

        if not clist:
            return None
        else:
            return clist



    def getSectionInfo(self, fd, pos=0):
        fd.seek(pos)

        if self.is32Bit:
            return struct.unpack('IIIIIIIIII', fd.read(40))
        else:
            return struct.unpack('IIQQQQIIQQ', fd.read(64))



    def __del__(self):
        pass



    def getString(self, strtable, start):
        idx = start
        end = self.fileSize - start

        while 1:
            if strtable[idx:idx+1] == b'\x00':
                break
            elif idx >= end:
                break

            idx += 1

        # pick symbol string #
        if start == idx:
            symbol = ''
        else:
            try:
                symbol = strtable[start:idx].decode()
            except:
                symbol = strtable[start:idx]

        return symbol



    def getSectionHeader(self, name):
        try:
            return self.attr['sectionHeader'][name]
        except:
            return None



    def __init__(\
        self, path=None, debug=False, onlyHeader=False, \
        fd=None, size=sys.maxsize, incArg=False):
        # define struct Elf32_Ehdr #
        '''
        #define EI_NIDENT 16

        /* Type for a 16-bit quantity.  */
        typedef uint16_t Elf32_Half;
        typedef uint16_t Elf64_Half;

        /* Types for signed and unsigned 32-bit quantities.  */
        typedef uint32_t Elf32_Word;
        typedef int32_t  Elf32_Sword;
        typedef uint32_t Elf64_Word;
        typedef int32_t  Elf64_Sword;

        /* Types for signed and unsigned 64-bit quantities.  */
        typedef uint64_t Elf32_Xword;
        typedef int64_t  Elf32_Sxword;
        typedef uint64_t Elf64_Xword;
        typedef int64_t  Elf64_Sxword;

        /* Type of addresses.  */
        typedef uint32_t Elf32_Addr;
        typedef uint64_t Elf64_Addr;

        /* Type of file offsets.  */
        typedef uint32_t Elf32_Off;
        typedef uint64_t Elf64_Off;

        /* Type for section indices, which are 16-bit quantities.  */
        typedef uint16_t Elf32_Section;
        typedef uint16_t Elf64_Section;

        /* Type for version symbol information.  */
        typedef Elf32_Half Elf32_Versym;
        typedef Elf64_Half Elf64_Versym;

        typedef struct
        {
          unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
          Elf32_Half    e_type;                 /* Object file type */
          Elf32_Half    e_machine;              /* Architecture */
          Elf32_Word    e_version;              /* Object file version */
          Elf32_Addr    e_entry;                /* Entry point virtual address */
          Elf32_Off     e_phoff;                /* Program header table file offset */
          Elf32_Off     e_shoff;                /* Section header table file offset */
          Elf32_Word    e_flags;                /* Processor-specific flags */
          Elf32_Half    e_ehsize;               /* ELF header size in bytes */
          Elf32_Half    e_phentsize;            /* Program header table entry size */
          Elf32_Half    e_phnum;                /* Program header table entry count */
          Elf32_Half    e_shentsize;            /* Section header table entry size */
          Elf32_Half    e_shnum;                /* Section header table entry count */
          Elf32_Half    e_shstrndx;             /* Section header string table index */
        } Elf32_Ehdr;

        typedef struct
        {
          unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
          Elf64_Half    e_type;                 /* Object file type */
          Elf64_Half    e_machine;              /* Architecture */
          Elf64_Word    e_version;              /* Object file version */
          Elf64_Addr    e_entry;                /* Entry point virtual address */
          Elf64_Off     e_phoff;                /* Program header table file offset */
          Elf64_Off     e_shoff;                /* Section header table file offset */
          Elf64_Word    e_flags;                /* Processor-specific flags */
          Elf64_Half    e_ehsize;               /* ELF header size in bytes */
          Elf64_Half    e_phentsize;            /* Program header table entry size */
          Elf64_Half    e_phnum;                /* Program header table entry count */
          Elf64_Half    e_shentsize;            /* Section header table entry size */
          Elf64_Half    e_shnum;                /* Section header table entry count */
          Elf64_Half    e_shstrndx;             /* Section header string table index */
        } Elf64_Ehdr;

        typedef struct
        {
          Elf32_Word    sh_name;                /* Section name (string tbl index) */
          Elf32_Word    sh_type;                /* Section type */
          Elf32_Word    sh_flags;               /* Section flags */
          Elf32_Addr    sh_addr;                /* Section virtual addr at execution */
          Elf32_Off     sh_offset;              /* Section file offset */
          Elf32_Word    sh_size;                /* Section size in bytes */
          Elf32_Word    sh_link;                /* Link to another section */
          Elf32_Word    sh_info;                /* Additional section information */
          Elf32_Word    sh_addralign;           /* Section alignment */
          Elf32_Word    sh_entsize;             /* Entry size if section holds table */
        } Elf32_Shdr;

        typedef struct
        {
          Elf64_Word    sh_name;                /* Section name (string tbl index) */
          Elf64_Word    sh_type;                /* Section type */
          Elf64_Xword   sh_flags;               /* Section flags */
          Elf64_Addr    sh_addr;                /* Section virtual addr at execution */
          Elf64_Off     sh_offset;              /* Section file offset */
          Elf64_Xword   sh_size;                /* Section size in bytes */
          Elf64_Word    sh_link;                /* Link to another section */
          Elf64_Word    sh_info;                /* Additional section information */
          Elf64_Xword   sh_addralign;           /* Section alignment */
          Elf64_Xword   sh_entsize;             /* Entry size if section holds table */
        } Elf64_Shdr;

        typedef struct
        {
          Elf32_Word    p_type;                 /* Segment type */
          Elf32_Off     p_offset;               /* Segment file offset */
          Elf32_Addr    p_vaddr;                /* Segment virtual address */
          Elf32_Addr    p_paddr;                /* Segment physical address */
          Elf32_Word    p_filesz;               /* Segment size in file */
          Elf32_Word    p_memsz;                /* Segment size in memory */
          Elf32_Word    p_flags;                /* Segment flags */
          Elf32_Word    p_align;                /* Segment alignment */
        } Elf32_Phdr;

        typedef struct
        {
          Elf64_Word    p_type;                 /* Segment type */
          Elf64_Word    p_flags;                /* Segment flags */
          Elf64_Off     p_offset;               /* Segment file offset */
          Elf64_Addr    p_vaddr;                /* Segment virtual address */
          Elf64_Addr    p_paddr;                /* Segment physical address */
          Elf64_Xword   p_filesz;               /* Segment size in file */
          Elf64_Xword   p_memsz;                /* Segment size in memory */
          Elf64_Xword   p_align;                /* Segment alignment */
        } Elf64_Phdr;

        typedef struct
        {
          Elf32_Word    st_name;                /* Symbol name (string tbl index) */
          Elf32_Addr    st_value;               /* Symbol value */
          Elf32_Word    st_size;                /* Symbol size */
          unsigned char st_info;                /* Symbol type and binding */
          unsigned char st_other;               /* Symbol visibility */
          Elf32_Section st_shndx;               /* Section index */
        } Elf32_Sym;

        typedef struct
        {
          Elf64_Word    st_name;                /* Symbol name (string tbl index) */
          unsigned char st_info;                /* Symbol type and binding */
          unsigned char st_other;               /* Symbol visibility */
          Elf64_Section st_shndx;               /* Section index */
          Elf64_Addr    st_value;               /* Symbol value */
          Elf64_Xword   st_size;                /* Symbol size */
        } Elf64_Sym;

        typedef struct
        {
          Elf32_Addr    r_offset;               /* Address */
          Elf32_Word    r_info;                 /* Relocation type and symbol index */
        } Elf32_Rel;

        /* I have seen two different definitions of the Elf64_Rel and
           Elf64_Rela structures, so we'll leave them out until Novell (or
           whoever) gets their act together.  */
        /* The following, at least, is used on Sparc v9, MIPS, and Alpha.  */

        typedef struct
        {
          Elf64_Addr    r_offset;               /* Address */
          Elf64_Xword   r_info;                 /* Relocation type and symbol index */
        } Elf64_Rel;

        /* Relocation table entry with addend (in section of type SHT_RELA).  */

        typedef struct
        {
          Elf32_Addr    r_offset;               /* Address */
          Elf32_Word    r_info;                 /* Relocation type and symbol index */
          Elf32_Sword   r_addend;               /* Addend */
        } Elf32_Rela;

        typedef struct
        {
          Elf64_Addr    r_offset;               /* Address */
          Elf64_Xword   r_info;                 /* Relocation type and symbol index */
          Elf64_Sxword  r_addend;               /* Addend */
        } Elf64_Rela;

        /* Version definition sections.  */

        typedef struct
        {
          Elf32_Half    vd_version;             /* Version revision */
          Elf32_Half    vd_flags;               /* Version information */
          Elf32_Half    vd_ndx;                 /* Version Index */
          Elf32_Half    vd_cnt;                 /* Number of associated aux entries */
          Elf32_Word    vd_hash;                /* Version name hash value */
          Elf32_Word    vd_aux;                 /* Offset in bytes to verdaux array */
          Elf32_Word    vd_next;                /* Offset in bytes to next verdef
                                                   entry */
        } Elf32_Verdef;

        typedef struct
        {
          Elf64_Half    vd_version;             /* Version revision */
          Elf64_Half    vd_flags;               /* Version information */
          Elf64_Half    vd_ndx;                 /* Version Index */
          Elf64_Half    vd_cnt;                 /* Number of associated aux entries */
          Elf64_Word    vd_hash;                /* Version name hash value */
          Elf64_Word    vd_aux;                 /* Offset in bytes to verdaux array */
          Elf64_Word    vd_next;                /* Offset in bytes to next verdef
                                                   entry */
        } Elf64_Verdef;

        /* Auxialiary version information.  */

        typedef struct
        {
          Elf32_Word    vda_name;               /* Version or dependency names */
          Elf32_Word    vda_next;               /* Offset in bytes to next verdaux
                                                   entry */
        } Elf32_Verdaux;

        typedef struct
        {
          Elf64_Word    vda_name;               /* Version or dependency names */
          Elf64_Word    vda_next;               /* Offset in bytes to next verdaux
                                                   entry */
        } Elf64_Verdaux;


        /* Version dependency section.  */

        typedef struct
        {
          Elf32_Half    vn_version;             /* Version of structure */
          Elf32_Half    vn_cnt;                 /* Number of associated aux entries */
          Elf32_Word    vn_file;                /* Offset of filename for this
                                                   dependency */
          Elf32_Word    vn_aux;                 /* Offset in bytes to vernaux array */
          Elf32_Word    vn_next;                /* Offset in bytes to next verneed
                                                   entry */
        } Elf32_Verneed;

        typedef struct
        {
          Elf64_Half    vn_version;             /* Version of structure */
          Elf64_Half    vn_cnt;                 /* Number of associated aux entries */
          Elf64_Word    vn_file;                /* Offset of filename for this
                                                   dependency */
          Elf64_Word    vn_aux;                 /* Offset in bytes to vernaux array */
          Elf64_Word    vn_next;                /* Offset in bytes to next verneed
                               entry */
        } Elf64_Verneed;

        /* Auxiliary needed version information.  */

        typedef struct
        {
          Elf32_Word    vna_hash;               /* Hash value of dependency name */
          Elf32_Half    vna_flags;              /* Dependency specific information */
          Elf32_Half    vna_other;              /* Unused */
          Elf32_Word    vna_name;               /* Dependency name string offset */
          Elf32_Word    vna_next;               /* Offset in bytes to next vernaux
                                                   entry */
        } Elf32_Vernaux;

        typedef struct
        {
          Elf64_Word    vna_hash;               /* Hash value of dependency name */
          Elf64_Half    vna_flags;              /* Dependency specific information */
          Elf64_Half    vna_other;              /* Unused */
          Elf64_Word    vna_name;               /* Dependency name string offset */
          Elf64_Word    vna_next;               /* Offset in bytes to next vernaux
                                                   entry */
        } Elf64_Vernaux;


        '''

        # define attributes #
        self.ret = True
        self.path = path
        self.attr = {}
        self.is32Bit = True
        self.saved = False
        self.sortedSymTable = []
        self.sortedAddrTable = []
        self.mergedSymTable = {}

        self.fileSize = size

        if fd is None:
            # check debug file #
            filename = os.path.basename(path)
            dirname = os.path.dirname(path)
            debugPath = '%s/.debug/%s' % (dirname, filename)
            if os.path.isfile(debugPath):
                SysMgr.printWarn(\
                    'Use %s instead of %s for debug symbols\n' % \
                    (debugPath, path))
                self.path = path = debugPath
            else:
                debugPath = '/usr/lib/debug%s' % path
                if os.path.isfile(debugPath):
                    SysMgr.printWarn(\
                        'Use %s instead of %s for debug symbols\n' % \
                        (debugPath, path))
                    self.path = path = debugPath

            # open file #
            try:
                fd = open(path, 'rb')
            except:
                if debug:
                    SysMgr.printOpenErr(path)
                else:
                    SysMgr.printOpenWarn(path)

                err = SysMgr.getErrMsg()
                raise Exception(err)

            # get file size #
            self.fileSize = os.stat(path).st_size

        # define default file type #
        e_type = e_class = 'dummpy'
        EI_NIDENT = 16

        # define err string #
        errStr = "Fail to recognize %s as an ELF object because %s"

        # check size #
        if self.fileSize < EI_NIDENT:
            size = UtilMgr.convSize2Unit(self.fileSize)
            SysMgr.printWarn(\
                errStr % (path, "it's size is just %s" % size), debug)
            self.ret = None
            return None

        # parse ELF header #
        ei_ident = struct.unpack('16B', fd.read(EI_NIDENT))
        ei_mag0, ei_mag1,ei_mag2, ei_mag3, \
            ei_class, ei_data, ei_version, ei_pad = ei_ident[:8]
        ei_nident = ei_ident[8:]

        # check magic number #
        if ei_mag0 != 0x7F and \
            ei_mag1 != ord('E') and \
            ei_mag2 != ord('L') and \
            ei_mag3 != ord('F'):
            SysMgr.printWarn(\
                errStr % (path, 'it is not the ELF object'), debug)
            self.ret = None
            return None

        # check 32/64-bit type #
        if ei_class == 1:
            self.is32Bit = True
            e_class = '32-bit objects'
        elif ei_class == 2:
            self.is32Bit = False
            e_class = '64-bit objects'
        else:
            SysMgr.printWarn(\
                errStr % (path, 'it is invaild class'), debug)
            self.ret = None
            return None

        # check data encoding (endian) #
        if ei_data == 1:
            e_data = 'ELFDATA2LSB'
        elif ei_data == 2:
            e_data = 'ELFDATA2MSB'
        else:
            SysMgr.printWarn(\
                errStr % (path, 'it is invalid for data encoding'), debug)
            self.ret = None
            return None

        # check file type #
        ei_type  = struct.unpack('H', fd.read(2))[0]
        try:
            e_type = ElfAnalyzer.EI_TYPE[ei_type]
        except:
            e_type = 'N/A'

        # check machine type #
        ei_machine  = struct.unpack('H', fd.read(2))[0]
        if ei_machine in ElfAnalyzer.EI_MACHINE_TYPE:
            e_machine = ElfAnalyzer.EI_MACHINE_TYPE[ei_machine]
        else:
            e_machine = 'Unknow machine'

        # update Program Table on arch #
        if e_machine.startswith('ARM'):
            ElfAnalyzer.PT_TYPE.update(\
                {0x70000000:"ARCHEXT",
                0x70000001:"EXIDX"})

            if e_machine.startswith('ARM 32'):
                ElfAnalyzer.SH_TYPE.update(\
                    {0x70000001:"EXIDX",
                    0x70000002:"PREEMPTMAP",
                    0x70000003:"ATTRIBUTES"})

                ElfAnalyzer.RELOC_TYPE = ElfAnalyzer.RELOC_TYPE_ARM
            else:
                ElfAnalyzer.RELOC_TYPE = ElfAnalyzer.RELOC_TYPE_AARCH64
        elif e_machine.startswith('AMD x86-64') or \
            e_machine.startswith('Intel IA-64'):
            ElfAnalyzer.PT_TYPE.update(\
                {0x60000012:"HP_OPT_ANOT",
                0x60000013:"HP_HSL_ANOT",
                0x60000014:"HP_STACK",
                0x70000000:"ARCHEXT",
                0x70000001:"UNWIND"})

            ElfAnalyzer.SH_TYPE.update(\
                {0x70000000:"EXT",
                0x70000001:"UNWIND"})

            ElfAnalyzer.RELOC_TYPE = ElfAnalyzer.RELOC_TYPE_x64
        elif e_machine.startswith('Intel '):
            ElfAnalyzer.RELOC_TYPE = ElfAnalyzer.RELOC_TYPE_x86

        # check version #
        ei_version = struct.unpack('I', fd.read(4))[0]
        if ei_version == 0:
            e_version = 'illegal version'
        else:
            e_version = str(ei_version)

        # parse 32-bit ELF header #
        if self.is32Bit:
            e_entry, e_phoff, e_shoff, e_flags, e_ehsize, e_phentsize, \
                e_phnum, e_shentsize, e_shnum, e_shstrndx = \
                struct.unpack('IIIIHHHHHH', fd.read(28))
        # parse 64-bit ELF header #
        else:
            e_entry, e_phoff, e_shoff, e_flags, e_ehsize, e_phentsize, \
                e_phnum, e_shentsize, e_shnum, e_shstrndx = \
                struct.unpack('QQQIHHHHHH', fd.read(40))

        # save header info #
        self.attr['elfHeader'] = dict()
        self.attr['elfHeader']['magic'] = \
            ("%02x %02x %02x %02x %02x %02x %02x %02x" %
            (ei_mag0, ei_mag1, ei_mag2, ei_mag3, ei_class, ei_data,\
                ei_version, ei_pad))
        self.attr['elfHeader']['class'] = e_class
        self.attr['elfHeader']['data'] = e_data
        self.attr['elfHeader']['type'] = e_type
        self.attr['elfHeader']['machine'] = e_machine
        self.attr['elfHeader']['version'] = e_version
        self.attr['elfHeader']['entry'] = e_entry
        self.attr['elfHeader']['phoff'] = e_phoff
        self.attr['elfHeader']['shoff'] = e_shoff
        self.attr['elfHeader']['flags'] = e_flags
        self.attr['elfHeader']['ehsize'] = e_ehsize
        self.attr['elfHeader']['phentsize'] = e_phentsize
        self.attr['elfHeader']['shnum'] = e_shnum
        self.attr['elfHeader']['shentsize'] = e_shentsize
        self.attr['elfHeader']['shnum'] = e_shnum
        self.attr['elfHeader']['shstrndx'] = e_shstrndx

        # check onlyHeader flag #
        if onlyHeader:
            return None

        # print header info #
        if debug:
            SysMgr.printPipe('''\
[ELF Header]
%s
Magic: %s
Class: %s
Data: %s
Type: %s
Machine: %s
Version: %s
Entry point address: 0x%x
Start of program headers: %d (bytes into file)
Start of section headers: %d (bytes into file)
Flags: 0x%02x
Size of this header: %d (bytes)
Size of program header: %d (bytes)
Number of program headers: %d
Size of section headers: %d (bytes)
Number of section headers: %d
Section header string table index: %d
%s
            ''' % (twoLine, self.attr['elfHeader']['magic'], \
                e_class, e_data, e_type, e_machine, e_version, \
                e_entry, e_phoff, e_shoff, e_flags, e_ehsize, \
                e_phentsize, e_shnum, e_shentsize, e_shnum, \
                e_shstrndx, twoLine))

        # parse section header #
        sh_name, sh_type, sh_flags, sh_addr, sh_offset, \
            sh_size, sh_link, sh_info, sh_addralign, sh_entsize = \
            self.getSectionInfo(fd, e_shoff + e_shentsize * e_shstrndx)

        # parse string section #
        fd.seek(sh_offset)
        str_section = fd.read(sh_size)

        # define program info #
        self.attr['progHeader'] = list()

        # print program header title #
        if debug:
            SysMgr.printPipe((\
                "[Program Headers]\n%s\n"
                "%16s %10s %16s %16s %12s %12s %10s\n%s") % \
                (twoLine, "Type", "Offset", "VirtAddr", \
                "PhysAddr", "FileSize", "MemSize", "Flags", twoLine))

        # parse program sections #
        e_shinterpndx = -1
        for i in range(0, e_phnum):
            fd.seek(e_phoff + e_phentsize * i)

            # 32-bit #
            if self.is32Bit:
                p_type, p_offset, p_vaddr, p_paddr, \
                    p_filesz, p_memsz, p_flags, p_align = \
                    struct.unpack('IIIIIIII', fd.read(32))
            # 64-bit #
            else:
                p_type, p_flags, p_offset, p_vaddr, p_paddr, \
                    p_filesz, p_memsz, p_align = \
                    struct.unpack('IIQQQQQQ', fd.read(56))

            # INTERP #
            if p_type == 3:
                e_shinterpndx = i

            # save program info #
            self.attr['progHeader'].append([\
                ElfAnalyzer.PT_TYPE[p_type] \
                    if p_type in ElfAnalyzer.PT_TYPE else p_type, \
                p_offset, p_vaddr, p_paddr, p_filesz, \
                p_memsz, ElfAnalyzer.PT_FLAGS[p_flags]])

            # print program header #
            if debug:
                SysMgr.printPipe(\
                    "%16s 0x%08x 0x%014x 0x%014x 0x%010x 0x%010x %010s" % \
                    (ElfAnalyzer.PT_TYPE[p_type] \
                        if p_type in ElfAnalyzer.PT_TYPE else hex(p_type), \
                    p_offset, p_vaddr, p_paddr, p_filesz, \
                    p_memsz, ElfAnalyzer.PT_FLAGS[p_flags]))
        if debug:
            SysMgr.printPipe(oneLine)

        if e_shinterpndx >= 0:
            fd.seek(e_phoff + e_phentsize * e_shinterpndx)

            # 32-bit #
            if self.is32Bit:
                p_type, p_offset, p_vaddr, p_paddr, \
                    p_filesz, p_memsz, p_flags, p_align = \
                    struct.unpack('IIIIIIII', fd.read(32))
            # 64-bit #
            else:
                p_type, p_flags, p_offset, p_vaddr, p_paddr, \
                    p_filesz, p_memsz, p_align = \
                    struct.unpack('IIQQQQQQ', fd.read(56))

            fd.seek(p_offset)
            interp = fd.read(p_filesz)

        # initialize indexes #
        e_shsymndx = -1
        e_shstrndx = -1
        e_shdynsym = -1
        e_shdynstr = -1
        e_shdynamic = -1
        e_shversym = -1
        e_shverneed = -1
        e_shverdef = -1
        e_shrellist = []
        e_shrelalist = []

        # define section info #
        self.attr['sectionHeader'] = dict()

        # print section header title #
        if debug:
            SysMgr.printPipe(\
                ("\n[Section Headers]\n%s\n"
                "[NR] %50s%15s%10s%10s%8s%8s%5s%5s%5s%6s\n%s") % \
                (twoLine, "Name", "Type", "Address", "Offset", "Size", \
                "EntSize", "Flag", "Link", "Info", "Align", twoLine))

        # parse section header #
        for i in range(0, e_shnum):
            sh_name, sh_type, sh_flags, sh_addr, \
                sh_offset, sh_size, sh_link, sh_info, \
                sh_addralign, sh_entsize  = \
                self.getSectionInfo(fd, e_shoff + e_shentsize * i)

            # check permission #
            f = ""
            if sh_flags & ElfAnalyzer.SHF_WRITE:
                f += "W"
            if sh_flags & ElfAnalyzer.SHF_ALLOC:
                f += "A"
            if sh_flags & ElfAnalyzer.SHF_EXECINSTR:
                f += "X"
            if sh_flags & ElfAnalyzer.SHF_MASKPROC:
                f += "M"

            # get symbol string #
            symbol = self.getString(str_section, sh_name)

            stype = ElfAnalyzer.SH_TYPE[sh_type] \
                if sh_type in ElfAnalyzer.SH_TYPE else sh_type

            self.attr['sectionHeader'][symbol] = {
                'type': stype, 'addr': sh_addr, 'offset': sh_offset, \
                'size': sh_size, 'entSize': sh_entsize, 'flag': f, \
                'link': sh_link, 'info': sh_info, 'align': sh_addralign}

            # print section header #
            if debug:
                SysMgr.printPipe(\
                    "[%02d] %50s%15s%10s%10x%8d%8d%5s%5s%5s%6s" % \
                    (i, symbol, \
                    ElfAnalyzer.SH_TYPE[sh_type] \
                        if sh_type in ElfAnalyzer.SH_TYPE else hex(sh_type), \
                    '0x%x' % sh_addr, sh_offset, sh_size, sh_entsize, \
                    f, sh_link, sh_info, sh_addralign))

            # get header index #
            if symbol == '.symtab':
                e_shsymndx = i
            elif symbol == '.strtab':
                e_shstrndx = i
            elif symbol == '.dynsym':
                e_shdynsym = i
            elif symbol == '.dynstr':
                e_shdynstr = i
            elif symbol == '.dynamic':
                e_shdynamic = i
            elif stype == 'GNU_versym':
                e_shversym = i
            elif stype == 'GNU_verdef':
                e_shverdef = i
            elif stype == 'GNU_verneed':
                e_shverneed = i
            elif stype == 'REL':
                e_shrellist.append(i)
            elif stype == 'RELA':
                e_shrelalist.append(i)

        if debug:
            SysMgr.printPipe(oneLine)

        # define versym info #
        self.attr['versymList'] = list()

        # parse .gnu.version table #
        if e_shversym >= 0:
            # get .gnu.version section info #
            sh_name, sh_type, sh_flags, sh_addr, \
                sh_offset, sh_size, sh_link, sh_info, \
                sh_addralign, sh_entsize  = \
                self.getSectionInfo(fd, e_shoff + e_shentsize * e_shversym)

            # read .gnu.version data #
            fd.seek(sh_offset)
            versym_section = fd.read(sh_size)

            for i in range(0, long(sh_size / sh_entsize)):
                target = versym_section[i*sh_entsize:(i+1)*sh_entsize]
                symidx = struct.unpack('H', target)[0]
                self.attr['versymList'].append(symidx)

        # define .dynsym info #
        self.attr['dynsymTable'] = dict()
        self.attr['dynsymList'] = [''] # STN_UNDEF == 0
        self.attr['versionTable'] = dict()


        # parse .dynsym table #
        if e_shdynsym >= 0 and e_shdynstr >= 0 and \
            self.attr['sectionHeader']['.dynsym']['type'] != 'NOBITS' and \
            self.attr['sectionHeader']['.dynstr']['type'] != 'NOBITS':
            # get .dynstr section info #
            sh_name, sh_type, sh_flags, sh_addr, \
                sh_offset, sh_size, sh_link, sh_info, \
                sh_addralign, sh_entsize  = \
                self.getSectionInfo(fd, e_shoff + e_shentsize * e_shdynstr)

            # backup .dynstr offset #
            dynstr_offset = sh_offset

            # read .dynstr data #
            fd.seek(sh_offset)
            dynstr_section = fd.read(sh_size)
            try:
                dynstr_section_decoded = dynstr_section.decode()
            except:
                dynstr_section_decoded = dynstr_section

            lastnull = long(0)
            dynsymTable = {}
            for i, s in enumerate(dynstr_section_decoded):
                if s == '\0':
                    try:
                        dynsymTable[lastnull] = \
                            dynstr_section[lastnull:i].decode()
                    except:
                        dynsymTable[lastnull] = \
                            dynstr_section[lastnull:i]
                    lastnull = i + 1

            # parse .gnu.version_d table #
            if e_shverdef >= 0:
                 # get .gnu.version_d section info #
                sh_name, sh_type, sh_flags, sh_addr, \
                    sh_offset, sh_size, sh_link, sh_info, \
                    sh_addralign, sh_entsize  = \
                    self.getSectionInfo(fd, e_shoff + e_shentsize * e_shverdef)

                # read .gnu.version_d data #
                fd.seek(sh_offset)
                verdef_section = fd.read(sh_size)

                # get verdef values #
                vdidx = 1
                offset = long(0)
                entsize = 20
                sentsize = 8
                for idx in range(sh_info):
                    target = verdef_section[offset:offset+entsize]
                    vd_version, vd_flags, vd_ndx, \
                        vd_cnt, vd_hash, vd_aux, vd_next = \
                        struct.unpack('HHHHIII', target)

                    # get verdef strings #
                    soffset = offset + vd_aux
                    for vidx in range(vd_cnt):
                        starget = verdef_section[soffset:soffset+sentsize]
                        vda_name, vda_next = \
                            struct.unpack('II', starget)

                        if vidx == 0:
                            self.attr['versionTable'][vdidx] = \
                                self.getString(dynstr_section, vda_name)

                            vdidx += 1

                        soffset += vda_next

                    offset += vd_next

            # parse .gnu.version_r table #
            if e_shverneed  >= 0:
                # get .gnu.version_r section info #
                sh_name, sh_type, sh_flags, sh_addr, \
                    sh_offset, sh_size, sh_link, sh_info, \
                    sh_addralign, sh_entsize  = \
                    self.getSectionInfo(\
                        fd, e_shoff + e_shentsize * e_shverneed)

                # read .gnu.version_r data #
                fd.seek(sh_offset)
                verneed_section = fd.read(sh_size)

                # get verneed values #
                offset = long(0)
                entsize = 16
                for idx in range(sh_info):
                    target = verneed_section[offset:offset+entsize]
                    vn_version, vn_cnt, vn_file, vn_aux, vn_next = \
                        struct.unpack('HHIII', target)

                    # get verneed strings #
                    soffset = offset + entsize
                    for vidx in range(vn_cnt):
                        starget = verneed_section[soffset:soffset+entsize]
                        vna_hash, vna_flags, vna_other, vna_name, vna_next = \
                            struct.unpack('IHHII', starget)

                        self.attr['versionTable'][vna_other] = \
                            self.getString(dynstr_section, vna_name)

                        soffset += entsize

                    offset += vn_next

            # get .dynsym section info #
            sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, \
                sh_link, sh_info, sh_addralign, sh_entsize = \
                self.getSectionInfo(fd, e_shoff + e_shentsize * e_shdynsym)

            # read .dynsym data #
            fd.seek(sh_offset)
            dynsym_section = fd.read(sh_size)

            # print .dynsym table title #
            if debug:
                SysMgr.printPipe((\
                    "\n[.dynsym Section]\n%s\n"
                    "%04s %16s%10s%10s%10s%10s%10s %30s\n%s") % \
                    (twoLine, "Num", "Value", "Size", "Type", \
                    "Bind", "Vis", "Ndx", "Name", twoLine))

            nrItems = long(sh_size / sh_entsize)
            if nrItems == 0:
                SysMgr.printPipe('\tNone')

            for i in range(0, nrItems):
                target = dynsym_section[i*sh_entsize:(i+1)*sh_entsize]
                # 32-bit #
                if self.is32Bit:
                    st_name, st_value, st_size, \
                        st_info, st_other, st_shndx = \
                        struct.unpack('IIIBBH', target)
                # 64-bit #
                else:
                    st_name, st_info, st_other, \
                        st_shndx, st_value, st_size = \
                        struct.unpack('IBBHQQ', target)

                # get symbol string #
                symbol = self.getString(dynstr_section, st_name)

                # convert manged string #
                symbol = ElfAnalyzer.demangleSymbol(symbol)

                # concatenate symbol with it's required version #
                try:
                    symIdx = len(self.attr['dynsymList'])
                    vsIdx = self.attr['versymList'][symIdx]
                    symbol = '%s@%s' % \
                        (symbol, self.attr['versionTable'][vsIdx])
                except:
                    pass

                # add symbol to table #
                self.attr['dynsymTable'][symbol] = {\
                    'value': st_value, 'size': st_size, \
                    'type': ElfAnalyzer.ST_TYPE[ \
                        ElfAnalyzer.ELF_ST_TYPE(st_info)], \
                    'bind': ElfAnalyzer.ST_BIND_TYPE[\
                        ElfAnalyzer.ELF_ST_BIND(st_info)], \
                    'vis': ElfAnalyzer.ST_VISIBILITY_TYPE[\
                        ElfAnalyzer.ELF_ST_VISIBILITY(st_other)], \
                    'ndx': st_shndx}

                # register symbol to dynamic symbol list #
                self.attr['dynsymList'].append(symbol)

                # print .dynsym table #
                if debug:
                    SysMgr.printPipe(\
                        "%04d %016x%10d%10s%10s%10s%10d %s" % \
                        (i, st_value, st_size, \
                        ElfAnalyzer.ST_TYPE[\
                            ElfAnalyzer.ELF_ST_TYPE(st_info)], \
                        ElfAnalyzer.ST_BIND_TYPE[\
                            ElfAnalyzer.ELF_ST_BIND(st_info)], \
                        ElfAnalyzer.ST_VISIBILITY_TYPE[\
                            ElfAnalyzer.ELF_ST_VISIBILITY(st_other)], \
                        st_shndx, symbol,))
            if debug:
                SysMgr.printPipe(oneLine)

        # define .sym info #
        self.attr['symTable'] = dict()

        # parse .symtab table #
        if e_shsymndx >= 0 and e_shstrndx >= 0 and \
            self.attr['sectionHeader']['.symtab']['type'] != 'NOBITS' and \
            self.attr['sectionHeader']['.strtab']['type'] != 'NOBITS':
            # get .symtab section info #
            sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, \
                sh_link, sh_info, sh_addralign, sh_entsize = \
                self.getSectionInfo(fd, e_shoff + e_shentsize * e_shstrndx)

            # backup .strtab offset #
            strtab_offset = sh_offset

            # read .strtab data #
            fd.seek(sh_offset)
            strtab_section = fd.read(sh_size)

            # get .symtab section info #
            sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, \
                sh_link, sh_info, sh_addralign, sh_entsize = \
                self.getSectionInfo(fd, e_shoff + e_shentsize * e_shsymndx)

            # read .symtab data #
            fd.seek(sh_offset)
            sym_section = fd.read(sh_size)

            # parse .sym table title #
            if debug:
                SysMgr.printPipe((\
                    "\n[.symtab Section]\n%s\n"
                    "%04s %16s%10s%10s%10s%10s%10s%30s\n%s") % \
                    (twoLine, "Num", "Value", "Size", "Type", \
                    "Bind", "Vis", "Ndx", "Name", twoLine))

            nrItems = long(sh_size / sh_entsize)
            if nrItems == 0:
                SysMgr.printPipe('\tNone')

            for i in range(0, nrItems):
                if self.is32Bit:
                    st_name, st_value, st_size, \
                        st_info, st_other, st_shndx = \
                        struct.unpack('IIIBBH', \
                        sym_section[i*sh_entsize:(i+1)*sh_entsize])
                # 64-bit #
                else:
                    st_name, st_info, st_other, \
                        st_shndx, st_value, st_size = \
                        struct.unpack('IBBHQQ', \
                        sym_section[i*sh_entsize:(i+1)*sh_entsize])

                # get symbol string #
                symbol = self.getString(strtab_section, st_name)

                # convert manged string #
                symbol = ElfAnalyzer.demangleSymbol(symbol)

                self.attr['symTable'][symbol] = {\
                    'value': st_value, 'size': st_size, \
                    'type': ElfAnalyzer.ST_TYPE[\
                    ElfAnalyzer.ELF_ST_TYPE(st_info)],
                    'bind': ElfAnalyzer.ST_BIND_TYPE[\
                    ElfAnalyzer.ELF_ST_BIND(st_info)], \
                    'vis': ElfAnalyzer.ST_VISIBILITY_TYPE[\
                    ElfAnalyzer.ELF_ST_VISIBILITY(st_other)], \
                    'ndx': st_shndx}

                # parse .sym table #
                if debug:
                    SysMgr.printPipe(\
                        "%04d %016x%10d%10s%10s%10s%10d %s" % \
                        (i, st_value, st_size, \
                        ElfAnalyzer.ST_TYPE[\
                            ElfAnalyzer.ELF_ST_TYPE(st_info)],
                        ElfAnalyzer.ST_BIND_TYPE[\
                            ElfAnalyzer.ELF_ST_BIND(st_info)], \
                        ElfAnalyzer.ST_VISIBILITY_TYPE[\
                            ElfAnalyzer.ELF_ST_VISIBILITY(st_other)], \
                        st_shndx, symbol,))
            if debug:
                SysMgr.printPipe(oneLine)
        else:
            ElfAnalyzer.stripedFiles[path] = True
            SysMgr.printWarn(\
                "Fail to get static symbol of %s (stripped)" % path)

        # parse REL table #
        for idx in e_shrellist:
            sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, \
                sh_link, sh_info, sh_addralign, sh_entsize = \
                self.getSectionInfo(fd, e_shoff + e_shentsize * idx)

            # get symbol string #
            shname = self.getString(str_section, sh_name)

            if debug:
                SysMgr.printPipe((\
                    '\n[%s Section]\n%s\n'
                    '%16s %16s %32s %16s %s\n%s') % \
                    (shname, twoLine, "Offset", "Info", "Type", \
                    "Sym.Value", "Sym.Name", twoLine))

            fd.seek(sh_offset)

            nrItems = long(sh_size / sh_entsize)
            if nrItems == 0:
                SysMgr.printPipe('\tNone')

            for i in range(0, nrItems):
                # 32-bit #
                if self.is32Bit:
                    sh_offset, sh_info = \
                        struct.unpack('II', fd.read(8))

                    rsym = ElfAnalyzer.ELF32_R_SYM(sh_info)
                    rtype = ElfAnalyzer.ELF32_R_TYPE(sh_info)
                # 64-bit #
                else:
                    sh_offset, sh_info = \
                        struct.unpack('QQ', fd.read(16))

                    rsym = ElfAnalyzer.ELF64_R_SYM(sh_info)
                    rtype = ElfAnalyzer.ELF64_R_TYPE(sh_info)

                try:
                    RTYPE = ElfAnalyzer.RELOC_TYPE[rtype]
                except:
                    RTYPE = rtype

                try:
                    symbol = self.attr['dynsymList'][rsym+1]
                except:
                    symbol = rsym

                # convert manged string #
                symbol = ElfAnalyzer.demangleSymbol(symbol)

                # update address on dynsym table #
                if symbol in self.attr['dynsymTable']:
                    if self.attr['dynsymTable'][symbol]['value'] == 0:
                        self.attr['dynsymTable'][symbol]['value'] = sh_offset

                # get address of symbol string #
                if symbol in self.attr['dynsymTable']:
                    saddr = self.attr['dynsymTable'][symbol]['value']
                else:
                    saddr = long(0)

                if debug:
                    SysMgr.printPipe(\
                        '%016x %016x %32s %016x %s' % \
                        (sh_offset, sh_info, RTYPE, saddr, symbol))

            if debug:
                SysMgr.printPipe(oneLine)

        # parse RELA table #
        for idx in e_shrelalist:
            sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, \
                sh_link, sh_info, sh_addralign, sh_entsize = \
                self.getSectionInfo(fd, e_shoff + e_shentsize * idx)

            # get symbol string #
            shname = self.getString(str_section, sh_name)

            if debug:
                SysMgr.printPipe((\
                    '\n[%s Section]\n%s\n'
                    '%16s %16s %32s %16s %s\n%s') % \
                    (shname, twoLine, "Offset", "Info", "Type", \
                    "Sym.Value", "Sym.Name + Addend", twoLine))

            fd.seek(sh_offset)

            nrItems = long(sh_size / sh_entsize)
            if nrItems == 0:
                SysMgr.printPipe('\tNone')

            for i in range(0, nrItems):
                # 32-bit #
                if self.is32Bit:
                    sh_offset, sh_info, sh_addend = \
                        struct.unpack('III', fd.read(12))

                    rsym = ElfAnalyzer.ELF32_R_SYM(sh_info)
                    rtype = ElfAnalyzer.ELF32_R_TYPE(sh_info)
                # 64-bit #
                else:
                    sh_offset, sh_info, sh_addend = \
                        struct.unpack('QQQ', fd.read(24))

                    rsym = ElfAnalyzer.ELF64_R_SYM(sh_info)
                    rtype = ElfAnalyzer.ELF64_R_TYPE(sh_info)

                try:
                    RTYPE = ElfAnalyzer.RELOC_TYPE[rtype]
                except:
                    RTYPE = rtype

                try:
                    symbol = self.attr['dynsymList'][rsym+1]
                except:
                    symbol = rsym

                # convert manged string #
                symbol = ElfAnalyzer.demangleSymbol(symbol)

                # update address on dynsym table #
                if symbol in self.attr['dynsymTable']:
                    if self.attr['dynsymTable'][symbol]['value'] == 0:
                        self.attr['dynsymTable'][symbol]['value'] = sh_offset

                if debug:
                    SysMgr.printPipe(\
                        '%016x %016x %32s %016x %s' % \
                        (sh_offset, sh_info, RTYPE, 0, \
                        '%s + %x' % (symbol, sh_addend)))

            if debug:
                SysMgr.printPipe(oneLine)

        # check dynamic section #
        if e_shdynamic < 0:
            return None

        # parse dynamic section #
        sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, \
            sh_link, sh_info, sh_addralign, sh_entsize = \
            self.getSectionInfo(fd, e_shoff + e_shentsize * e_shdynamic)

        fd.seek(sh_offset)
        dynamic_section = fd.read(sh_size)

        if debug:
            SysMgr.printPipe((\
                '\n[.dynamic Section]\n%s\n'
                '%16s %20s %32s\n%s') % \
                (twoLine, "Tag", "Type", "Name/Value", twoLine))

        nrItems = long(sh_size / sh_entsize)
        if nrItems == 0:
            SysMgr.printPipe('\tNone')

        for i in range(0, nrItems):
            fd.seek(sh_offset + i * sh_entsize)

            if self.is32Bit:
                d_tag, d_un = struct.unpack('II', fd.read(sh_entsize))
            else:
                d_tag, d_un = struct.unpack('QQ', fd.read(sh_entsize))

            if debug:
                if d_tag in ElfAnalyzer.DT_TYPE:
                    if ElfAnalyzer.DT_TYPE[d_tag] == 'NEEDED' or \
                        ElfAnalyzer.DT_TYPE[d_tag] == 'SONAME' or \
                        ElfAnalyzer.DT_TYPE[d_tag] == 'RPATH':
                        SysMgr.printPipe(\
                            '%016x %20s %32s' % \
                            (d_tag, ElfAnalyzer.DT_TYPE[d_tag], \
                            dynsymTable[d_un]))
                    elif ElfAnalyzer.DT_TYPE[d_tag] == 'STRSZ' or \
                        ElfAnalyzer.DT_TYPE[d_tag] == 'SYMENT' or \
                        ElfAnalyzer.DT_TYPE[d_tag] == 'RELSZ' or \
                        ElfAnalyzer.DT_TYPE[d_tag] == 'RELENT' or \
                        ElfAnalyzer.DT_TYPE[d_tag] == 'PLTRELSZ' or \
                        ElfAnalyzer.DT_TYPE[d_tag] == 'VERDEFNUM' or \
                        ElfAnalyzer.DT_TYPE[d_tag] == 'VERNEEDNUM' or \
                        ElfAnalyzer.DT_TYPE[d_tag] == 'RELCOUNT':
                        SysMgr.printPipe(\
                            '%016x %20s %32s' % \
                            (d_tag, ElfAnalyzer.DT_TYPE[d_tag], d_un))
                    else:
                        SysMgr.printPipe(\
                            '%016x %20s %32s' % \
                            (d_tag, ElfAnalyzer.DT_TYPE[d_tag], hex(d_un)))
                else:
                    SysMgr.printPipe(\
                        '%016x %20s %32s' % (d_tag, d_tag, hex(d_un)))

            # NULL termination #
            if d_tag == d_un == 0:
                break

        if debug:
            SysMgr.printPipe(oneLine)





class ThreadAnalyzer(object):
    """ Analyzer for thread profiling """

    reportData = {}
    lifecycleData = {}
    procTotData = {}
    procIntData = []
    procEventData = []
    dbusData = {'totalCnt': long(0), 'totalErr': long(0)}
    dbgObj = None

    # request type #
    requestType = [
        'LOG',
        'EVENT',
        'PRINT',
        'REPORT_ALWAYS',
        'REPORT_BOUND',
    ]

    # default constant to check system status for reporting #
    reportBoundary = {
        'cpu' : {
            'total' : 80
        },
        'mem' : {
            'free' : 50
        },
        'swap' : {
            'usage' : 70
        },
        'block' : {
            'ioWait' : 10
        },
        'storage' : {
            'total' : 99
        },
        'task' : {
            'nrCtx' : 20000
        }
    }

    init_procTotData = \
        {'comm': '', 'ppid': long(0), 'nrThreads': long(0), 'pri': '', \
        'startIdx': long(0), 'cpu': long(0), 'cpuMax': long(0), \
        'cpuMin': long(-1), 'cpuAvg': long(0), 'initMem': long(0), \
        'lastMem': long(0), 'memDiff': long(0), 'blk': long(0), \
        'minMem': long(0), 'maxMem': long(0), 'minVss': long(0), \
        'maxVss': long(0), 'blkrd': long(0), 'blkwr': long(0)}

    init_procIntData = \
        {'cpu': long(0), 'cpuMax': long(0), 'cpuMin': long(-1), \
        'cpuAvg': long(0), 'mem': long(0), 'memDiff': long(0), \
        'blk': long(0), 'blkrd': long(0), 'blkwr': long(0), 'die': False}



    @staticmethod
    def checkFilter(comm, pid):
        found = False

        for idx in list(SysMgr.filterGroup):
            # check exclusion condition #
            if idx.startswith('^'):
                cond = idx[1:]
                if cond in comm or pid == cond:
                    found=False
                    break
                else:
                    found=True
                    continue

            # check inclusion condition #
            if idx in comm or pid == idx:
                found = True
                break

        return found



    @staticmethod
    def doSumReport(fname):
        if not fname:
            SysMgr.printErr("No input file")
            sys.exit(0)

        # load file #
        SysMgr.reloadFileBuffer(fname)

        # recognize data #
        start = end = -1
        reverse = True
        for idx, item in enumerate(SysMgr.procBuffer):
            if 'Top Summary Info' in item:
                reverse = False
            if start == -1 and '[Top Info] ' in item:
                start = idx
            if start >= 0 and not '[Top Info]' in item:
                end = idx
                break

        # check data #
        if start == end == -1:
            SysMgr.printErr(\
                "Fail to recognize %s" % fname)
            sys.exit(0)

        # check data #
        SysMgr.procBuffer = SysMgr.procBuffer[start:end]

        # reverse sequence #
        if reverse:
            SysMgr.procBuffer = list(reversed(SysMgr.procBuffer))

        # print summary #
        ThreadAnalyzer.printIntervalUsage()



    @staticmethod
    def doDiffReports(flist):
        def getProcName(pinfo):
            namelist = pinfo.split('(')
            if len(namelist) <= 2:
                if namelist[0] == '':
                    return '(%s' % namelist[1]
                return namelist[0]
            else:
                return '(%s' % ''.join(namelist[:-1])

        flist = UtilMgr.getFileList(flist)
        if len(flist) < 2:
            SysMgr.printErr(\
                "Fail to get file list to diff, "
                "input at least two effective file paths")
            sys.exit(0)

        # define variable and table #
        nrFiles = len(flist)
        unionCpuList = dict()
        unionGpuList = dict()
        unionRssList = dict()
        statFileList = dict()

        # define total key #
        unionCpuList.setdefault('TOTAL', 0)
        unionRssList.setdefault('FREE', 0)

        # parse stats from multiple files #
        for idx, lfile in enumerate(flist):
            try:
                gstats, cstats = \
                    ThreadAnalyzer.getDrawStats(lfile, applyOpt=False)
            except:
                sys.exit(0)

            # save all stats in a file #
            statFileList[lfile] = gstats

            # define proc usage #
            cpuProcUsage = gstats['cpuProcUsage']
            memProcUsage = gstats['memProcUsage']
            gpuProcUsage = gstats['gpuProcUsage'] = {}

            # get total CPU info #
            cpuUsage = gstats['cpuUsage']
            cpuProcUsage['TOTAL'] = {
                'usage': cpuUsage,
                'average': sum(cpuUsage) / float(len(cpuUsage)),
                'minimum': min(cpuUsage),
                'maximum': max(cpuUsage),
                }

            # get total gpu info #
            gpuProcUsage = gstats['gpuUsage']

            # get total free info #
            memFree = gstats['memFree']
            memProcUsage['FREE'] = {
                'rssUsage': memFree,
                'average': sum(memFree) / len(memFree),
                'minRss': min(memFree),
                'maxRss': max(memFree),
                }

            # remove * characters #
            for pinfo in sorted(cpuProcUsage.keys()):
                if pinfo.startswith('*'):
                    cpuProcUsage[pinfo[1:]] = cpuProcUsage.pop(pinfo)
                else:
                    break

            # merge tasks having same name #
            prevTask = None
            for pinfo in sorted(cpuProcUsage.keys()):
                pname = getProcName(pinfo)

                # convert usage string to list #
                try:
                    cpuProcUsage[pinfo]['usage'] = list(map(long, \
                        cpuProcUsage[pinfo]['usage'].split()))
                except:
                    pass

                # register the first task #
                if prevTask != pname:
                    prevTask = pname

                    target = cpuProcUsage[pinfo]
                    cpuProcUsage.setdefault(pname, target)
                    target['cnt'] = 1
                    target['average'] = \
                        sum(target['usage']) / float(len(target['usage']))
                    if '(' in pinfo:
                        cpuProcUsage.pop(pinfo)

                    continue

                # merge tasks #
                target = cpuProcUsage[pname]
                target['usage'] = list(map(sum, \
                    zip(*[target['usage'], cpuProcUsage[pinfo]['usage']])))

                # update stats #
                target['cnt'] += 1
                target['minimum'] = min(target['usage'])
                target['maximum'] = max(target['usage'])
                target['average'] = \
                    sum(target['usage']) / float(len(target['usage']))

                # pop this task #
                if '(' in pinfo:
                    cpuProcUsage.pop(pinfo)

            # iterate CPU list #
            for pinfo, value in sorted(cpuProcUsage.items()):
                pname = getProcName(pinfo)

                # register comm #
                unionCpuList.setdefault(pname, 0)

                # save diff itself #
                if idx > 0:
                    targetList = dict()
                    prevProcList = statFileList[flist[idx-1]]['cpuProcUsage']

                    for proc, pval in prevProcList.items():
                        if getProcName(proc) == pname:
                            targetList.setdefault(pname, pval)

                    # get diff by average #
                    if len(targetList) == 0:
                        value['diff'] = value['average']
                    elif len(targetList) == 1:
                        target = targetList.popitem()[1]
                        value['diff'] = value['average'] - target['average']
                    else:
                        pass

            # set diff to the union list if this file is lastest one #
            if idx == len(flist)-1:
                prevProcList = statFileList[flist[-2]]['cpuProcUsage']
                lastProcList = statFileList[flist[-1]]['cpuProcUsage']
                for pname, value in unionCpuList.items():
                    if pname in lastProcList:
                        try:
                            unionCpuList[pname] = \
                                lastProcList[pname]['average'] - \
                                    prevProcList[pname]['average']
                        except:
                            unionCpuList[pname] = \
                                lastProcList[pname]['average']
                    elif pname in prevProcList:
                        unionCpuList[pname] = \
                            -(prevProcList[pname]['average'])

            # remove * characters #
            for pinfo in sorted(gpuProcUsage.keys()):
                if pinfo.startswith('*'):
                    gpuProcUsage[pinfo[1:]] = gpuProcUsage.pop(pinfo)
                else:
                    break

            # merge tasks having same name #
            prevTask = None
            for pinfo in sorted(gpuProcUsage.keys()):
                pname = getProcName(pinfo)

                # convert usage string to list #
                try:
                    gusage = list(map(long, gpuProcUsage[pinfo].split()))
                    gpuProcUsage[pinfo] = {
                        'usage': gusage,
                        }
                    gstats['gpuProcUsage'][pinfo] = gpuProcUsage[pinfo]
                except:
                    pass

                # register the first task #
                if prevTask != pname:
                    prevTask = pname

                    target = gpuProcUsage[pinfo]
                    target['cnt'] = 1
                    target['minimum'] = min(target['usage'])
                    target['maximum'] = max(target['usage'])
                    target['average'] = \
                        sum(target['usage']) / float(len(target['usage']))

                    gpuProcUsage.setdefault(pname, target)

                    if '(' in pinfo:
                        gpuProcUsage.pop(pinfo)

                    continue

                # merge tasks #
                target = gpuProcUsage[pname]
                target['usage'] = list(map(sum, \
                    zip(*[target['usage'], gpuProcUsage[pinfo]['usage']])))

                # update stats #
                target['cnt'] += 1
                target['minimum'] = min(target['usage'])
                target['maximum'] = max(target['usage'])
                target['average'] = \
                    sum(target['usage']) / float(len(target['usage']))

                # pop this task #
                if '(' in pinfo:
                    gpuProcUsage.pop(pinfo)

            # iterate gpu list #
            for pinfo, value in gpuProcUsage.items():
                pname = getProcName(pinfo)

                # register comm #
                unionGpuList.setdefault(pname, 0)

                # save diff itself #
                if idx > 0:
                    targetList = dict()
                    prevProcList = statFileList[flist[idx-1]]['gpuProcUsage']

                    for proc, pval in prevProcList.items():
                        if getProcName(proc) == pname:
                            targetList.setdefault(proc, pval)

                    # get diff by average #
                    if len(targetList) == 0:
                        value['diff'] = value['average']
                    elif len(targetList) == 1:
                        target = targetList.popitem()[1]
                        value['diff'] = value['average'] - target['average']
                    else:
                        pass

                # set diff to the union list if this file is lastest one #
                if idx == len(flist)-1:
                    unionGpuList[pname] = value['diff']

            # remove * characters #
            for pinfo in sorted(memProcUsage.keys()):
                if pinfo.startswith('*'):
                    memProcUsage[pinfo[1:]] = memProcUsage.pop(pinfo)
                else:
                    break

            # merge tasks having same name #
            prevTask = None
            for pinfo in sorted(memProcUsage.keys()):
                pname = getProcName(pinfo)

                # convert usage string to list #
                try:
                    rssList = memProcUsage[pinfo]['rssUsage']
                    if type(rssList) is str:
                        rssList = rssList.split()
                    memProcUsage[pinfo]['rssUsage'] = list(map(long, rssList))
                except:
                    continue

                # register the first task #
                if prevTask != pname:
                    prevTask = pname

                    target = memProcUsage[pinfo]
                    memProcUsage.setdefault(pname, target)
                    target['cnt'] = 1
                    target['minRss'] = min(target['rssUsage'])
                    target['maxRss'] = max(target['rssUsage'])
                    target['avgRss'] = \
                        sum(target['rssUsage']) / len(target['rssUsage'])
                    if '(' in pinfo:
                        memProcUsage.pop(pinfo)

                    continue

                # merge tasks #
                target = memProcUsage[pname]
                target['rssUsage'] = list(map(sum, \
                    zip(*[target['rssUsage'], memProcUsage[pinfo]['rssUsage']])))

                # update stats #
                target['cnt'] += 1
                target['minRss'] = min(target['rssUsage'])
                target['maxRss'] = max(target['rssUsage'])
                target['avgRss'] = \
                    sum(target['rssUsage']) / len(target['rssUsage'])

                # pop this task #
                if '(' in pinfo:
                    memProcUsage.pop(pinfo)

            # iterate rss list #
            for pinfo, value in memProcUsage.items():
                pname = getProcName(pinfo)

                # register comm #
                unionRssList.setdefault(pname, 0)

                # set stat #
                if pname == 'FREE':
                    stat = 'minRss'
                else:
                    stat = 'maxRss'

                # save diff itself #
                if idx > 0:
                    targetList = dict()
                    prevProcList = statFileList[flist[idx-1]]['memProcUsage']

                    for proc, pval in prevProcList.items():
                        if getProcName(proc) == pname:
                            targetList.setdefault(proc, pval)

                    # get diff by average #
                    try:
                        if len(targetList) == 0:
                            if stat in value:
                                value['diff'] = value[stat]
                        elif len(targetList) == 1:
                            target = targetList.popitem()[1]
                            if stat in value:
                                value['diff'] = value[stat] - target[stat]
                        else:
                            pass
                    except:
                        continue

            # set diff to the union list if this file is lastest one #
            if idx == len(flist)-1:
                prevProcList = statFileList[flist[-2]]['memProcUsage']
                lastProcList = statFileList[flist[-1]]['memProcUsage']
                for pname, value in unionRssList.items():
                    # set stat #
                    if pname == 'FREE':
                        stat = 'minRss'
                    else:
                        stat = 'maxRss'

                    if pname in lastProcList:
                        try:
                            unionRssList[pname] = \
                                lastProcList[pname][stat] - \
                                    prevProcList[pname][stat]
                        except:
                            unionRssList[pname] = \
                                lastProcList[pname][stat]
                    elif pname in prevProcList:
                        unionRssList[pname] = \
                            -(prevProcList[pname][stat])

        # print CPU diff #
        SysMgr.printPipe('\n[Diff CPU Info]\n%s' % twoLine)

        emptyCpuStat = "%7s(%2s)(%7s/%7s/%7s)" % \
            ('-', '-', '-', '-', '-')
        menuStat = "%7s(%2s)(%7s/%7s/%7s)" % \
            ('Diff', 'Nr', 'Min', 'Avg', 'Max')
        lenCpuStat = len(emptyCpuStat)

        # print file names #
        totalBuf = ""
        menuBuf = "{0:^16} | ".format('Task')
        printBuf = "{0:^16} | ".format('File')
        for fname in flist:
            printBuf = \
                ('{0:1} {1:^%d}' % len(emptyCpuStat)).format(printBuf, fname)
            menuBuf = \
                ('{0:1} {1:^%d}' % len(menuStat)).format(menuBuf, menuStat)
        printBuf = "%s\n%s\n%s\n%s" % (printBuf, oneLine, menuBuf, twoLine)
        SysMgr.printPipe(printBuf)

        for pname, value in sorted(\
            unionCpuList.items(), key=lambda e:float(e[1]), reverse=True):
            printBuf = "%16s | " % pname
            for idx, fname in enumerate(flist):
                try:
                    prevCpuProcList = statFileList[flist[idx-1]]['cpuProcUsage']
                except:
                    prevCpuProcList = None

                cpuProcList = statFileList[fname]['cpuProcUsage']

                # no target process in this file #
                if not pname in cpuProcList:
                    if idx > 0 and prevCpuProcList and pname in prevCpuProcList:
                        printBuf = '%s %6.1f%%%s' % \
                            (printBuf, -(prevCpuProcList[pname]['average']), \
                                emptyCpuStat[7:])
                    else:
                        printBuf = '%s %s' % (printBuf, emptyCpuStat)
                    continue

                cpuProcStat = cpuProcList[pname]
                if not 'diff' in cpuProcStat:
                    diff = '-'
                elif cpuProcStat['diff'] > 0:
                    diff = '{0:>6}%'.format(\
                        '%6s' % ('+%.1f' % cpuProcStat['diff']))
                elif cpuProcStat['diff'] < 0:
                    diff = '{0:>6}%'.format(\
                        '%6s' % ('-%.1f' % abs(cpuProcStat['diff'])))
                else:
                    diff = '0'

                newStat = "%7s(%2d)(%6.1f%%/%6.1f%%/%6.1f%%)" % \
                    (diff, cpuProcStat['cnt'], \
                        cpuProcStat['minimum'], cpuProcStat['average'], \
                        cpuProcStat['maximum'])

                printBuf = '%s %s' % (printBuf, newStat)

            if pname == 'TOTAL':
                totalBuf = printBuf
            else:
                SysMgr.addPrint(printBuf + '\n', force=True)

        SysMgr.printPipe('%s\n%s' % (totalBuf, oneLine))

        SysMgr.doPrint(newline=False, clear=True)

        if len(unionCpuList) < 2:
            SysMgr.printPipe('\tNone')

        SysMgr.printPipe(oneLine)

        # print GPU diff #
        SysMgr.printPipe('\n[Diff GPU Info]\n%s' % twoLine)

        emptyGpuStat = "%7s(%2s)(%7s/%7s/%7s)" % \
            ('-', '-', '-', '-', '-')
        menuStat = "%7s(%2s)(%7s/%7s/%7s)" % \
            ('Diff', 'Nr', 'Min', 'Avg', 'Max')
        lenGpuStat = len(emptyCpuStat)

        menuBuf = "{0:^16} | ".format('Task')
        printBuf = "{0:^16} | ".format('File')
        for fname in flist:
            printBuf = \
                ('{0:1} {1:^%d}' % len(emptyGpuStat)).format(printBuf, fname)
            menuBuf = \
                ('{0:1} {1:^%d}' % len(menuStat)).format(menuBuf, menuStat)
        printBuf = "%s\n%s\n%s\n%s" % (printBuf, oneLine, menuBuf, twoLine)
        SysMgr.printPipe(printBuf)

        for pname, value in sorted(\
            unionGpuList.items(), key=lambda e:float(e[1]), reverse=True):
            printBuf = "%16s | " % pname
            for idx, fname in enumerate(flist):
                try:
                    prevGpuProcList = statFileList[flist[idx-1]]['gpuProcUsage']
                except:
                    prevGpuProcList = None

                gpuProcList = statFileList[fname]['gpuProcUsage']

                # no target process in this file #
                if not pname in gpuProcList:
                    if idx > 0 and prevGpuProcList and pname in prevGpuProcList:
                        printBuf = '%s %6.1f%%%s' % \
                            (printBuf, -(prevGpuProcList[pname]['average']), \
                                emptyGpuStat[7:])
                    else:
                        printBuf = '%s %s' % (printBuf, emptyGpuStat)
                    continue

                gpuProcStat = gpuProcList[pname]
                if not 'diff' in gpuProcStat:
                    diff = '-'
                elif gpuProcStat['diff'] > 0:
                    diff = '{0:>6}%'.format(\
                        '%6s' % ('+%.1f' % gpuProcStat['diff']))
                elif gpuProcStat['diff'] < 0:
                    diff = '{0:>6}%'.format(\
                        '%6s' % ('-%.1f' % abs(gpuProcStat['diff'])))
                else:
                    diff = '0'

                newStat = "%7s(%2d)(%6.1f%%/%6.1f%%/%6.1f%%)" % \
                    (diff, gpuProcStat['cnt'], \
                        gpuProcStat['minimum'], gpuProcStat['average'], \
                        gpuProcStat['maximum'])

                printBuf = '%s %s' % (printBuf, newStat)

            SysMgr.addPrint(printBuf + '\n', force=True)

        SysMgr.doPrint(newline=False, clear=True)

        if len(unionGpuList) == 0:
            SysMgr.printPipe('\tNone')

        SysMgr.printPipe(oneLine)

        # check memory type #
        if SysMgr.pssEnable:
            mtype = 'PSS'
        elif SysMgr.ussEnable:
            mtype = 'USS'
        else:
            mtype = 'RSS'

        # print memory diff #
        SysMgr.printPipe(\
            '\n[Diff %s Info]\n%s' % (mtype, twoLine))

        emptyRssStat = "%7s(%2s)(%7s/%7s/%7s)" % \
            ('-', '-', '-', '-', '-')
        menuStat = "%7s(%2s)(%7s/%7s/%7s)" % \
            ('Diff', 'Nr', 'Min', 'Avg', 'Max')
        lenRssStat = len(emptyRssStat)

        totalBuf = ""
        menuBuf = "{0:^16} | ".format('Task')
        printBuf = "{0:^16} | ".format('File')
        for fname in flist:
            printBuf = \
                ('{0:1} {1:^%d}' % len(emptyRssStat)).format(printBuf, fname)
            menuBuf = \
                ('{0:1} {1:^%d}' % len(menuStat)).format(menuBuf, menuStat)
        printBuf = "%s\n%s\n%s\n%s" % (printBuf, oneLine, menuBuf, twoLine)
        SysMgr.printPipe(printBuf)

        for pname, value in sorted(\
            unionRssList.items(), key=lambda e:long(e[1]), reverse=True):
            printBuf = "%16s | " % pname
            for idx, fname in enumerate(flist):
                try:
                    prevRssProcList = statFileList[flist[idx-1]]['memProcUsage']
                except:
                    prevRssProcList = None

                rssProcList = statFileList[fname]['memProcUsage']

                # no target process in this file #
                if not pname in rssProcList:
                    if idx > 0 and prevRssProcList and pname in prevRssProcList:
                        printBuf = '%s %6dM%s' % \
                            (printBuf, -(prevRssProcList[pname]['maxRss']), \
                                emptyRssStat[7:])
                    else:
                        printBuf = '%s %s' % (printBuf, emptyRssStat)
                    continue

                rssProcStat = rssProcList[pname]
                if not 'diff' in rssProcStat:
                    diff = '-'
                elif rssProcStat['diff'] > 0:
                    diff = '{0:>6}M'.format('+%s' % rssProcStat['diff'])
                elif rssProcStat['diff'] < 0:
                    diff = '{0:>6}M'.format('-%s' % abs(rssProcStat['diff']))
                else:
                    diff = '0'

                newStat = "%7s(%2d)(%6dM/%6dM/%6dM)" % \
                    (diff, rssProcStat['cnt'], \
                        rssProcStat['minRss'], rssProcStat['avgRss'], \
                        rssProcStat['maxRss'])

                printBuf = '%s %s' % (printBuf, newStat)

            if pname == 'FREE':
                totalBuf = printBuf
            else:
                SysMgr.addPrint(printBuf + '\n', force=True)

        SysMgr.printPipe('%s\n%s' % (totalBuf, oneLine))

        SysMgr.doPrint(newline=False, clear=True)

        if len(unionRssList) < 2:
            SysMgr.printPipe('\tNone')

        SysMgr.printPipe(oneLine)



    def __init__(self, file=None, onlyInstance=None):

        # thread mode #
        if file:
            self.initThreadData()

            self.init_threadData = \
                {'comm': '', 'usage': float(0), 'cpuRank': long(0), \
                'yield': long(0), 'cpuWait': float(0), 'pri': '?', \
                'reqRdBlock': long(0), 'readBlock': long(0), 'ioRank': long(0), \
                'irq': float(0), 'reclaimWait': float(0), 'reclaimCnt': long(0), \
                'ptid': '-'*5, 'new': ' ', 'die': ' ', 'preempted': long(0), \
                'preemption': long(0), 'start': float(0), 'stop': float(0), \
                'ioRdWait': float(0), 'readQueueCnt': long(0), \
                'readStart': float(0), 'maxRuntime': float(0), \
                'coreSchedCnt': long(0), 'longRunCore': long(-1), \
                'dReclaimWait': float(0), 'dReclaimStart': float(0), \
                'migrate': long(0), 'dReclaimCnt': long(0), 'ftxMax': float(0), \
                'ftxLockCnt': long(0), 'ftxEnter': float(0), 'ftxLock': float(0), \
                'ftxTotal': float(0), 'ftxWaitCnt': long(0), \
                'ftxProcess': float(0), 'ftxLockMax': float(0), 'ftxStat': '?', \
                'ftxLSwitch': long(0), 'ftxBlockTotal': float(0), \
                'ftxLBlockTotal': float(0), 'ftxBlock': float(0), \
                'ftxLBlock': float(0), 'ftxBlockCnt': long(0), \
                'ftxEnt': None, 'lastStatus': 'N', 'offCnt': long(0), \
                'offTime': float(0), 'waitStartAsParent': float(0), \
                'nrPages': long(0), 'reclaimedPages': long(0), 'waitPid': long(0), \
                'remainKmem': long(0), 'wasteKmem': long(0), 'childList': None, \
                'kernelPages': long(0), 'readBlockCnt': long(0), \
                'writeBlock': long(0), 'writeBlockCnt': long(0), 'tgid': '-'*5, \
                'cachePages': long(0), 'userPages': long(0), 'lastOff': float(0), \
                'maxPreempted': float(0), 'anonReclaimedPages': long(0), \
                'lastIdleStatus': long(0), 'createdTime': float(0), \
                'waitChild': float(0), 'waitParent': float(0), \
                'customEvent': None, 'userEvent': None, 'kernelEvent': None, \
                'blkCore': long(0), 'lockWait': float(0), 'lockTime': float(0), \
                'lockCnt': long(0), 'tryLockCnt': long(0), \
                'lastLockTime': float(0), 'lastLockWait': float(0), \
                'reqWrBlock': long(0), 'writeQueueCnt': long(0), \
                'writeBlockCnt': long(0), 'writeStart': float(0), \
                'ioWrWait': float(0), 'awriteBlock': long(0), \
                'awriteBlockCnt': long(0), 'schedLatency': float(0), \
                'schedReady': float(0), 'lastNrSyscall': long(-1), \
                'nrSyscall': long(0)}

            self.init_irqData = \
                {'name': None, 'usage': float(0), 'start': float(0), \
                'max': float(0), 'min': float(0), 'maxPeriod': float(0), \
                'minPeriod': float(0), 'count': long(0)}

            self.init_intData = \
                {'time': float(0), 'firstLogTime': float(0), 'cpuPer': float(0), \
                'totalUsage': float(0), 'totalMemUsage': long(0), \
                'brUsage': long(0), 'totalBrUsage': long(0), 'irqUsage': float(0), \
                'kmemUsage': long(0), 'totalKmemUsage': long(0), \
                'coreSchedCnt': long(0), 'totalCoreSchedCnt': long(0), \
                'preempted': float(0), 'totalBwUsage': long(0), \
                'totalPreempted': float(0), 'new': ' ', 'die': ' ', \
                'bwUsage': long(0), 'cpuUsage': float(0), 'memUsage': long(0)}

            self.init_eventData = \
                {'count': long(0), 'start': float(0), 'usage': float(0), \
                'max': float(0), 'min': float(0), 'maxPeriod': float(0), \
                'minPeriod': float(0)}

            self.init_kmallocData = \
                {'tid': '0', 'caller': '0', 'ptr': '0', 'req': long(0), \
                'alloc': long(0), 'time': '0', 'waste': long(0), 'core': long(0)}

            self.wakeupData = \
                {'tid': '0', 'nr': '0', 'ret': '0', 'time': '0', 'args': '0', \
                'valid': long(0), 'from': '0', 'to': '0', 'corrupt': '0'}

            self.init_syscallInfo = \
                {'usage': float(0), 'last': float(0), 'count': long(0), \
                'max': float(0), 'min': float(0), 'err': long(0)}

            self.init_pageData = \
                {'tid': '0', 'page': '0', 'flags': '0', 'type': '0', 'time': '0'}
            self.init_lastJob = \
                {'job': '0', 'time': '0', 'tid': '0', 'prevWakeupTid': '0'}
            self.init_preemptData = \
                {'usage': float(0), 'count': long(0), 'max': float(0)}

            self.finishTime = '0'
            self.lastTidPerCore = {}
            self.lastCore = '0'
            self.lastEvent = '0'

        # top mode #
        else:
            self.init_procData = \
                {'isMain': bool(False), 'tids': None, 'stat': None, \
                'io': None, 'alive': False, 'runtime': float(0), \
                'changed': True, 'new': bool(False), 'majflt': long(0), \
                'ttime': long(0), 'cttime': long(0), 'utime': long(0), \
                'stime': long(0), 'taskPath': None, 'statm': None, \
                'mainID': '', 'btime': long(0), 'maps': None, 'status': None}

            self.init_cpuData = \
                {'user': long(0), 'system': long(0), 'nice': long(0), \
                'idle': long(0), 'wait': long(0), 'irq': long(0), \
                'softirq': long(0)}

            self.nrThread = long(0)
            self.nrPrevThread = long(0)
            self.nrProcess = long(0)
            self.nrPrevProcess = long(0)
            self.nrFd = long(0)
            self.procData = {}
            self.prevProcData = {}
            self.nsData = {}
            self.fileData = {}
            self.cpuData = {}
            self.gpuData = {}
            self.prevCpuData = {}
            self.irqData = {}
            self.prevIrqData = {}
            self.zoneData = {}
            self.prevZoneData = {}
            self.memData = {}
            self.prevMemData = {}
            self.vmData = {}
            self.prevVmData = {}
            self.stackTable = {}
            self.prevSwaps = None
            self.abnormalTaskList = {}

            # set index of attributes #
            self.majfltIdx = ConfigMgr.STAT_ATTR.index("MAJFLT")
            self.utimeIdx = ConfigMgr.STAT_ATTR.index("UTIME")
            self.stimeIdx = ConfigMgr.STAT_ATTR.index("STIME")
            self.cutimeIdx = ConfigMgr.STAT_ATTR.index("CUTIME")
            self.cstimeIdx = ConfigMgr.STAT_ATTR.index("CSTIME")
            self.btimeIdx = ConfigMgr.STAT_ATTR.index("DELAYBLKTICK")
            self.commIdx = ConfigMgr.STAT_ATTR.index("COMM")
            self.ppidIdx = ConfigMgr.STAT_ATTR.index("PPID")
            self.nrthreadIdx = ConfigMgr.STAT_ATTR.index("NRTHREAD")
            self.prioIdx = ConfigMgr.STAT_ATTR.index("PRIORITY")
            self.policyIdx = ConfigMgr.STAT_ATTR.index("POLICY")
            self.vssIdx = ConfigMgr.STAT_ATTR.index("VSIZE")
            self.rssIdx = ConfigMgr.STAT_ATTR.index("RSS")
            self.scodeIdx = ConfigMgr.STAT_ATTR.index("STARTCODE")
            self.ecodeIdx = ConfigMgr.STAT_ATTR.index("ENDCODE")
            self.statIdx = ConfigMgr.STAT_ATTR.index("STATE")
            self.starttimeIdx = ConfigMgr.STAT_ATTR.index("STARTTIME")
            self.sidIdx = ConfigMgr.STAT_ATTR.index("SESSIONID")
            self.pgrpIdx = ConfigMgr.STAT_ATTR.index("PGRP")
            self.shrIdx = ConfigMgr.STATM_TYPE.index("SHR")

            # initialize netlink socket #
            try:
                SysMgr.initNetlink()
            except:
                SysMgr.printWarn(\
                    "Fail to initialize netlink", reason=True)

            # check to return just instance #
            if onlyInstance:
                return

            if SysMgr.graphEnable:
                # convert text-based statistics to images #
                if SysMgr.inputParam:
                    self.drawStats(SysMgr.inputParam)
                # no path for statistics file #
                else:
                    SysMgr.printErr((\
                        "wrong option used, "
                        "use also -I option to load statistics data"))
                sys.exit(0)

            # set system maximum fd number #
            SysMgr.setMaxFd()

            # set default interval #
            if SysMgr.intervalEnable == 0:
                SysMgr.intervalEnable = 1

            # remove wrong filter #
            if len(SysMgr.filterGroup) > 0:
                for idx, val in enumerate(SysMgr.filterGroup):
                    if len(val) == 0:
                        SysMgr.filterGroup.pop(idx)

                taskList = ', '.join(SysMgr.filterGroup)

                if SysMgr.fileTopEnable:
                    pass
                elif SysMgr.groupProcEnable:
                    if SysMgr.processEnable:
                        SysMgr.printInfo((\
                            "only specific processes that are involved "
                            "in the process group [ %s ] are shown") % \
                                taskList)
                    else:
                        SysMgr.printInfo((\
                            "only specific threads that are involved "
                            "in the process group [ %s ] are shown") % \
                                taskList)
                elif SysMgr.processEnable:
                    SysMgr.printInfo(\
                        "only specific processes [ %s ] are shown" % \
                        taskList)
                else:
                    SysMgr.printInfo(\
                        "only specific threads [ %s ] are shown" % \
                        taskList)

            # set network configuration #
            if not SysMgr.findOption('x'):
                NetworkMgr.setServerNetwork(None, None)

            # set configuration #
            if 'boundary' in ConfigMgr.confData:
                confData = ConfigMgr.confData
                if type(confData) is str:
                    confData = UtilMgr.convStr2Dict('\n'.join(confData))
                ThreadAnalyzer.reportBoundary = confData

            # set log buffer size #
            if SysMgr.bufferSize == -1:
                # default unlimited #
                SysMgr.bufferSize = long(0)
            else:
                # change unit from KB to Byte #
                SysMgr.bufferSize = long(SysMgr.bufferSize) << 10

            if SysMgr.printFile:
                SysMgr.printStat(\
                    r"start profiling... [ STOP(Ctrl+c), SAVE(Ctrl+\) ]")

            # file top mode #
            if SysMgr.fileTopEnable:
                self.runFileTop()
            # DLT top mode #
            elif SysMgr.dltTopEnable:
                DltAnalyzer.runDltReceiver(mode='top')
            elif SysMgr.dbusTopEnable:
                DbusAnalyzer.runDbusSnooper(mode='top')

            # print system general info in advance #
            if SysMgr.printFile and SysMgr.pipeEnable and SysMgr.exitFlag:
                SysMgr.printLogo(big=True)
                SysMgr.sysInstance.saveSysStat()
                SysMgr.printInfoBuffer()
                SysMgr.printPipe('\n')

            # request service to remote server #
            self.requestService()

            # process top mode #
            self.runProcTop()

            # terminate top mode #
            sys.exit(0)



        #-------------------- THREAD MODE --------------------#
        # change default CPU property #
        SysMgr.cpuEnable = False

        # initialize preempt thread list #
        if SysMgr.preemptGroup:
            for index in SysMgr.preemptGroup:
                '''
                preempted state
                [preemptBit, threadList, startTime, core, totalUsage] #
                '''
                self.preemptData.append([False, {}, float(0), 0, float(0)])

        # read trace data #
        lines = ThreadAnalyzer.readTraceData(file)

        # save trace data and stop analysis #
        if SysMgr.outputFile:
            SysMgr.saveTraceData(lines)
            sys.exit(0)

        # get process tree #
        SysMgr.getProcTreeInfo()

        # start parsing logs #
        SysMgr.printStat(\
            'start analyzing... [ STOP(Ctrl+c) ]')
        SysMgr.totalLine = len(lines)

        for idx, log in enumerate(lines):
            time = self.parse(log)
            UtilMgr.printProgress(idx, SysMgr.totalLine)

            # save last job per core #
            self.lastJob.setdefault(self.lastCore, dict(self.init_lastJob))

            self.lastJob[self.lastCore]['job'] = self.lastEvent
            self.lastJob[self.lastCore]['time'] = self.finishTime

            if self.stopFlag:
                break

        # update finish time #
        if self.finishTime == '0':
            self.finishTime = time

        UtilMgr.deleteProgress()

        # update anonymous comm #
        for idx, val in self.threadData.items():
            if val['comm'] == '<...>':
                val['comm'] = '?'

        # add comsumed time of jobs not finished yet to each threads #
        for idx, val in self.lastTidPerCore.items():
            if self.threadData[val]['lastStatus'] == 'S':
                # apply core off time #
                coreId = '0[%s]' % idx
                if self.threadData[coreId]['lastOff'] > 0:
                    self.threadData[coreId]['usage'] += \
                        float(self.finishTime) - self.threadData[coreId]['start']
                continue
            self.threadData[val]['usage'] += \
                (float(self.finishTime) - float(self.threadData[val]['start']))

        # add lock time of jobs not finished yet to each threads #
        if SysMgr.lockEnable:
            for idx, item in self.threadData.items():
                if item['ftxEnter'] > 0:
                    # elapsed time #
                    wtime = float(self.finishTime) - item['ftxEnter']
                    item['ftxTotal'] += wtime
                    if item['ftxMax'] < wtime:
                        item['ftxMax'] = wtime

                    # CPU time #
                    if item['start'] > item['ftxEnter']:
                        ctime = float(self.finishTime) - item['start']
                        item['ftxProcess'] += ctime
                    elif item['ftxBlock'] == 0 and item['ftxLBlock'] == 0:
                        ctime = float(self.finishTime) - item['ftxEnter']
                        item['ftxProcess'] += ctime

                    # wait time #
                    if item['ftxBlock'] > 0:
                        wtime = float(self.finishTime) - item['ftxBlock']
                        item['ftxBlockTotal'] += wtime
                    if item['ftxLBlock'] > 0:
                        wtime = float(self.finishTime) - item['ftxLBlock']
                        item['ftxLBlockTotal'] += wtime

                if not 'futexObj' in item:
                    continue

                # lock time #
                for obj, time in item['futexObj'].items():
                    ltime = float(self.finishTime) - time
                    item['ftxLock'] += ltime
                    if item['ftxLockMax'] < ltime:
                        item['ftxLockMax'] = ltime

        # add block waiting time of jobs not finished yet to each threads #
        if SysMgr.blockEnable:
            # waiting for read #
            for idx, item in sorted(\
                self.threadData.items(), \
                key=lambda e: e[1]['readStart'], reverse=True):

                if item['readStart'] > 0:
                    waitTime = float(self.finishTime) - item['readStart']
                    item['ioRdWait'] += waitTime
                    self.threadData[item['blkCore']]['ioRdWait'] += waitTime
                    item['readStart'] = long(0)
                else:
                    break

            # waiting for synchronous write #
            for idx, item in sorted(\
                self.threadData.items(), \
                key=lambda e: e[1]['writeStart'], reverse=True):

                # cancel to add blocking time for write because async write #
                break
                '''
                if item['writeStart'] > 0:
                    waitTime = float(self.finishTime) - item['writeStart']
                    item['ioWrWait'] += waitTime
                    self.threadData[item['blkCore']]['ioWrWait'] += waitTime
                    item['writeStart'] = long(0)
                else:
                    break
                '''

            # warn uncompleted block request #
            if len(self.ioData) > 0:
                SysMgr.printWarn(\
                    "Fail to handle %s block requests" % len(self.ioData))

        # calculate usage of threads in last interval #
        self.processIntervalData(self.finishTime)

        if len(self.threadData) == 0:
            SysMgr.printErr(\
                "No recognized data in %s" % SysMgr.inputFile)
            sys.exit(0)

        self.totalTime = \
            round(float(self.finishTime) - float(SysMgr.startTime), 7)

        # apply filter #
        if SysMgr.filterGroup != []:
            # make parent list #
            plist = {}
            if SysMgr.groupProcEnable:
                for key, value in self.threadData.items():
                    for item in SysMgr.filterGroup:
                        if item in value['comm']:
                            plist[value['tgid']] = long(0)

            for key in list(self.threadData.keys()):
                # except for core #
                if key.startswith('0['):
                    continue

                if not SysMgr.isExceptTarget(\
                    key, self.threadData, plist=plist):
                    continue

                # remove thread #
                try:
                    self.threadData.pop(key, None)
                except:
                    continue



    def __del__(self):
        pass



    def runFileTop(self):
        def getFilter(init=False):
            procFilter = []
            fileFilter = []

            if SysMgr.filterGroup == []:
                return [procFilter, fileFilter]

            newFilter = ','.join(SysMgr.filterGroup)
            newFilter = newFilter.split(':')

            for pval in newFilter[0].split(','):
                if pval != '':
                    procFilter.append(pval)
            if len(newFilter) > 1:
                for fval in newFilter[1].split(','):
                    if fval != '':
                        fileFilter.append(fval)

            if init and len(procFilter) > 0:
                SysMgr.printInfo(\
                    "only specific processes including [ %s ] are shown" % \
                        ', '.join(procFilter))

            if init and len(fileFilter) > 0:
                SysMgr.printInfo(\
                    "only specific files including [ %s ] are shown" % \
                        ', '.join(fileFilter))

            return [procFilter, fileFilter]

        SysMgr.checkPerm()

        if not os.path.isdir(SysMgr.procPath):
            SysMgr.printErr("Fail to access proc filesystem")
            sys.exit(0)

        # import select package in the foreground #
        if not SysMgr.printFile:
            SysMgr.getPkg('select', False)

        prevFilter = []

        # initialize task stat #
        ThreadAnalyzer.dbgObj = Debugger(SysMgr.pid, attach=False)
        ThreadAnalyzer.dbgObj.initValues()
        ThreadAnalyzer.dbgObj.getCpuUsage()

        while 1:
            # save timestamp #
            prevTime = time.time()

            # update proc and file filter #
            if prevFilter != SysMgr.filterGroup:
                nowFilter = getFilter(True)
                prevFilter = SysMgr.filterGroup
            else:
                nowFilter = getFilter()

            # collect file stats as soon as possible #
            self.saveFileStat(nowFilter)

            # print system status #
            self.printFileStat(nowFilter)

            # flush socket cache #
            SysMgr.udpListCache = \
                SysMgr.tcpListCache = None

            # check repeat count #
            SysMgr.checkProgress()

            # reset system status #
            self.reinitStats()

            # write user command #
            SysMgr.writeTraceCmd('AFTER')

            # get delayed time #
            delayTime = time.time() - prevTime
            if delayTime > SysMgr.intervalEnable:
                waitTime = 0.000001
            else:
                waitTime = SysMgr.intervalEnable - delayTime

            # wait for next interval #
            if not SysMgr.waitUserInput(\
                waitTime, msg="Press enter key..."):
                time.sleep(waitTime)



    def runProcTop(self):
        if not os.path.isdir(SysMgr.procPath):
            SysMgr.printErr("Fail to access proc filesystem")
            sys.exit(0)

        # initialize perf events #
        SysMgr.initSystemPerfEvents()

        # import select package in the foreground #
        if not SysMgr.printFile:
            SysMgr.getPkg('select', False)

        # run loop #
        while 1:
            if SysMgr.remoteServObj:
                # receive response from server #
                ret = SysMgr.localServObj.recvfrom()

                # handle response from server #
                self.handleServerResponse(ret)

                continue

            # collect system stats as soon as possible #
            self.saveSystemStat()

            # save timestamp #
            prevTime = time.time()

            if self.prevCpuData != {}:
                # print system status #
                self.printSystemStat()

                if SysMgr.elasticEnable:
                    # report system status for elastic stack
                    self.reportSystemStatElastic()
                else:
                    # report system status #
                    self.reportSystemStat()

            # check repeat count #
            SysMgr.checkProgress()

            # reset system status #
            self.reinitStats()

            # write user command #
            SysMgr.writeTraceCmd('AFTER')

            # get delayed time #
            delayTime = time.time() - prevTime
            if delayTime > SysMgr.intervalEnable:
                waitTime = 0.000001
            else:
                waitTime = SysMgr.intervalEnable - delayTime

            if SysMgr.stackEnable and self.stackTable != {}:
                # get stack of threads #
                self.sampleStack(waitTime)
                SysMgr.waitUserInput(0.000001)
            else:
                # wait for next interval #
                if not SysMgr.waitUserInput(waitTime):
                    time.sleep(waitTime)

            # check request from client #
            self.checkServer()



    def saveProcInstance(self):
        del self.prevProcData
        self.prevProcData = self.procData
        self.procData = {}
        SysMgr.topInstance = self
        SysMgr.procInstance = self.procData



    def reinitStats(self):
        del self.prevCpuData
        self.prevCpuData = self.cpuData
        self.nsData = {}
        self.cpuData = {}
        self.fileData = {}
        self.abnormalTaskList = {}
        self.nrPrevThread = self.nrThread
        self.nrPrevProcess = self.nrProcess
        self.nrThread = long(0)
        self.nrProcess = long(0)
        self.nrFd = long(0)
        SysMgr.jsonData = {}



    @staticmethod
    def getDrawStats(logFile, applyOpt=True):
        logBuf = None
        infoBuf = None

        chartStats = {}

        timeline = []
        eventList = []

        cpuUsage = []
        nrCore = []
        memFree = []
        memAnon = []
        memCache = []
        swapUsage = []
        reclaimBg = []
        reclaimDr = []
        blkWait = []
        blkRead = []
        blkWrite = []
        netRead = []
        netWrite = []
        gpuUsage = {}
        cpuProcUsage = {}
        memProcUsage = {}
        blkProcUsage = {}
        storageUsage = {}
        networkUsage = {}

        # get file handle #
        try:
            fd = UtilMgr.getTextLines(logFile, retfd=True)
        except:
            SysMgr.printErr("Fail to read %s\n" % logFile)
            sys.exit(0)

        SysMgr.printStat(\
            r"start processing %s..." % logFile)

        # context varaible #
        finalLine = long(0)
        context = None
        totalRam = None

        # get total size #
        try:
            totalSize = os.stat(logFile).st_size
        except:
            totalSize = long(0)

        curSize = long(0)
        for idx, line in enumerate(fd):
            curSize += len(line)
            UtilMgr.printProgress(curSize, totalSize)

            # get system info #
            if len(SysMgr.systemInfoBuffer) == 0 and \
                line.startswith('[System General Info]'):
                infoBuf = ''
            elif infoBuf is not None:
                if line.startswith('['):
                    # apply launch option #
                    SysMgr.systemInfoBuffer = infoBuf
                    if applyOpt:
                        SysMgr.applyLaunchOption()
                    infoBuf = None
                    continue
                elif line.startswith('=') or line.startswith(' '):
                    continue
                else:
                    infoBuf += line
                    continue

            # split line #
            sline = line.split('|')
            slen = len(sline)

            # get context #
            if line.startswith('[Top '):
                pid = long(0)
                average = long(0)
                maxVss = long(0)
                maxRss = long(0)
                maxUsage = long(0)
                pname = None
                gname = None
                intervalList = None

                contextlist = line.split()

                # termination #
                if len(contextlist) > 5:
                    strPos = line.find('[RAM')
                    sline = line[strPos:].split()

                    try:
                        totalRam = UtilMgr.convUnit2Size(sline[1][:-1])
                    except:
                        pass

                    try:
                        totalSwap = UtilMgr.convUnit2Size(sline[3][:-1])
                    except:
                        totalSwap = None

                    break

                # change context #
                context = contextlist[1]

            # Summary #
            if context == 'Summary':
                nrStatistics = 15

                if slen < nrStatistics:
                    continue

                try:
                    idx = long(sline[0])
                except:
                    continue

                try:
                    timeline.append(long(float(sline[1].split('-')[1])))
                except:
                    timeline.append(0)

                eventList.append(list())

                try:
                    cpuUsage.append(long(sline[2]))
                except:
                    cpuUsage.append(0)

                try:
                    memStat = sline[3].split('/')
                    if len(memStat) != 3:
                        raise Exception()
                    memFree.append(long(memStat[0]))
                    memAnon.append(long(memStat[1]))
                    memCache.append(long(memStat[2]))
                except:
                    # for backward compatibility #
                    try:
                        memFree.append(long(sline[3]))
                        memAnon.append(0)
                        memCache.append(0)
                    except:
                        memFree.append(0)
                        memAnon.append(0)
                        memCache.append(0)
                try:
                    blkWait.append(long(sline[5]))
                except:
                    blkWait.append(0)

                try:
                    swapUsage.append(long(sline[6]))
                except:
                    swapUsage.append(0)

                try:
                    reclaim = sline[7].strip().split('/')
                    reclaimBg.append(long(reclaim[0]) << 2)
                    reclaimDr.append(long(reclaim[1]) << 2)
                except:
                    reclaimBg.append(0)
                    reclaimDr.append(0)

                try:
                    blkUsage = sline[4].split('/')
                    blkRead.append(long(blkUsage[0]) << 10)
                    blkWrite.append(long(blkUsage[1]) << 10)
                except:
                    blkRead.append(0)
                    blkWrite.append(0)

                try:
                    nrCore.append(long(sline[12]))
                except:
                    nrCore.append(0)

                try:
                    netstat = sline[13].strip().split('/')
                    if netstat[0] == '-':
                        raise Exception()

                    if netstat[0][-1] == 'T':
                        netRead.append(long(netstat[0][:-1]) << 30)
                    elif netstat[0][-1] == 'G':
                        netRead.append(long(netstat[0][:-1]) << 20)
                    elif netstat[0][-1] == 'M':
                        netRead.append(long(netstat[0][:-1]) << 10)
                    elif netstat[0][-1] == 'K':
                        netRead.append(long(netstat[0][:-1]))
                    else:
                        netRead.append(0)

                    if netstat[0][-1] == 'T':
                        netWrite.append(long(netstat[1][:-1]) << 30)
                    elif netstat[0][-1] == 'G':
                        netWrite.append(long(netstat[1][:-1]) << 20)
                    elif netstat[1][-1] == 'M':
                        netWrite.append(long(netstat[1][:-1]) << 10)
                    elif netstat[1][-1] == 'K':
                        netWrite.append(long(netstat[1][:-1]))
                    else:
                        netWrite.append(0)
                except:
                    netRead.append(0)
                    netWrite.append(0)

            # Event #
            elif context == 'Event':
                if slen != 4:
                    continue

                try:
                    time = long(float(sline[0]))
                    rtime = float(sline[1])
                    dtime = float(sline[2])
                    event = sline[3].strip()

                    idx = timeline.index(time)
                    eventList[idx].append('%s [%.2fs]' % (event, dtime))
                except:
                    pass

            # CPU #
            elif context == 'CPU':
                if slen == 3:
                    m = re.match(r'\s*(?P<comm>.+)\(\s*(?P<pid>[0-9]+)', line)
                    if not m:
                        continue

                    d = m.groupdict()
                    comm = d['comm'].strip()

                    if SysMgr.filterGroup != []:
                        if not ThreadAnalyzer.checkFilter(comm, d['pid']):
                            intervalList = None
                        else:
                            pid = d['pid']
                            pname = '%s(%s)' % (comm, pid)

                            intervalList = sline[2]
                    else:
                        pid = d['pid']
                        pname = '%s(%s)' % (comm, pid)

                        intervalList = sline[2]
                elif slen == 2:
                    if intervalList:
                        intervalList += sline[1]
                elif intervalList:
                    # save previous info #
                    cpuProcUsage[pname] = {}
                    cpuProcUsage[pname]['pid'] = pid

                    cpuProcUsage[pname]['usage'] = intervalList
                    cpuList = list(map(long, intervalList.split()))
                    intervalList = None

                    # calculate total usage of tasks filtered #
                    if ThreadAnalyzer.checkFilter(comm, pid):
                        if not "[ TOTAL ]" in cpuProcUsage:
                            cpuProcUsage["[ TOTAL ]"] = dict()

                            filterTotal = list(map(long, \
                                cpuProcUsage[pname]['usage'].split()))

                            cpuProcUsage["[ TOTAL ]"]['usage'] = \
                                ' '.join(list(map(str,filterTotal)))

                            cpuProcUsage["[ TOTAL ]"]['count'] = 1
                        else:
                            filterTotal = list(map(long, \
                                cpuProcUsage["[ TOTAL ]"]['usage'].split()))

                            for idx in range(0, len(filterTotal)):
                                filterTotal[idx] += cpuList[idx]

                            cpuProcUsage["[ TOTAL ]"]['usage'] = \
                                ' '.join(list(map(str,filterTotal)))

                            cpuProcUsage["[ TOTAL ]"]['count'] += 1

                        cpuProcUsage["[ TOTAL ]"]['minimum'] = \
                            min(filterTotal)
                        cpuProcUsage["[ TOTAL ]"]['average'] = \
                            sum(filterTotal) / len(filterTotal)
                        cpuProcUsage["[ TOTAL ]"]['maximum'] = \
                            max(filterTotal)

                    if len(cpuList) == 0:
                        cpuProcUsage[pname]['minimum'] = long(0)
                        cpuProcUsage[pname]['average'] = long(0)
                        cpuProcUsage[pname]['maximum'] = long(0)
                    else:
                        cpuProcUsage[pname]['minimum'] = min(cpuList)
                        cpuProcUsage[pname]['average'] = \
                            sum(cpuList) / len(cpuList)
                        cpuProcUsage[pname]['maximum'] = max(cpuList)

            # GPU #
            elif context == 'GPU':
                if slen == 3:
                    gname = sline[0].strip()
                    intervalList = sline[2]
                elif slen == 2:
                    if intervalList:
                        intervalList += sline[1]
                elif intervalList and gname != 'GPU':
                    # save previous info #
                    gpuUsage[gname] = intervalList
                    intervalList = None

                    '''
                    gpuUsage[gname] = {}

                    gpuUsage[gname]['usage'] = intervalList
                    gpuList = list(map(long, intervalList.split()))

                    if len(gpuList) == 0:
                        gpuUsage[gname]['minimum'] = long(0)
                        gpuUsage[gname]['average'] = long(0)
                        gpuUsage[gname]['maximum'] = long(0)
                    else:
                        gpuUsage[pname]['minimum'] = min(gpuList)
                        gpuUsage[pname]['average'] = \
                            sum(gpuList) / len(gpuList)
                        gpuUsage[pname]['maximum'] = max(gpuList)
                    '''

            # VSS #
            elif context == 'VSS':
                if slen == 3:
                    m = re.match(r'\s*(?P<comm>.+)\(\s*(?P<pid>[0-9]+)', line)
                    if not m:
                        continue

                    d = m.groupdict()
                    comm = d['comm'].strip().replace('^', '')

                    if SysMgr.filterGroup == []:
                        pid = d['pid']
                        pname = '%s(%s)' % (comm, pid)
                        maxVss = long(sline[1])
                        intervalList = sline[2]
                        continue

                    if not ThreadAnalyzer.checkFilter(comm, d['pid']):
                        intervalList = None
                    else:
                        pid = d['pid']
                        pname = '%s(%s)' % (comm, pid)
                        maxVss = long(sline[1])
                        intervalList = sline[2]
                elif slen == 2:
                    if intervalList:
                        intervalList += sline[1]
                elif intervalList:
                    # save previous info #
                    try:
                        memProcUsage[pname]
                    except:
                        memProcUsage[pname] = {}
                        memProcUsage[pname]['pid'] = pid

                    memProcUsage[pname]['maxVss'] = maxVss
                    memProcUsage[pname]['vssUsage'] = intervalList
                    intervalList = None

            # RSS / PSS / USS #
            elif (SysMgr.rssEnable or \
                    SysMgr.pssEnable or \
                    SysMgr.ussEnable) and \
                (context == 'RSS' or \
                    context == 'PSS' or \
                    context == 'USS'):
                if slen == 3:
                    m = re.match(r'\s*(?P<comm>.+)\(\s*(?P<pid>[0-9]+)', line)
                    if not m:
                        continue

                    d = m.groupdict()
                    comm = d['comm'].strip().replace('^', '')

                    if SysMgr.filterGroup == []:
                        pid = d['pid']
                        pname = '%s(%s)' % (comm, pid)
                        maxRss = long(sline[1])
                        intervalList = sline[2]
                        continue

                    if not ThreadAnalyzer.checkFilter(comm, d['pid']):
                        intervalList = None
                    else:
                        pid = d['pid']
                        pname = '%s(%s)' % (comm, pid)
                        maxRss = long(sline[1])
                        intervalList = sline[2]
                elif slen == 2:
                    if intervalList:
                        intervalList += sline[1]
                elif intervalList:
                    # save previous info #
                    try:
                        memProcUsage[pname]
                    except:
                        memProcUsage[pname] = {}
                        memProcUsage[pname]['pid'] = pid

                    memProcUsage[pname]['maxRss'] = maxRss
                    memProcUsage[pname]['rssUsage'] = intervalList
                    intervalList = None

            # Block #
            elif context == 'Block':
                if slen == 3:
                    m = re.match(r'\s*(?P<comm>.+)\(\s*(?P<pid>[0-9]+)', line)
                    if not m:
                        continue

                    d = m.groupdict()
                    comm = d['comm'].strip()

                    if SysMgr.filterGroup == []:
                        pid = d['pid']
                        pname = '%s(%s)' % (comm, pid)

                        try:
                            total = long(sline[1])
                        except:
                            total = sline[1]

                        intervalList = sline[2]
                        continue

                    if not ThreadAnalyzer.checkFilter(comm, d['pid']):
                        intervalList = None
                    else:
                        pid = d['pid']
                        pname = '%s(%s)' % (comm, pid)

                        try:
                            total = long(sline[1])
                        except:
                            total = sline[1]

                        intervalList = sline[2]
                elif slen == 2:
                    if intervalList:
                        intervalList += sline[1]
                elif intervalList:
                    # save previous info #
                    blkProcUsage[pname] = {}
                    blkProcUsage[pname]['pid'] = pid
                    blkProcUsage[pname]['total'] = total
                    blkProcUsage[pname]['usage'] = intervalList
                    intervalList = None

            # Storage #
            elif context == 'Storage':
                if slen == 3:
                    sname = sline[0].strip()
                    intervalList = sline[2]
                elif slen == 2:
                    if intervalList:
                        intervalList += sline[1]
                elif intervalList and sname != 'Storage':
                    # define arrays #
                    storageUsage.setdefault(sname, dict())
                    busyList = list()
                    readList = list()
                    writeList = list()
                    freeList = list()

                    # convert previous stats #
                    for item in intervalList.split():
                        busy, read, write, free = item.split('/')
                        busyList.append(busy)
                        readList.append(\
                            UtilMgr.convUnit2Size(read) >> 10)
                        writeList.append(\
                            UtilMgr.convUnit2Size(write) >> 10)
                        freeList.append(\
                            UtilMgr.convUnit2Size(free) >> 10)

                    # save previous info #
                    storageUsage[sname]['busy'] = busyList
                    storageUsage[sname]['read'] = readList
                    storageUsage[sname]['write'] = writeList
                    storageUsage[sname]['free'] = freeList
                    intervalList = None

            # Network #
            elif context == 'Network':
                if slen == 3:
                    sname = sline[0].strip()
                    intervalList = sline[2]
                elif slen == 2:
                    if intervalList:
                        intervalList += sline[1]
                elif intervalList and sname != 'Network':
                    # define arrays #
                    networkUsage.setdefault(sname, dict())
                    recvList = list()
                    tranList = list()

                    # convert previous stats e
                    for item in intervalList.split():
                        recv, tran = item.split('/')
                        recvList.append(\
                            UtilMgr.convUnit2Size(recv) >> 10)
                        tranList.append(\
                            UtilMgr.convUnit2Size(tran) >> 10)

                    # save previous info #
                    networkUsage[sname]['recv'] = recvList
                    networkUsage[sname]['tran'] = tranList
                    intervalList = None

            # Meory Details #
            elif context == 'Memory':
                if slen != 13:
                    continue

                m = re.match(\
                    r'\s*(?P<comm>.+)\(\s*(?P<pid>[0-9]+)', sline[0])
                if m:
                    d = m.groupdict()
                    pid = d['pid']
                    comm = d['comm'].strip()
                    pname = '%s(%s)' % (comm, pid)
                    chartStats[pname] = {}

                    try:
                        chartStats[pname][sline[1].strip()] = \
                            list(map(long, sline[2:-1]))
                    except:
                        pass
                elif long(pid) > 0:
                    try:
                        chartStats[pname][sline[1].strip()] = \
                            list(map(long, sline[2:-1]))
                    except:
                        pass

        UtilMgr.deleteProgress()

        # check output data #
        if not totalRam:
            SysMgr.printErr(\
                "Fail to find Detailed Statistics in %s" % logFile)
            sys.exit(0)
        elif not timeline:
            SysMgr.printErr(\
                "Fail to find interval data in %s" % logFile)
            sys.exit(0)

        # get indexes for trim #
        trim = SysMgr.getOption('t')
        if trim:
            trim = trim.split(':')
            try:
                if len(trim) == 1:
                    condMin = long(trim[0])
                    condMax = sys.maxsize
                elif len(trim) >= 2:
                    condMin = long(trim[0])
                    condMax = long(trim[1])
            except:
                SysMgr.printErr(\
                    "Fail to recognize %s as START:END time" % \
                        ':'.join(trim))
                sys.exit(0)

            # define default values #
            imin = timeline[0]
            imax = timeline[-1]

            # get min index #
            for itime in timeline:
                if itime >= condMin:
                    imin = itime
                    break

            # get max index #
            for itime in timeline:
                if itime >= condMax:
                    imax = itime
                    break

            # convert index range #
            imin = timeline.index(imin)
            imax = timeline.index(imax)

            # trim intervals #
            for name, value in cpuProcUsage.items():
                value['usage'] = value['usage'].split()[imin:imax]
                value['usage'] = ' '.join(value['usage'])

            for name, value in blkProcUsage.items():
                value['usage'] = value['usage'].split()[imin:imax]
                value['usage'] = ' '.join(value['usage'])

            for name, value in memProcUsage.items():
                if 'vssUsage' in value:
                    value['vssUsage'] = value['vssUsage'].split()[imin:imax]
                    value['vssUsage'] = ' '.join(value['vssUsage'])
                if 'rssUsage' in value:
                    value['rssUsage'] = value['rssUsage'].split()[imin:imax]
                    value['rssUsage'] = ' '.join(value['rssUsage'])

            for name, value in gpuUsage.items():
                value['usage'] = value['usage'].split()[imin:imax]
                value['usage'] = ' '.join(value['usage'])

            for name, dev in storageUsage.items():
                for item, value in dev.items():
                    storageUsage[name][item] = value[imin:imax]

            for name, dev in networkUsage.items():
                for item, value in dev.items():
                    networkUsage[name][item] = value[imin:imax]
        else:
            # set range index #
            imin = 0
            imax = -1

        # change maximum value for 1-length array #
        if imax == -1 and len(timeline) == 1:
            imax = 1

        # set graph argument list #
        graphStats = {
            'timeline': timeline[imin:imax],
            'eventList': eventList[imin:imax],
            'cpuUsage': cpuUsage[imin:imax],
            'cpuProcUsage': cpuProcUsage,
            'blkWait': blkWait[imin:imax],
            'blkProcUsage': blkProcUsage,
            'blkRead': blkRead[imin:imax],
            'blkWrite': blkWrite[imin:imax],
            'netRead': netRead[imin:imax],
            'netWrite': netWrite[imin:imax],
            'memFree': memFree[imin:imax],
            'memAnon': memAnon[imin:imax],
            'memCache': memCache[imin:imax],
            'memProcUsage': memProcUsage,
            'gpuUsage': gpuUsage,
            'totalRam': totalRam,
            'swapUsage': swapUsage[imin:imax],
            'totalSwap': totalSwap,
            'reclaimBg': reclaimBg[imin:imax],
            'reclaimDr': reclaimDr[imin:imax],
            'storageUsage': storageUsage,
            'networkUsage': networkUsage,
            'nrCore': nrCore[imin:imax],
        }

        return graphStats, chartStats



    def drawStats(self, flist, outFile=None, onlyGraph=False, onlyChart=False):
        # convert str to list #
        if type(flist) is str:
            flist = [flist]

        # get stats from single file #
        if len(flist) == 1:
            logFile = flist[0]

            # parse stats #
            graphStats, chartStats = ThreadAnalyzer.getDrawStats(logFile)
        # get stats from multiple files for comparison #
        else:
            logFile = SysMgr.outFileName

            # define integrated stats #
            graphStats = dict()
            chartStats = dict()

            # parse stats from multiple files #
            for lfile in flist:
                try:
                    gstats, cstats = ThreadAnalyzer.getDrawStats(lfile)
                except SystemExit:
                    sys.exit(0)
                except:
                    continue

                for key, val in gstats.items():
                    graphStats['%s:%s' % (lfile, key)] = val

        # draw graphs #
        try:
            if not onlyChart:
                self.drawGraph(graphStats, logFile, outFile=outFile)
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Fail to draw graph", True)
            return

        # draw charts #
        try:
            if not onlyGraph:
                self.drawChart(chartStats, logFile, outFile=outFile)
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Fail to draw chart", True)
            return



    def drawChart(self, data, logFile, outFile=None):
        # pylint: disable=undefined-variable

        if len(data) == 0:
            return

        def make_autopct(values):
            def autopct(pct):
                total = sum(values)
                val = long(round(pct*total/100.0)) << 20
                val = UtilMgr.convSize2Unit(val, True)
                usage = '{v:s} ({p:.0f}%)'.format(p=pct,v=val)
                line = '=' * 7
                string = '{s:1}\n{l:1}{d:1}'.\
                    format(s=usage,d=self.details[self.tmpCnt],l=line)
                self.tmpCnt += 1
                return string
            return autopct

        SysMgr.printStat(r"start drawing charts...")

        # get matplotlib object #
        matplotlib = SysMgr.getPkg('matplotlib', False)
        if not matplotlib:
            SysMgr.printPipWarn('matplotlib', 'matplotlib')
            sys.exit(0)
        from matplotlib.ticker import MaxNLocator

        SysMgr.matplotlibVersion = \
            float('.'.join(matplotlib.__version__.split('.')[:2]))

        matplotlib.use('Agg')

        # get pylab object #
        SysMgr.importPkgItems('pylab')

        seq = long(0)
        height = \
            long(len(data) / 2) \
            if len(data) % 2 == 0 else long(len(data) / 2 + 1)
        colors = \
            ['pink', 'lightgreen', 'skyblue', \
            'lightcoral', 'gold', 'yellowgreen']
        propList = \
            ['count', 'vmem', 'rss', 'pss', 'swap', \
            'huge', 'locked', 'pdirty', 'sdirty']
        suptitle('Guider Memory Chart', fontsize=8)

        for idx, item in sorted(data.items(),\
            key=lambda e: e[1]['[TOTAL]'][propList.index('rss')] +\
            e[1]['[TOTAL]'][propList.index('swap')], reverse=True):
            labels = []
            sizes = []
            explode = []
            self.details = []
            self.tmpCnt = long(0)

            if item['[TOTAL]'][propList.index('count')] == 0:
                continue

            for prop, value in item.items():
                if prop == '[TOTAL]' or \
                    (value[propList.index('rss')] == 0 and \
                    value[propList.index('swap')] == 0):
                    continue

                # add label of property and its property count #
                labels.append('%s(%s)' % \
                    (prop, value[propList.index('count')]))

                sizes.append(\
                    value[propList.index('rss')] + \
                    value[propList.index('swap')])

                # set private dirty size #
                pdrt = UtilMgr.convSize2Unit(\
                    value[propList.index('pdirty')] << 10, True)

                # set shared dirty size #
                sdrt = UtilMgr.convSize2Unit(\
                    value[propList.index('sdirty')] << 10, True)

                # set rss size #
                rss = UtilMgr.convSize2Unit(\
                    value[propList.index('rss')] << 20, True)

                # set swap size #
                swap = UtilMgr.convSize2Unit(\
                    value[propList.index('swap')] << 20, True)

                # set locked size #
                locked = UtilMgr.convSize2Unit(\
                    value[propList.index('locked')] << 10, True)

                self.details.append((\
                    '\n- RSS  : %5s \n- SWAP : %5s \n%s\n'
                    '- LOCK : %5s \n- PDRT : %5s \n- SDRT : %5s') % \
                    (rss, swap, '=' * 7, locked, pdrt, sdrt))

            # convert labels to tuple #
            labels = tuple(labels)

            # find and mark index of max value #
            explode = [0] * len(sizes)
            explode[sizes.index(max(sizes))] = 0.03

            # set size and position of this chart #
            try:
                ypos = seq >> 1
                xpos = seq - (ypos << 1)
                ax = subplot2grid((height,2), (ypos,xpos), rowspan=1, colspan=1)
                ax.xaxis.set_major_locator(MaxNLocator(integer=True))
            except:
                continue

            # get property of process  #
            line = '_' * len(idx) * 1

            rss = item['[TOTAL]'][propList.index('rss')]
            swap = item['[TOTAL]'][propList.index('swap')]
            total = UtilMgr.convSize2Unit((rss+swap) << 20)

            rss = UtilMgr.convSize2Unit(rss << 20)
            swap = UtilMgr.convSize2Unit(swap << 20)

            vmem = UtilMgr.convSize2Unit(\
                item['[TOTAL]'][propList.index('vmem')] << 20)

            pss = UtilMgr.convSize2Unit(\
                item['[TOTAL]'][propList.index('pss')] << 20)

            lock = UtilMgr.convSize2Unit(\
                item['[TOTAL]'][propList.index('locked')] << 10)

            dirty = item['[TOTAL]'][propList.index('pdirty')] + \
                item['[TOTAL]'][propList.index('sdirty')]
            dirty = UtilMgr.convSize2Unit(dirty << 10)

            totalList =\
                [('\n%s\n%s\n\n- TOTAL: %s \n- RSS: %s \n- SWAP: %s \n%s\n\n'
                '- VIRT: %s \n- PSS: %s \n- LOCK: %s \n- DIRTY: %s') %\
                ('[%s] %s' % (str(seq+1), idx), line, total, \
                rss, swap, line, vmem, pss, lock, dirty)]

            # draw chart #
            if SysMgr.matplotlibVersion >= 1.2:
                patches, texts, autotexts = \
                    pie(sizes, explode=explode, labels=labels, colors=colors, \
                    autopct=make_autopct(sizes), shadow=True, startangle=50, \
                    pctdistance=0.7)
            else:
                patches, texts, autotexts = \
                    pie(sizes, explode=explode, labels=labels, colors=colors,
                    autopct=make_autopct(sizes), shadow=True, pctdistance=0.7)

            # set font size #
            for idx, val in enumerate(texts):
                val.set_fontsize(5)
                autotexts[idx].set_fontsize(3.5)
            axis('equal')

            # print total size in legend #
            if SysMgr.matplotlibVersion >= 1.2:
                legend(patches, totalList, loc="lower right", shadow=True,\
                    fontsize=4.5, handlelength=0, bbox_to_anchor=(1.2, 0.01))
            else:
                legend(patches, totalList, loc="lower right", shadow=True,\
                    handlelength=0, bbox_to_anchor=(1.2, 0.01))

            seq += 1

        # draw image #
        figure(num=1, figsize=(10, 10), facecolor='b', edgecolor='k').\
            subplots_adjust(left=0, top=0.9, bottom=0.02, hspace=0.1, wspace=0.1)

        # save to file #
        self.saveImage(logFile, 'chart', outFile=outFile)



    def drawGraph(self, graphStats, logFile, outFile=None):
        # pylint: disable=undefined-variable

        #==================== DEFINE PART ====================#
        def getTextAlign(idx, timeline):
            if idx < len(timeline)/4:
                return 'left'
            elif idx > len(timeline)/4*3:
                return 'right'
            else:
                return 'center'

        def drawEvent(graphStats):
            # get minimum timeline #
            timeline = None
            for key, val in graphStats.items():
                if not key.endswith('timeline'):
                    continue
                elif not timeline:
                    timeline = val
                elif len(timeline) > len(val):
                    timeline = val
            lent = len(timeline)

            # start loop #
            for key, val in graphStats.items():
                if not key.endswith('timeline'):
                    continue

                res = key.split(':')
                if len(res) > 1:
                    fname = '%s:' % res[0]
                    prefix = '[%s] ' % res[0]
                else:
                    fname = ''
                    prefix = ''

                # get event table #
                eventList = graphStats['%seventList' % fname]

                for tm, evts in enumerate(eventList):
                    if len(evts) == 0:
                        continue

                    evtbox = '%s%s' % (prefix, '\n'.join(evts))

                    try:
                        text(timeline[tm], yticks()[0][-1], evtbox, fontsize=3,\
                            verticalalignment='top', style='italic',\
                            bbox={'facecolor':'green', 'alpha': 1, 'pad': 1},\
                            ha=getTextAlign(tm, timeline))

                        axvline(\
                            x=timeline[tm], linewidth=1, \
                                linestyle='--', color='green')
                    except:
                        pass

        def drawBottom(xtype, ax):
            if xtype == 1:
                # convert tick type to integer #
                try:
                    xtickLabel = ax.get_xticks().tolist()
                    xtickLabel = list(map(long, xtickLabel))
                    xlim([xtickLabel[0], xtickLabel[-1]])
                    xtickLabel[-1] = '   TIME(Sec)'
                    ax.set_xticklabels(xtickLabel)
                except:
                    pass
            elif xtype == 3:
                # draw the number of tasks #
                try:
                    xtickLabel = ax.get_xticks().tolist()
                    xlim([xtickLabel[0], xtickLabel[-1]])
                    if sum(effectProcList) == 0:
                        for seq, cnt in enumerate(xtickLabel):
                            xtickLabel[seq] = '?'
                    else:
                        for seq, cnt in enumerate(xtickLabel):
                            try:
                                xtickLabel[seq] = \
                                    effectProcList[timeline.index(long(cnt))]
                            except:
                                xtickLabel[seq] = ' '
                    xtickLabel[-1] = '   TASK(NR)'
                    ax.set_xticklabels(xtickLabel)
                except:
                    pass
            elif xtype == 2:
                # draw the number of cores #
                try:
                    xtickLabel = ax.get_xticks().tolist()
                    xlim([xtickLabel[0], xtickLabel[-1]])
                    for seq, cnt in enumerate(xtickLabel):
                        try:
                            xtickLabel[seq] = nrCore[timeline.index(long(cnt))]
                        except:
                            xtickLabel[seq] = ' '
                    xtickLabel[-1] = '   CORE(NR)'
                    ax.set_xticklabels(xtickLabel)
                except:
                    pass

        def drawBoundary(gtype, labelList):
            if not SysMgr.boundaryLine:
                return

            try:
                boundaryList = \
                    list(map(UtilMgr.convUnit2Size, \
                        SysMgr.boundaryLine))
            except:
                SysMgr.printErr(\
                    "Fail to set boundary line", True)
                sys.exit(0)

            # draw boundary graph #
            for boundary in boundaryList:
                if gtype == 'io':
                    bl = boundary >> 10
                elif gtype == 'mem':
                    bl = boundary >> 20
                else:
                    bl = boundary

                try:
                    axhline(y=bl, linewidth=1, linestyle='--', color='black')

                    labelList.append(\
                        '[ Boundary %s ]' % \
                            UtilMgr.convSize2Unit(boundary))
                except SystemExit:
                    sys.exit(0)
                except:
                    continue

        def drawCpu(graphStats, xtype, pos, size):
            # draw title #
            ax = subplot2grid((6,1), (pos,0), rowspan=size, colspan=1)
            ax.xaxis.set_major_locator(MaxNLocator(integer=True))
            suptitle('Guider Graph', fontsize=8)

            # define common label list #
            ymax = long(0)
            labelList = []

            # get minimum timeline #
            timeline = None
            for key, val in graphStats.items():
                if not key.endswith('timeline'):
                    continue
                elif not timeline:
                    timeline = val
                elif len(timeline) > len(val):
                    timeline = val
            lent = len(timeline)

            # start loop #
            for key, val in graphStats.items():
                if not key.endswith('timeline'):
                    continue

                res = key.split(':')
                if len(res) > 1:
                    fname = '%s:' % res[0]
                    prefix = '[%s] ' % res[0]
                else:
                    fname = ''
                    prefix = ''

                cpuUsage = graphStats['%scpuUsage' % fname][:lent]
                cpuProcUsage = graphStats['%scpuProcUsage' % fname]
                blkWait = graphStats['%sblkWait' % fname][:lent]
                blkProcUsage = graphStats['%sblkProcUsage' % fname]
                gpuUsage = graphStats['%sgpuUsage' % fname]
                nrCore = graphStats['%snrCore' % fname]
                maxCore = max(nrCore)

                # convert total CPU usage by core number #
                if not SysMgr.cpuAvrEnable:
                    cpuUsage = [maxCore * i for i in cpuUsage]

                # set visible total usage flag #
                if SysMgr.showAll or \
                    len(SysMgr.filterGroup) == 0:
                    isVisibleTotal = True
                else:
                    isVisibleTotal = False

                # add boundary line #
                drawBoundary('cpu', labelList)

                #-------------------- Total GPU usage --------------------#
                if isVisibleTotal:
                    for gpu, stat in gpuUsage.items():
                        stat = list(map(long, stat.split()))[:lent]
                        try:
                            if min(stat) == max(stat):
                                continue
                        except:
                            pass

                        # set color #
                        if len(prefix) > 0:
                            gcolor = None
                        else:
                            gcolor = 'olive'

                        # draw total gpu graph #
                        plot(timeline, stat, '-', c=gcolor, linestyle='-',\
                            linewidth=1, marker='d', markersize=1, \
                            solid_capstyle='round')

                        try:
                            avgUsage = round(sum(stat) / len(stat), 1)
                        except:
                            avgUsage = long(0)

                        maxUsage = max(stat)
                        maxIdx = stat.index(maxUsage)

                        labelList.append(\
                            '%s[ %s ] - %s%%' % (prefix, gpu, avgUsage))

                        for idx in [idx for idx, usage in enumerate(stat) \
                            if usage == maxUsage]:
                            if idx != 0 and stat[idx] == stat[idx-1]:
                                continue
                            text(timeline[idx], stat[maxIdx], \
                                '%s max: %d%% / avg: %d%%' % \
                                    (prefix, maxUsage, avgUsage),\
                                fontsize=4, color='olive', fontweight='bold',\
                                bbox=dict(boxstyle='round', facecolor='wheat',\
                                alpha=0.3),\
                                ha=getTextAlign(idx, timeline))
                            break

                #-------------------- Total CPU usage --------------------#
                if isVisibleTotal:
                    if sum(blkWait) > 0:
                        for idx, item in enumerate(blkWait):
                            blkWait[idx] += cpuUsage[idx]

                            # update the maximum ytick #
                            if ymax < blkWait[idx]:
                                ymax = blkWait[idx]

                        # set color #
                        if len(prefix) > 0:
                            icolor = None
                        else:
                            icolor = 'pink'

                        # draw total CPU + iowait graph #
                        plot(timeline, blkWait, '-', c=icolor, linestyle='-',\
                            linewidth=1, marker='d', markersize=1, \
                            solid_capstyle='round')

                        try:
                            avgUsage = round(sum(blkWait) / len(blkWait), 1)
                        except:
                            avgUsage = long(0)

                        labelList.append(\
                            '%s[ CPU+IO Average ] - %s%%' % (prefix, avgUsage))

                        maxUsage = max(blkWait)
                        maxIdx = blkWait.index(maxUsage)

                        for idx in [idx for idx, usage in enumerate(blkWait) \
                            if usage == maxUsage]:
                            if idx != 0 and blkWait[idx] == blkWait[idx-1]:
                                continue
                            text(timeline[idx], blkWait[maxIdx], \
                                '%s max: %d%% / avg: %.1f%%' % \
                                    (prefix, maxUsage, avgUsage),\
                                fontsize=4, color='pink', fontweight='bold',\
                                bbox=dict(boxstyle='round', facecolor='wheat',\
                                alpha=0.3),\
                                ha=getTextAlign(idx, timeline))
                            break

                    # set color #
                    if len(prefix) > 0:
                        ccolor = None
                    else:
                        ccolor = 'red'

                    # draw total CPU graph #
                    plot(timeline, cpuUsage, '-', c=ccolor, linestyle='-',\
                        linewidth=1, marker='d', markersize=1, \
                        solid_capstyle='round')

                    try:
                        avgUsage = round(sum(cpuUsage) / len(cpuUsage), 1)
                    except:
                        avgUsage = long(0)

                    maxUsage = max(cpuUsage)
                    maxIdx = cpuUsage.index(maxUsage)

                    labelList.append(\
                        '%s[ CPU Average ] - %s%%' % (prefix, avgUsage))

                    # update the maximum ytick #
                    if ymax < maxUsage:
                        ymax = maxUsage

                    for idx in [idx for idx, usage in enumerate(cpuUsage) \
                        if usage == maxUsage]:
                        if idx != 0 and cpuUsage[idx] == cpuUsage[idx-1]:
                            continue
                        text(timeline[idx], cpuUsage[maxIdx], \
                            '%smax: %d%% / avg: %.1f%%' % \
                            (prefix, maxUsage, avgUsage),\
                            fontsize=4, color='red', fontweight='bold',\
                            bbox=dict(boxstyle='round', facecolor='wheat',\
                            alpha=0.3),\
                            ha=getTextAlign(idx, timeline))
                        break

                #-------------------- Process CPU usage --------------------#
                # total CPU usage of processes filtered #
                if "[ TOTAL ]" in cpuProcUsage and \
                    cpuProcUsage["[ TOTAL ]"]['count'] > 1:
                    totalUsage = cpuProcUsage["[ TOTAL ]"]['usage'].split()
                    totalUsage = list(map(long, totalUsage))[:lent]

                    # draw total graph #
                    plot(timeline, totalUsage, '-', c='green', linestyle='-',\
                        linewidth=1, marker='d', markersize=1, \
                        solid_capstyle='round')

                    labelList.append('%s[ TOTAL ]' % prefix)

                    try:
                        avgUsage = round(sum(totalUsage) / len(totalUsage), 1)
                    except:
                        avgUsage = long(0)

                    maxUsage = max(totalUsage)
                    maxIdx = totalUsage.index(maxUsage)

                    # update the maximum ytick #
                    if ymax < maxUsage:
                        ymax = maxUsage

                    for idx in [idx for idx, usage in enumerate(totalUsage) \
                        if usage == maxUsage]:
                        if idx != 0 and totalUsage[idx] == totalUsage[idx-1]:
                            continue

                        text(timeline[idx], totalUsage[maxIdx], \
                            '%s max: %d%% / avg: %.1f%%' % \
                                (prefix, maxUsage, avgUsage),\
                            fontsize=4, color='green', fontweight='bold',\
                            bbox=dict(boxstyle='round', facecolor='wheat',\
                            alpha=0.3),\
                            ha=getTextAlign(idx, timeline))
                        break

                cpuProcUsage.pop("[ TOTAL ]", None)

                # define top variable #
                if SysMgr.nrTop:
                    tcnt = long(0)

                # CPU usage of processes #
                for idx, item in sorted(\
                    cpuProcUsage.items(), \
                    key=lambda e: e[1]['average'], reverse=True):

                    if not SysMgr.cpuEnable:
                        break

                    # check top number #
                    if SysMgr.nrTop:
                        if tcnt >= SysMgr.nrTop:
                            break
                        else:
                            tcnt += 1

                    usage = item['usage'].split()
                    usage = list(map(long, usage))[:lent]
                    cpuUsage = list(usage)

                    try:
                        avgUsage = round(sum(cpuUsage) / len(cpuUsage), 1)
                    except:
                        avgUsage = long(0)

                    if not SysMgr.blockEnable:
                        # merge CPU usage and wait time of processes #
                        try:
                            blkUsage = blkProcUsage[idx]['usage'].split()
                            blkUsage = list(map(long, blkUsage))
                            for interval, value in enumerate(blkUsage):
                                usage[interval] += value
                        except:
                            pass

                    # increase effectProcList count #
                    for seq, cnt in enumerate(usage):
                        if cnt > 0:
                            effectProcList[seq] += 1

                    # update the maximum ytick #
                    maxusage = max(usage)
                    if ymax < maxusage:
                        ymax = maxusage

                    maxIdx = usage.index(maxusage)
                    color = plot(timeline, usage, '-')[0].get_color()

                    ytick = yticks()[0]
                    if len(ytick) > 1:
                        margin = (ytick[1] - ytick[0]) / 10
                    else:
                        margin = long(0)

                    maxCpuPer = str(cpuUsage[maxIdx])
                    if idx in blkProcUsage and not SysMgr.blockEnable:
                        maxBlkPer = str(blkUsage[maxIdx])
                    else:
                        maxBlkPer = '0'
                    maxPer = '[max: %s%%+%s%% / avg: %s%%]' % \
                        (maxCpuPer, maxBlkPer, avgUsage)

                    ilabel = '%s%s %s' % (prefix, idx, maxPer)
                    text(timeline[maxIdx], usage[maxIdx] + margin, ilabel,\
                        fontsize=3, color=color, fontweight='bold',\
                        ha=getTextAlign(maxIdx, timeline))

                    labelList.append(\
                        '%s%s - %s%%' % (prefix, idx, avgUsage))

            '''
            ylabel('CPU + I/O', fontsize=5)
            ax.yaxis.set_label_coords(-0.05,0.5)
            '''

            if SysMgr.matplotlibVersion >= 1.2:
                legend(labelList, bbox_to_anchor=(1.12, 1.05), \
                    fontsize=3.5, loc='upper right')
            else:
                legend(labelList, bbox_to_anchor=(1.12, 1.05), loc='upper right')

            grid(which='both', linestyle=':', linewidth=0.2)

            tick_params(axis='x', direction='in')
            tick_params(axis='y', direction='in')

            # update ymax #
            if SysMgr.funcDepth > 0:
                ymax = SysMgr.funcDepth

            # set yticks attributes #
            xticks(fontsize=4)
            ylim([0, ymax+int(ymax/10)])
            if len(timeline) > 1:
                xlim([timeline[0], timeline[-1]])
            inc = long(ymax / 10)
            if inc == 0:
                inc = 1
            yticks(range(0, ymax + inc, inc), fontsize=5)

            # add % unit to each value #
            try:
                ytickLabel = ax.get_yticks().tolist()
                ytickLabel = list(map(long, ytickLabel))

                # convert label units #
                ytickLabel = \
                    ['%s%%' % val for val in ytickLabel]

                ax.set_yticklabels(ytickLabel)
            except:
                pass

            #ticklabel_format(useOffset=False)
            locator_params(axis = 'x', nbins=30)
            self.figure = \
                figure(num=1, figsize=(10, 10), facecolor='b', edgecolor='k')
            self.figure.subplots_adjust(left=0.06, top=0.95, bottom=0.04)

            drawBottom(xtype, ax)

        def drawIo(graphStats, xtype, pos, size):
            def drawSystemIo(statList, color, ymax):
                usage = list(map(long, statList))[:lent]

                # update the maximum ytick #
                maxUsage = max(usage)
                if ymax < maxUsage:
                    ymax = maxUsage

                minIdx = usage.index(min(usage))
                maxIdx = usage.index(max(usage))

                minval = '%s%s' % \
                    (prefix, convSize2Unit(usage[minIdx] << 10))
                maxsize = convSize2Unit(usage[maxIdx] << 10)
                totalsize = convSize2Unit(long(sum(usage)) << 10)
                maxval = '%s%s' % (prefix, maxsize)
                lastval = '%s%s' % \
                    (prefix, convSize2Unit(usage[-1] << 10))

                if usage[minIdx] > 0:
                    text(timeline[minIdx], usage[minIdx], minval,\
                        fontsize=4, color=color, fontweight='bold',\
                        ha=getTextAlign(minIdx, timeline))
                if usage[minIdx] != usage[maxIdx] and usage[maxIdx] > 0:
                    text(timeline[maxIdx], usage[maxIdx], maxval,\
                        fontsize=4, color=color, fontweight='bold',\
                        ha=getTextAlign(maxIdx, timeline))
                if usage[-1] > 0:
                    try:
                        unit = (timeline[-1]-timeline[-2]) / 10
                    except:
                        unit = long(0)
                    text(timeline[-1], usage[-1], lastval,\
                        fontsize=4, color=color, fontweight='bold',\
                        ha='right')

                # set color #
                if len(prefix) > 0:
                    rcolor = None
                else:
                    rcolor = color

                if usage[minIdx] == usage[maxIdx] == 0:
                    plot(timeline, statList, '-', c=rcolor, \
                        linewidth=1, alpha=0.1)
                else:
                    plot(timeline, statList, '-', c=rcolor, linewidth=1)

                return totalsize, ymax

            # define common label list #
            ymax = long(0)
            labelList = []

            # set convert size #
            convSize2Unit = UtilMgr.convSize2Unit

            # draw title #
            ax = subplot2grid((6,1), (pos,0), rowspan=size, colspan=1)
            ax.xaxis.set_major_locator(MaxNLocator(integer=True))
            suptitle('Guider Graph', fontsize=8)

            # get minimum timeline #
            timeline = None
            for key, val in graphStats.items():
                if not key.endswith('timeline'):
                    continue
                elif not timeline:
                    timeline = val
                elif len(timeline) > len(val):
                    timeline = val
            lent = len(timeline)

            # add boundary line #
            drawBoundary('io', labelList)

            # start loop #
            for key, val in graphStats.items():
                if not key.endswith('timeline'):
                    continue

                res = key.split(':')
                if len(res) > 1:
                    fname = '%s:' % res[0]
                    prefix = '[%s] ' % res[0]
                else:
                    fname = ''
                    prefix = ''

                blkRead = graphStats['%sblkRead' % fname][:lent]
                blkWrite = graphStats['%sblkWrite' % fname][:lent]
                blkProcUsage = graphStats['%sblkProcUsage' % fname]
                netRead = graphStats['%snetRead' % fname][:lent]
                netWrite = graphStats['%snetWrite' % fname][:lent]
                reclaimBg = graphStats['%sreclaimBg' % fname][:lent]
                reclaimDr = graphStats['%sreclaimDr' % fname][:lent]
                storageUsage = graphStats['%sstorageUsage' % fname]
                networkUsage = graphStats['%snetworkUsage' % fname]

                # System Block Read #
                totalsize, ymax = drawSystemIo(blkRead, 'skyblue', ymax)
                labelList.append(\
                    '%sBlock Read - %s' % (prefix, totalsize))

                # System Block Write #
                totalsize, ymax = drawSystemIo(blkWrite, 'green', ymax)
                labelList.append(\
                    '%sBlock Write - %s' % (prefix, totalsize))

                # System Background Reclaim #
                totalsize, ymax = drawSystemIo(reclaimBg, 'pink', ymax)
                labelList.append(\
                    '%sReclaim BG - %s' % (prefix, totalsize))

                # System Direct Reclaim #
                totalsize, ymax = drawSystemIo(reclaimDr, 'red', ymax)
                labelList.append(\
                    '%sReclaim FG - %s' % (prefix, totalsize))

                # System Network Inbound #
                totalsize, ymax = drawSystemIo(netRead, 'purple', ymax)
                labelList.append(\
                    '%sNetwork In - %s' % (prefix, totalsize))

                # System Network Outbound #
                totalsize, ymax = drawSystemIo(netWrite, 'cyan', ymax)
                labelList.append(\
                    '%sNetwork Out - %s' % (prefix, totalsize))

                # System Network Usage #
                for idx, item in networkUsage.items():
                    rdUsage = item['recv'][:lent]
                    wrUsage = item['tran'][:lent]

                    # no network usage #
                    if len(rdUsage) == len(wrUsage) == 0:
                        continue

                    # get margin #
                    ytick = yticks()[0]
                    if len(ytick) > 1:
                        margin = (ytick[1] - ytick[0]) / 10
                    else:
                        margin = long(0)

                    # Network Transfer #
                    minIdx = wrUsage.index(min(wrUsage))
                    maxIdx = wrUsage.index(max(wrUsage))

                    # update the maximum ytick #
                    maxUsage = max(wrUsage)
                    if ymax < maxUsage:
                        ymax = maxUsage

                    maxsize = convSize2Unit(wrUsage[maxIdx] << 10)
                    totalsize = convSize2Unit(long(sum(wrUsage)) << 10)
                    maxval = '%s%s' % (prefix, maxsize)
                    lastval = '%s%s' % \
                        (prefix, convSize2Unit(wrUsage[-1] << 10))

                    if wrUsage[minIdx] == wrUsage[maxIdx] == 0:
                        pass
                    else:
                        color = \
                            plot(timeline, wrUsage, '-', \
                                linewidth=1)[0].get_color()
                        if wrUsage[maxIdx] > 0:
                            text(timeline[maxIdx], \
                                wrUsage[maxIdx] + margin, maxval,\
                                fontsize=4, color=color, fontweight='bold',\
                                ha=getTextAlign(maxIdx, timeline))
                        if wrUsage[-1] > 0:
                            try:
                                unit = (timeline[-1]-timeline[-2]) / 10
                            except:
                                unit = long(0)
                            text(timeline[-1],\
                                wrUsage[-1] + margin, lastval,\
                                fontsize=4, color=color, fontweight='bold',\
                                ha='right')

                        labelList.append(\
                            '%s%s Transfer - %s' % (prefix, idx, totalsize))

                    # Network Receive #
                    minIdx = rdUsage.index(min(rdUsage))
                    maxIdx = rdUsage.index(max(rdUsage))

                    # update the maximum ytick #
                    maxUsage = max(rdUsage)
                    if ymax < maxUsage:
                        ymax = maxUsage

                    maxsize = convSize2Unit(rdUsage[maxIdx] << 10)
                    totalsize = convSize2Unit(long(sum(rdUsage)) << 10)
                    maxval = '%s%s' % (prefix, maxsize)
                    lastval = '%s%s' % \
                        (prefix, convSize2Unit(rdUsage[-1] << 10))

                    if rdUsage[minIdx] == rdUsage[maxIdx] == 0:
                        pass
                    else:
                        color = \
                            plot(timeline, rdUsage, '-', \
                                linewidth=1)[0].get_color()
                        if rdUsage[maxIdx] > 0:
                            text(timeline[maxIdx], \
                                rdUsage[maxIdx] + margin, maxval,\
                                fontsize=4, color=color, fontweight='bold',\
                                ha=getTextAlign(maxIdx, timeline))
                        if rdUsage[-1] > 0:
                            try:
                                unit = (timeline[-1]-timeline[-2]) / 10
                            except:
                                unit = long(0)
                            text(timeline[-1], \
                                rdUsage[-1] + margin, lastval,\
                                fontsize=4, color=color, fontweight='bold',\
                                ha='right')

                        labelList.append(\
                            '%s%s Receive - %s' % (prefix, idx, totalsize))

                # System Storage Usage #
                for idx, item in storageUsage.items():
                    rdUsage = item['read'][:lent]
                    wrUsage = item['write'][:lent]
                    freeUsage = item['free'][:lent]

                    # no storage usage #
                    if len(rdUsage) == len(wrUsage) == len(freeUsage) == 0:
                        continue

                    # get margin #
                    ytick = yticks()[0]
                    if len(ytick) > 1:
                        margin = (ytick[1] - ytick[0]) / 10
                    else:
                        margin = long(0)

                    # Storage Write #
                    minIdx = wrUsage.index(min(wrUsage))
                    maxIdx = wrUsage.index(max(wrUsage))

                    # update the maximum ytick #
                    maxUsage = max(wrUsage)
                    if ymax < maxUsage:
                        ymax = maxUsage

                    maxsize = convSize2Unit(wrUsage[maxIdx] << 10)
                    totalsize = convSize2Unit(long(sum(wrUsage)) << 10)
                    maxval = '%s%s' % (prefix, maxsize)
                    lastval = '%s%s' % \
                        (prefix, convSize2Unit(wrUsage[-1] << 10))

                    if wrUsage[minIdx] == wrUsage[maxIdx] == 0:
                        pass
                    else:
                        color = \
                            plot(timeline, wrUsage, '-', \
                                linewidth=1)[0].get_color()
                        if wrUsage[maxIdx] > 0:
                            text(timeline[maxIdx], \
                                wrUsage[maxIdx] + margin, maxval,\
                                fontsize=4, color=color, fontweight='bold',\
                                ha=getTextAlign(maxIdx, timeline))
                        if wrUsage[-1] > 0:
                            try:
                                unit = (timeline[-1]-timeline[-2]) / 10
                            except:
                                unit = long(0)
                            text(timeline[-1], wrUsage[-1] + margin, lastval,\
                                fontsize=4, color=color, fontweight='bold',\
                                ha='right')

                        labelList.append(\
                            '%s%s Write - %s' % (prefix, idx, totalsize))

                    # Storage Read #
                    minIdx = rdUsage.index(min(rdUsage))
                    maxIdx = rdUsage.index(max(rdUsage))

                    # update the maximum ytick #
                    maxUsage = max(rdUsage)
                    if ymax < maxUsage:
                        ymax = maxUsage

                    maxsize = convSize2Unit(rdUsage[maxIdx] << 10)
                    totalsize = convSize2Unit(long(sum(rdUsage)) << 10)
                    maxval = '%s%s' % (prefix, maxsize)
                    lastval = '%s%s' % \
                        (prefix, convSize2Unit(rdUsage[-1] << 10))

                    if rdUsage[minIdx] == rdUsage[maxIdx] == 0:
                        pass
                    else:
                        color = \
                            plot(timeline, rdUsage, '-', \
                                linewidth=1)[0].get_color()
                        if rdUsage[maxIdx] > 0:
                            text(timeline[maxIdx],\
                                rdUsage[maxIdx] + margin, maxval,\
                                fontsize=4, color=color, fontweight='bold',\
                                ha=getTextAlign(maxIdx, timeline))
                        if rdUsage[-1] > 0:
                            try:
                                unit = (timeline[-1]-timeline[-2]) / 10
                            except:
                                unit = long(0)
                            text(timeline[-1], rdUsage[-1] + margin, lastval,\
                                fontsize=4, color=color, fontweight='bold',\
                                ha='right')

                        labelList.append(\
                            '%s%s Read - %s' % (prefix, idx, totalsize))

                # IO usage of processes #
                for idx, item in blkProcUsage.items():
                    if not SysMgr.blockEnable:
                        break

                    usage = item['usage'].split()[:lent]
                    rdUsage = list()
                    wrUsage = list()

                    # divide io graph #
                    for item in usage:
                        io = item.split('/')
                        if(len(io) == 2):
                            rdUsage.append(long(io[0]) << 10)
                            wrUsage.append(long(io[1]) << 10)

                    # no io usage #
                    if len(rdUsage) == len(wrUsage) == 0:
                        continue

                    # get margin #
                    ytick = yticks()[0]
                    if len(ytick) > 1:
                        margin = (ytick[1] - ytick[0]) / 10
                    else:
                        margin = long(0)

                    # Block Write of process #
                    minIdx = wrUsage.index(min(wrUsage))
                    maxIdx = wrUsage.index(max(wrUsage))

                    # update the maximum ytick #
                    maxUsage = max(wrUsage)
                    if ymax < maxUsage:
                        ymax = maxUsage

                    maxsize = convSize2Unit(wrUsage[maxIdx] << 10)
                    totalsize = convSize2Unit(long(sum(wrUsage)) << 10)
                    maxval = '%s[%s]%s' % (prefix, maxsize, idx)
                    lastval = '%s[%s]%s' % \
                        (prefix, convSize2Unit(wrUsage[-1] << 10), idx)

                    if wrUsage[minIdx] == wrUsage[maxIdx] == 0:
                        pass
                    else:
                        color = \
                            plot(timeline, wrUsage, '-', \
                                linewidth=1)[0].get_color()
                        if wrUsage[maxIdx] > 0:
                            text(timeline[maxIdx], wrUsage[maxIdx] + margin, \
                                maxval, fontsize=3, color=color, \
                                fontweight='bold', \
                                ha=getTextAlign(maxIdx, timeline))
                        if wrUsage[-1] > 0:
                            try:
                                unit = (timeline[-1]-timeline[-2]) / 10
                            except:
                                unit = long(0)
                            text(timeline[-1], wrUsage[-1] + margin, \
                                lastval, fontsize=3, color=color, \
                                fontweight='bold', \
                                ha='right')

                        labelList.append(\
                            '%s%s[BWR] - %s' % (prefix, idx, totalsize))

                    # Block Read of process #
                    minIdx = rdUsage.index(min(rdUsage))
                    maxIdx = rdUsage.index(max(rdUsage))

                    # update the maximum ytick #
                    maxUsage = max(rdUsage)
                    if ymax < maxUsage:
                        ymax = maxUsage

                    maxsize = convSize2Unit(rdUsage[maxIdx] << 10)
                    totalsize = convSize2Unit(long(sum(rdUsage)) << 10)
                    maxval = '%s[%s]%s' % (prefix, maxsize, idx)
                    lastval = '%s[%s]%s' % \
                        (prefix, convSize2Unit(rdUsage[-1] << 10), idx)

                    if rdUsage[minIdx] == rdUsage[maxIdx] == 0:
                        pass
                    else:
                        color = \
                            plot(timeline, rdUsage, '-', \
                                linewidth=1)[0].get_color()
                        if rdUsage[maxIdx] > 0:
                            text(timeline[maxIdx], rdUsage[maxIdx] + margin, \
                                maxval, fontsize=3, color=color, \
                                fontweight='bold', \
                                ha=getTextAlign(maxIdx, timeline))
                        if rdUsage[-1] > 0:
                            try:
                                unit = (timeline[-1]-timeline[-2]) / 10
                            except:
                                unit = long(0)
                            text(timeline[-1], rdUsage[-1] + margin, \
                                lastval, fontsize=3, color=color, \
                                fontweight='bold', \
                                ha='right')

                        labelList.append(\
                            '%s%s[BRD] - %s' % (prefix, idx, totalsize))

            '''
            ylabel('I/O', fontsize=5)
            ax.yaxis.set_label_coords(-0.05,0.5)
            '''

            if len(labelList) > 0:
                if SysMgr.matplotlibVersion >= 1.2:
                    legend(labelList, bbox_to_anchor=(1.12, 0.95), \
                        fontsize=3.5, loc='upper right')
                else:
                    legend(labelList, bbox_to_anchor=(1.12, 0.95), \
                        loc='upper right')

            grid(which='both', linestyle=':', linewidth=0.2)
            tick_params(axis='x', direction='in')
            tick_params(axis='y', direction='in')

            # update and set ymax #
            if SysMgr.funcDepth > 0:
                ymaxval = SysMgr.funcDepth
            else:
                ymaxval = ymax+int(ymax/10)
            if ymaxval == 0:
                ymaxval = 1
            ylim([0, ymaxval])

            # adjust yticks #
            ylist = ax.get_yticks().tolist()
            ymin = long(min(ylist))
            if ymin < 0:
                ymin = long(0)

            #ymax = long(max(ylist))
            inc = long(ymax / 10)
            if inc == 0:
                inc = 1
            yticks(range(ymin, ymax + inc, inc), fontsize=5)

            xticks(fontsize=4)
            if len(timeline) > 1:
                xlim([timeline[0], timeline[-1]])

            try:
                ticklabel_format(useOffset=False)
            except:
                pass

            locator_params(axis = 'x', nbins=30)
            self.figure = \
                figure(num=1, figsize=(10, 10), facecolor='b', edgecolor='k')
            self.figure.subplots_adjust(left=0.06, top=0.95, bottom=0.04)

            # convert tick type to integer #
            try:
                #ax.get_xaxis().set_visible(False)
                ytickLabel = ax.get_yticks().tolist()
                ytickLabel = list(map(long, ytickLabel))

                # convert label units #
                ytickLabel = \
                    [convSize2Unit(val << 10) for val in ytickLabel]

                # remove redundant ticks #
                lastTick = ''
                tempLabelList = list(ytickLabel)
                for idx, ytick in enumerate(tempLabelList):
                    if lastTick == ytick:
                        ytickLabel[idx] = ''
                    else:
                        lastTick = ytick
                ax.set_yticklabels(ytickLabel)

                # hide yticks #
                if ytickLabel[-1] == '0':
                    ax.set_ylim(top=1)
                    ax.get_yaxis().set_visible(False)
                else:
                    try:
                        ax.set_ylim(bottom=0)
                    except:
                        pass
            except:
                pass

            drawBottom(xtype, ax)

        def drawMem(graphStats, xtype, pos, size):
            def drawSystemMem(statList, color, ymax):
                usage = list(map(long, statList))
                minIdx = usage.index(min(usage))
                maxIdx = usage.index(max(usage))

                if usage[minIdx] == usage[maxIdx] == 0:
                    return None, ymax

                # update the maximum ytick #
                maxusage = max(usage)
                if ymax < maxusage:
                    ymax = maxusage

                minval = '%s%s' % \
                    (prefix, convSize2Unit(usage[minIdx] << 20))
                maxsize = convSize2Unit(usage[maxIdx] << 20)
                maxval = '%s%s' % (prefix, maxsize)
                lastsize = convSize2Unit(usage[-1] << 20)
                lastval = '%s%s' % (prefix, lastsize)

                if usage[minIdx] > 0:
                    text(timeline[minIdx], usage[minIdx], minval,\
                        fontsize=4, color=color, fontweight='bold',\
                        ha=getTextAlign(minIdx, timeline))
                if usage[minIdx] != usage[maxIdx] and usage[maxIdx] > 0:
                    text(timeline[maxIdx], usage[maxIdx], maxval,\
                        fontsize=4, color=color, fontweight='bold',\
                        ha=getTextAlign(maxIdx, timeline))
                if usage[-1] > 0:
                    text(timeline[-1], usage[-1], lastval,\
                        fontsize=4, color=color, fontweight='bold',\
                        ha='right')

                # set color #
                if len(prefix) > 0:
                    fcolor = None
                else:
                    fcolor = color

                plot(timeline, usage, '-', c=fcolor, \
                    linewidth=1, solid_capstyle='round')

                return lastsize, ymax

            # define common label list #
            ymax = long(0)
            labelList = []

            # set convert size #
            convSize2Unit = UtilMgr.convSize2Unit

            # draw title #
            ax = subplot2grid((6,1), (pos,0), rowspan=size, colspan=1)
            ax.xaxis.set_major_locator(MaxNLocator(integer=True))
            suptitle('Guider Graph', fontsize=8)

            # get minimum timeline #
            timeline = None
            for key, val in graphStats.items():
                if not key.endswith('timeline'):
                    continue
                elif not timeline:
                    timeline = val
                elif len(timeline) > len(val):
                    timeline = val
            lent = len(timeline)

            # add boundary line #
            drawBoundary('mem', labelList)

            # define top variable #
            if SysMgr.nrTop:
                tcnt = long(0)

            # start loop #
            for key, val in graphStats.items():
                if not key.endswith('timeline'):
                    continue

                # get prefix #
                res = key.split(':')
                if len(res) > 1:
                    fname = '%s:' % res[0]
                    prefix = '[%s] ' % res[0]
                else:
                    fname = ''
                    prefix = ''

                totalRam = graphStats['%stotalRam' % fname]
                memFree = graphStats['%smemFree' % fname][:lent]
                memAnon = graphStats['%smemAnon' % fname][:lent]
                memCache = graphStats['%smemCache' % fname][:lent]
                memProcUsage = graphStats['%smemProcUsage' % fname]
                totalSwap = graphStats['%stotalSwap' % fname]
                swapUsage = graphStats['%sswapUsage' % fname][:lent]

                # get margin #
                ytick = yticks()[0]
                if len(ytick) > 1:
                    margin = (ytick[1] - ytick[0]) / 10
                else:
                    margin = long(0)

                # Process VSS #
                if SysMgr.vssEnable:
                    for key, item in sorted(memProcUsage.items(), \
                        key=lambda e: 0 \
                        if not 'maxVss' in e[1] else e[1]['maxVss'], \
                        reverse=True):
                        # check top number #
                        if SysMgr.nrTop:
                            if tcnt >= SysMgr.nrTop:
                                break
                            else:
                                tcnt += 1

                        usage = list(map(long, item['vssUsage'].split()))[:lent]

                        # update the maximum ytick #
                        maxusage = max(usage)
                        if ymax < maxusage:
                            ymax = maxusage

                        try:
                            minIdx = usage.index(min(usage))
                        except:
                            minIdx = long(0)
                        try:
                            maxIdx = usage.index(item['maxVss'])
                        except:
                            maxIdx = long(0)

                        key = '%s%s' % (prefix, key)
                        minval = '%s [%s]' % \
                            (key, convSize2Unit(usage[minIdx] << 20))
                        maxsize = convSize2Unit(usage[maxIdx] << 20)
                        maxval = '%s [%s]' % (key, maxsize)
                        lastval = '%s [%s]' % \
                            (key, convSize2Unit(usage[-1] << 20))

                        if usage[minIdx] == usage[maxIdx] == 0:
                            continue

                        # ignore 0 #
                        usage = list(map(lambda x: x if x != 0 else None, usage))

                        # get color #
                        color = plot(timeline, usage, '-', \
                            linewidth=1)[0].get_color()

                        if usage[minIdx]:
                            text(timeline[minIdx], usage[minIdx] + margin, \
                                minval, color=color, fontsize=3, \
                                ha=getTextAlign(minIdx, timeline))
                        if usage[minIdx] != usage[maxIdx] and usage[maxIdx]:
                            text(timeline[maxIdx], usage[maxIdx] + margin, \
                                maxval, color=color, fontsize=3, \
                                ha=getTextAlign(maxIdx, timeline))
                        if usage[-1]:
                            text(timeline[-1], usage[-1] + margin, \
                                lastval, color=color, fontsize=3, \
                                ha='right')

                        labelList.append(\
                            '%s [VSS] - %s' % (key, maxsize))

                # Process Leak #
                elif SysMgr.leakEnable:
                    # get VSS diffs #
                    for key, item in sorted(memProcUsage.items(), \
                        key=lambda e: 0 \
                        if not 'maxVss' in e[1] else e[1]['maxVss'], \
                        reverse=True):
                        usage = list(map(long, item['vssUsage'].split()))[:lent]

                        # update the maximum ytick #
                        maxusage = max(usage)
                        if ymax < maxusage:
                            ymax = maxusage

                        # get maximum value #
                        try:
                            maxVss = max(usage)
                        except:
                            maxVss = long(0)

                        if maxVss == 0:
                            item['vssDiff'] = long(0)
                            continue

                        # get index of maximum and minimum values greater than 0 #
                        try:
                            first = next(val for val in usage if val > 0)
                            last = next(val for val in reversed(usage) if val > 0)
                            if long(first) > long(last):
                                item['vssDiff'] = long(0)
                                continue
                        except:
                            pass

                        # get minimum value #
                        try:
                            minVss = min(x for x in usage if x != 0)
                        except:
                            minVss = long(0)

                        diff = maxVss - minVss
                        item['vssDiff'] = diff

                    # draw leakage plots #
                    for key, item in sorted(\
                        memProcUsage.items(), \
                        key=lambda e: e[1]['vssDiff'], reverse=True):

                        # check top number #
                        if SysMgr.nrTop:
                            if tcnt >= SysMgr.nrTop:
                                break
                            else:
                                tcnt += 1

                        if item['vssDiff'] == 0:
                            break

                        usage = list(map(long, item['vssUsage'].split()))[:lent]

                        # update the maximum ytick #
                        maxusage = max(usage)
                        if ymax < maxusage:
                            ymax = maxusage

                        # get minimum value #
                        try:
                            minIdx = usage.index(min(usage))
                        except:
                            minIdx = long(0)

                        # get maximum value #
                        try:
                            maxIdx = usage.index(item['maxVss'])
                        except:
                            maxIdx = long(0)

                        key = '%s%s' % (prefix, key)
                        minval = '%s [%s]' % \
                            (key, convSize2Unit(usage[minIdx] << 20))
                        diffsize = convSize2Unit(item['vssDiff'] << 20)
                        lastval = '%s [%s/+%s]' % \
                            (key, convSize2Unit(usage[maxIdx] << 20),\
                                diffsize)

                        if usage[minIdx] == usage[maxIdx] == 0:
                            continue

                        # ignore 0 #
                        usage = list(map(lambda x: x if x != 0 else None, usage))

                        # get color #
                        color = plot(timeline, usage, '-', \
                            linewidth=1)[0].get_color()

                        if usage[minIdx]:
                            text(timeline[minIdx], usage[minIdx] - margin, \
                                minval, color=color, fontsize=3, \
                                ha=getTextAlign(minIdx, timeline))
                        if usage[minIdx] != usage[maxIdx] and usage[maxIdx]:
                            text(timeline[maxIdx], usage[maxIdx] + margin, \
                                lastval, color=color, fontsize=3, \
                                ha=getTextAlign(maxIdx, timeline))

                        labelList.append('%s [LEAK] - %s' % (key, diffsize))

                # Process RSS #
                elif SysMgr.rssEnable or \
                    SysMgr.pssEnable or \
                    SysMgr.ussEnable:
                    for key, item in sorted(memProcUsage.items(), \
                        key=lambda e: 0 \
                        if not 'maxRss' in e[1] else e[1]['maxRss'], \
                        reverse=True):

                        # check top number #
                        if SysMgr.nrTop:
                            if tcnt >= SysMgr.nrTop:
                                break
                            else:
                                tcnt += 1

                        try:
                            usage = \
                                list(map(long, item['rssUsage'].split()))[:lent]
                        except:
                            continue

                        # update the maximum ytick #
                        maxusage = max(usage)
                        if ymax < maxusage:
                            ymax = maxusage

                        try:
                            minIdx = usage.index(min(usage))
                        except:
                            minIdx = long(0)

                        try:
                            maxIdx = usage.index(item['maxRss'])
                        except:
                            maxIdx = long(0)

                        key = '%s%s' % (prefix, key)
                        minval = '%s [%s]' % \
                            (key, convSize2Unit(usage[minIdx] << 20))
                        maxsize = convSize2Unit(usage[maxIdx] << 20)
                        maxval = '%s [%s]' % (key, maxsize)
                        lastsize = convSize2Unit(usage[-1] << 20)
                        lastval = '%s [%s]' % (key, lastsize)

                        if usage[minIdx] == usage[maxIdx] == 0:
                            continue

                        # ignore 0 #
                        usage = list(map(lambda x: x if x != 0 else None, usage))

                        # get color #
                        color = plot(timeline, usage, '-', \
                            linewidth=1)[0].get_color()

                        if usage[minIdx]:
                            text(timeline[minIdx], usage[minIdx] + margin, \
                                minval, color=color, fontsize=3, \
                                ha=getTextAlign(minIdx, timeline))
                        if usage[minIdx] != usage[maxIdx] and usage[maxIdx]:
                            text(timeline[maxIdx], usage[maxIdx] + margin, \
                                maxval, color=color, fontsize=3, \
                                ha=getTextAlign(maxIdx, timeline))
                        if usage[-1]:
                            text(timeline[-1], usage[-1] + margin, \
                                lastval, color=color, fontsize=3, \
                                ha='right')

                        # set memory type #
                        if SysMgr.pssEnable:
                            mem = 'PSS'
                        elif SysMgr.ussEnable:
                            mem = 'USS'
                        else:
                            mem = 'RSS'

                        labelList.append('%s [%s] - %s' % (key, mem, maxsize))

                # System #
                else:
                    # System Free Memory #
                    lastsize, ymax = drawSystemMem(memFree, 'blue', ymax)
                    if lastsize is not None:
                        if totalRam:
                            label = \
                                '%s[ RAM Total ] - %s\nRAM Available - %s' % \
                                    (prefix, convSize2Unit(totalRam), lastsize)
                            labelList.append(label)
                        else:
                            labelList.append(\
                                '%sRAM Available - %s' % (prefix, lastsize))

                    # System Anon Memory #
                    lastsize, ymax = drawSystemMem(memAnon, 'skyblue', ymax)
                    if lastsize is not None:
                        labelList.append(\
                            '%sRAM User - %s' % (prefix, lastsize))

                    # System Cache Memory #
                    lastsize, ymax = drawSystemMem(memCache, 'darkgray', ymax)
                    if lastsize is not None:
                        labelList.append(\
                            '%sRAM Cache - %s' % (prefix, lastsize))

                    # System Swap Memory #
                    lastsize, ymax = drawSystemMem(swapUsage, 'orange', ymax)
                    if lastsize is not None:
                        if totalSwap:
                            label = \
                                '%s[ Swap Total ] - %s\nSwap Usage - %s' % \
                                (prefix, convSize2Unit(totalSwap), lastsize)
                            labelList.append(label)
                        else:
                            labelList.append(\
                                '%sSwap Usage - %s' % (prefix, lastsize))

            '''
            ylabel('MEMORY', fontsize=5)
            ax.yaxis.set_label_coords(-0.05,0.5)
            '''

            if SysMgr.matplotlibVersion >= 1.2:
                legend(labelList, bbox_to_anchor=(1.12, 0.75), \
                    fontsize=3.5, loc='upper right')
            else:
                legend(labelList, bbox_to_anchor=(1.12, 0.75), loc='upper right')

            grid(which='both', linestyle=':', linewidth=0.2)
            tick_params(axis='x', direction='in')
            tick_params(axis='y', direction='in')

            # adjust yticks #
            ylist = ax.get_yticks().tolist()

            # set ymin #
            ymin = long(min(ylist))
            if ymin < 0:
                ymin = long(0)
            elif ymin == 0:
                try:
                    ax.set_ylim(bottom=0)
                except:
                    pass

            # update ymax #
            if SysMgr.funcDepth > 0:
                ymax = SysMgr.funcDepth

            # update yticks #
            ylim([ymin, ymax+int(ymax/10)])

            inc = long(ymax / 10)
            if inc == 0:
                inc = 1

            # set yticks #
            yticks(range(ymin, ymax + inc, inc), fontsize=5)

            try:
                #ax.get_xaxis().set_visible(False)
                ytickLabel = ax.get_yticks().tolist()
                ytickLabel = list(map(long, ytickLabel))

                # convert label units #
                ytickLabel = \
                    [convSize2Unit(val << 20) for val in ytickLabel]

                # remove redundant ticks #
                lastTick = ''
                tempLabelList = list(ytickLabel)
                for idx, ytick in enumerate(tempLabelList):
                    if lastTick == ytick:
                        ytickLabel[idx] = ''
                    else:
                        lastTick = ytick

                ax.set_yticklabels(ytickLabel)
            except:
                pass

            xticks(fontsize=4)
            if len(timeline) > 1:
                xlim([timeline[0], timeline[-1]])

            #ticklabel_format(useOffset=False)
            locator_params(axis = 'x', nbins=30)
            self.figure = \
                figure(num=1, figsize=(10, 10), facecolor='b', edgecolor='k')
            self.figure.subplots_adjust(left=0.06, top=0.95, bottom=0.04)

            drawBottom(xtype, ax)

        #==================== BODY PART ====================#

        SysMgr.printStat(r"start drawing graphs...")

        # get matplotlib object #
        matplotlib = SysMgr.getPkg('matplotlib', False)
        if not matplotlib:
            SysMgr.printPipWarn('matplotlib', 'matplotlib')
            sys.exit(0)
        from matplotlib.ticker import MaxNLocator

        SysMgr.matplotlibVersion = \
            float('.'.join(matplotlib.__version__.split('.')[:2]))

        matplotlib.use('Agg')

        # get pylab object #
        SysMgr.importPkgItems('pylab')

        # set dpi #
        matplotlib.rcParams['figure.dpi'] = SysMgr.matplotlibDpi

        '''
        initialize list that count the number of process
        using resource more than 1% #
        '''

        # get timeline #
        if 'timeline' in graphStats:
            timeline = graphStats['timeline']
        else:
            timeline = []
            for key, val in graphStats.items():
                if key.endswith('timeline') and len(val) > len(timeline):
                    timeline = val

        # get nrCore #
        if 'nrCore' in graphStats:
            nrCore = graphStats['nrCore']
        else:
            nrCore = []
            for key, val in graphStats.items():
                if key.endswith('nrCore') and len(val) > len(nrCore):
                    nrCore = val

        # get effectProcList #
        effectProcList = [0] * len(timeline)

        if not SysMgr.layout:
            drawCpu(graphStats, 3, 0, 4)

            # draw events on graphs #
            drawEvent(graphStats)

            drawIo(graphStats, 2, 4, 1)

            drawMem(graphStats, 1, 5, 1)
        else:
            pos = long(0)
            total = long(0)
            layoutDict = {}
            layoutList = []
            layout = SysMgr.layout.split(',')

            # sum size of graph boxes #
            for idx, graph in enumerate(layout):
                try:
                    if len(graph.split(':')) == 1:
                        target = graph
                        size = 1
                    else:
                        (target, size) = graph.split(':')

                    # check duplicated graph #
                    try:
                        layoutDict[target]
                        SysMgr.printErr(\
                            "Fail to draw graph "
                            "because %s graph is duplicated" % target)
                        sys.exit(0)
                    except SystemExit:
                        sys.exit(0)
                    except:
                        layoutDict[target] = True

                    size = long(size)
                    if size == 0:
                        raise Exception()
                    else:
                        total += size
                        layoutList.append([target, long(size)])
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printErr(\
                        "Fail to draw graph "
                        "because graph format [TYPE:SIZE] is wrong")
                    sys.exit(0)

            for idx, item in enumerate(layoutList):
                target = item[0]
                size = item[1]

                # convert size to proportion #
                size = long((size / float(total)) * 6)

                try:
                    xtype = len(layoutList) - idx

                    targetc = target.upper()

                    if targetc == 'CPU' or targetc.startswith('C'):
                        drawCpu(graphStats, xtype, pos, size)
                    elif targetc == 'MEM' or targetc.startswith('M'):
                        drawMem(graphStats, xtype, pos, size)
                    elif targetc == 'IO' or targetc.startswith('I'):
                        drawIo(graphStats, xtype, pos, size)
                    else:
                        SysMgr.printErr(\
                            "Fail to draw graph "
                            "because '%s' is not recognized" % target)
                        sys.exit(0)

                    if idx == 0:
                        # draw events on graphs #
                        drawEvent(graphStats)

                    pos += size
                except SystemExit:
                    sys.exit(0)
                except:
                    err = SysMgr.getErrMsg()
                    raise Exception(err)

        # draw system info #
        try:
            if SysMgr.systemInfoBuffer and \
                len(SysMgr.systemInfoBuffer) > 0:
                if not SysMgr.origArgs:
                    SysMgr.origArgs = ['None']

                # add draw command #
                drawCmdStr = "{0:20} # {1:<100}".\
                    format('DrawCmd', ' '.join(SysMgr.origArgs))
                SysMgr.systemInfoBuffer = \
                    SysMgr.systemInfoBuffer[:-1] + drawCmdStr

                self.figure.text(\
                    0, 1, SysMgr.systemInfoBuffer,\
                        va='top', ha='left', size=2)
        except:
            SysMgr.printWarn(\
                "Fail to write system info", True, reason=True)

        # remove stats to free memory #
        graphStats.clear()

        # save to file #
        self.saveImage(logFile, 'graph', outFile=outFile)



    def saveImage(self, logFile, itype='', outFile=None):
        try:
            # build output file name #
            if outFile:
                outputFile = outFile
            else:
                if SysMgr.printFile:
                    outputFile = os.path.normpath(SysMgr.printFile)
                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.png' % (name, itype)

            # 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(\
                    '%s is renamed to %s' % (outputFile, oldPath))
        except:
            SysMgr.printErr(\
                "Fail to backup %s to %s" % (outputFile, oldPath), True)

        # get pylab object #
        SysMgr.importPkgItems('pylab')

        try:
            # save graph #
            savefig(outputFile, dpi=SysMgr.matplotlibDpi) # pylint: disable=undefined-variable
            clf() # pylint: disable=undefined-variable

            # get output size #
            try:
                fsize = \
                    UtilMgr.convSize2Unit(\
                        long(os.path.getsize(outputFile)))
            except:
                fsize = '?'

            SysMgr.printStat(\
                "write resource %s into %s [%s]" % (itype, outputFile, fsize))
        except:
            SysMgr.printErr(\
                "Fail to draw image to %s" % outputFile, True)
            return



    def sampleStack(self, period):
        def findNthStr(s, x, n, i = 0):
            i = s.find(x, i)
            if n == 1 or i == -1:
                return i
            else:
                return findNthStr(s, x, n - 1, i + len(x))

        start = time.time()

        while 1:
            for idx in list(self.stackTable.keys()):
                item = self.stackTable[idx]

                # read stack #
                try:
                    item['fd'].seek(0)
                    stack = item['fd'].read()
                except SystemExit:
                    sys.exit(0)
                except:
                    self.stackTable.pop(idx, None)
                    continue

                # cut stack length #
                try:
                    if SysMgr.funcDepth > 0:
                        nth = findNthStr(stack, '\n', SysMgr.funcDepth)
                        stack = stack[:nth]
                except:
                    pass

                # count sampled stack #
                try:
                    item['total'] += 1
                    item['stack'][stack] += 1
                except SystemExit:
                    sys.exit(0)
                except:
                    item['stack'][stack] = 1

            if time.time() - start >= period:
                return

            # set 1ms as sampling rate #
            time.sleep(0.001)



    def getRunTaskNum(self):
        return len(self.threadData) - SysMgr.nrCore



    def printCreationTree(self, tid, loc):
        try:
            childList = self.threadData[tid]['childList']
        except:
            return

        threadName = "%s(%s)" % (self.threadData[tid]['comm'], tid)

        if self.threadData[tid]['createdTime'] > 0:
            threadName += " /%2.3f/" % \
                (self.threadData[tid]['createdTime'] - \
                float(SysMgr.startTime))

        if self.threadData[tid]['usage'] > 0:
            threadName += " <%2.3f>" % (self.threadData[tid]['usage'])

        if self.threadData[tid]['childList']:
            threadName += " |%d|" % (len(self.threadData[tid]['childList']))

        if self.threadData[tid]['waitChild'] > 0:
            threadName += " {%1.3f}" % (self.threadData[tid]['waitChild'])

        if self.threadData[tid]['waitParent'] > 0:
            threadName += " [%1.3f]" % (self.threadData[tid]['waitParent'])

        # set new position of line #
        newLoc = loc + 5

        if self.threadData[tid]['die'] == ' ':
            life = '+ '
        else:
            life = '- '

        SysMgr.printPipe(' ' * loc + life + threadName)

        if childList:
            for thread in childList:
                self.printCreationTree(thread, newLoc)



    @staticmethod
    def getCoreId(string):
        try:
            offset = string.rfind('/')
            if offset >= 0:
                return long(string[offset+1:])
            else:
                return -1
        except:
            return -1



    def printComInfo(self):
        convertNum = UtilMgr.convNum

        # print thread tree by creation #
        if SysMgr.showAll and self.nrNewTask > 0:
            SysMgr.clearPrint()
            SysMgr.printPipe((\
                '\n[Thread Creation Info] [Alive: +] [Die: -] '
                '[CreatedTime: //] [ChildCount: ||] '
                '[CpuUsage: <>] [WaitForChilds: {}] '
                '[WaitOfParent: []]'))
            SysMgr.printPipe(twoLine)

            cnt = long(0)
            for key, value in sorted(\
                self.threadData.items(), \
                key=lambda e: e[1]['waitChild'], reverse=True):

                # print tree from root threads #
                if value['childList'] and value['new'] == ' ':
                    cnt += 1
                    self.printCreationTree(key, 0)
            if cnt == 0:
                SysMgr.printPipe('\tNone')
            SysMgr.printPipe(oneLine)

        # print signal traffic #
        if SysMgr.showAll and len(self.sigData) > 0:
            SysMgr.clearPrint()
            SysMgr.printPipe('\n[Thread Signal Info]')
            SysMgr.printPipe(twoLine)
            SysMgr.printPipe(\
                "{0:^6} {1:^16} {2:>10}({3:>5}) {4:^10} {5:>16}({6:>5})".\
                format('TYPE', 'TIME', 'SENDER', \
                'TID', 'SIGNAL', 'RECEIVER', 'TID'))
            SysMgr.printPipe(twoLine)

            cnt = long(0)
            for val in self.sigData:
                try:
                    signal = ConfigMgr.SIG_LIST[int(val[4])]
                except:
                    signal = 'SIG_%s' % val[4]

                stype = val[0]
                stime = val[1]
                stid = val[2]
                rtid = val[3]

                # skip useless signal log #
                if ((stid and stid[0] == '0') or \
                    stid not in self.threadData) and \
                    ((rtid and rtid[0] == '0') or \
                    rtid not in self.threadData):
                    continue

                try:
                    scomm = self.threadData[stid]['comm']
                except:
                    scomm = '?'

                try:
                    rcomm = self.threadData[rtid]['comm']
                except:
                    rcomm = '?'

                if stype == 'SEND':
                    if stid.startswith('0['):
                        stid = long(0)

                    SysMgr.printPipe((\
                        "{0:^6} {1:>10.6f} {2:>16}({3:>5}) "
                        "{4:^10} {5:>16}({6:>5})").\
                        format(stype, stime, scomm, stid, \
                        signal, rcomm, rtid))

                    cnt += 1
                elif val[0] == 'RECV':
                    SysMgr.printPipe((\
                        "{0:^6} {1:>10.6f} {2:>16} {3:>5}  "
                        "{4:^10} {5:>16}({6:>5})").\
                        format(stype, stime, ' ', ' ', signal, rcomm, rtid))

                    cnt += 1
            if cnt == 0:
                SysMgr.printPipe('\tNone')
            SysMgr.printPipe(oneLine)

        # print interrupt information #
        if len(self.irqData) > 0:
            totalCnt = long(0)
            totalUsage = float(0)

            SysMgr.printPipe('\n[Thread IRQ Info]')
            SysMgr.printPipe(twoLine)
            SysMgr.printPipe((\
                "{0:^16}({1:^62}): {2:^12} {3:^10} {4:^10} "
                "{5:^10} {6:^10} {7:^10}").\
                format("IRQ", "Name", "Count", "Usage", "ProcMax", \
                "ProcMin", "InterMax", "InterMin"))
            SysMgr.printPipe(twoLine)

            SysMgr.clearPrint()

            # print irq list #
            irqList = [irq for irq in list(self.irqData.keys()) \
                if irq.startswith('irq')]
            for key in sorted(irqList, key=lambda e:int(e.split('/')[1])):
                totalCnt += self.irqData[key]['count']
                totalUsage += self.irqData[key]['usage']
                SysMgr.addPrint(\
                    ("{0:>16}({1:^62}): {2:>12} {3:^10.6f} {4:^10.6f} "
                    "{5:^10.6f} {6:^10.6f} {7:^10.6f}\n").\
                    format(key, \
                    ' | '.join(list(self.irqData[key]['name'].keys())), \
                    convertNum(self.irqData[key]['count']), \
                    self.irqData[key]['usage'], \
                    self.irqData[key]['max'], self.irqData[key]['min'], \
                    self.irqData[key]['maxPeriod'], \
                    self.irqData[key]['minPeriod']))

            # print softirq list #
            sirqList = [irq for irq in list(self.irqData.keys()) \
                if irq.startswith('softirq')]
            for key in sorted(sirqList, key=lambda e:int(e.split('/')[1])):
                totalCnt += self.irqData[key]['count']
                totalUsage += self.irqData[key]['usage']
                SysMgr.addPrint(\
                    ("{0:>16}({1:^62}): {2:>12} {3:^10.6f} {4:^10.6f} "
                    "{5:^10.6f} {6:^10.6f} {7:^10.6f}\n").format(\
                    key, ' | '.join(list(self.irqData[key]['name'].keys())), \
                    convertNum(self.irqData[key]['count']), \
                    self.irqData[key]['usage'], \
                    self.irqData[key]['max'], self.irqData[key]['min'], \
                    self.irqData[key]['maxPeriod'], \
                    self.irqData[key]['minPeriod']))

            SysMgr.printPipe(\
                "%s# IRQ(%s) / Total(%6.3f) / Cnt(%s)\n" % \
                    ('', convertNum(len(self.irqData)), \
                    totalUsage, convertNum(totalCnt)))
            SysMgr.doPrint()
            SysMgr.printPipe(oneLine)



    def printEventInfo(self):
        # pick up event info from thread info #
        for key, value in sorted(self.threadData.items()):
            if value['customEvent']:
                self.customInfo[key] = value['customEvent']
            if value['userEvent']:
                self.userInfo[key] = value['userEvent']
            if value['kernelEvent']:
                self.kernelInfo[key] = value['kernelEvent']

        # print custom event info #
        if len(self.customEventInfo) > 0:
            SysMgr.clearPrint()
            SysMgr.printPipe('\n[Thread CUSTOM Event Info]')
            SysMgr.printPipe(twoLine)
            SysMgr.printPipe(\
                "{0:^32} {1:>16}({2:^5}) {3:>10} {4:>10} {5:>10}".\
                format('Event', 'Comm', 'Tid', 'Count', \
                'MaxPeriod', 'MinPeriod'))
            SysMgr.printPipe(twoLine)

            newLine = False
            for idx, val in sorted(\
                self.customEventInfo.items(), key=lambda e: e[1]['count'], \
                reverse=True):
                if newLine:
                    SysMgr.printPipe()
                else:
                    newLine = True

                SysMgr.printPipe(\
                    "{0:^32} {1:>16}({2:^5}) {3:>10} {4:>10.6f} {5:>10.6f}".\
                    format(idx, 'TOTAL', '-', val['count'], val['maxPeriod'], \
                    val['minPeriod']))

                for key, value in sorted(self.customInfo.items(), \
                    key=lambda e: 0 if not idx in e[1] else e[1][idx]['count'], \
                    reverse=True):

                    try:
                        value[idx]
                        self.threadData[key]['comm']
                    except:
                        continue

                    SysMgr.printPipe(\
                        "{0:^32} {1:>16}({2:>5}) {3:>10} {4:>10.6f} {5:>10.6f}".\
                        format(' ', self.threadData[key]['comm'], key, \
                        value[idx]['count'], value[idx]['maxPeriod'], \
                        value[idx]['minPeriod']))
            SysMgr.printPipe(oneLine)

        # print custom event history #
        if SysMgr.showAll and len(self.customEventData) > 0:
            SysMgr.clearPrint()
            SysMgr.printPipe('\n[Thread CUSTOM Event History]')
            SysMgr.printPipe(twoLine)
            SysMgr.printPipe(\
                "{0:^32} {1:^10} {2:>16}({3:>5}) {4:<1}".\
                format('EVENT', 'TIME', 'COMM', 'TID', 'ARG'))
            SysMgr.printPipe(twoLine)

            cnt = long(0)
            for val in self.customEventData:
                skipFlag = False
                for fval in SysMgr.filterGroup:
                    if SysMgr.isEffectiveTid(val[2], fval) or \
                        fval in val[1]:
                        skipFlag = False
                        break
                    skipFlag = True

                if skipFlag:
                    continue

                cnt += 1
                SysMgr.printPipe(\
                    "{0:^32} {1:>10.6f} {2:>16}({3:>5}) {4:<1}".\
                    format(val[0], val[3], val[1], val[2], val[4]))
            if cnt == 0:
                SysMgr.printPipe("\tNone")
            SysMgr.printPipe(oneLine)

        # print user event info #
        if len(self.userEventInfo) > 0:
            SysMgr.clearPrint()
            SysMgr.printPipe('\n[Thread User Event Info]')
            SysMgr.printPipe(twoLine)
            SysMgr.printPipe((\
                "{0:^32} {1:>16}({2:^5}) {3:>10} {4:>10} "
                "{5:>10} {6:>10} {7:>10} {8:>10}").\
                format('Event', 'Comm', 'Tid', 'Usage', 'Count', \
                'ProcMax', 'ProcMin', 'InterMax', 'InterMin'))
            SysMgr.printPipe(twoLine)

            newLine = False
            for idx, val in sorted(\
                self.userEventInfo.items(), \
                key=lambda e: e[1]['usage'], reverse=True):

                if newLine:
                    SysMgr.printPipe()
                else:
                    newLine = True
                SysMgr.printPipe(\
                    ("{0:^32} {1:>16}({2:^5}) {3:>10.6f} {4:>10} {5:>10.6f} "
                    "{6:>10.6f} {7:>10.6f} {8:>10.6f}").\
                    format(idx, 'TOTAL', '-', val['usage'], val['count'], \
                    val['max'], val['min'], val['maxPeriod'], val['minPeriod']))

                for key, value in sorted(self.userInfo.items(), \
                    key=lambda e: 0 if not idx in e[1] else e[1][idx]['usage'], \
                    reverse=True):

                    try:
                        value[idx]
                        self.threadData[key]['comm']
                    except:
                        continue

                    SysMgr.printPipe(\
                        ("{0:^32} {1:>16}({2:>5}) {3:>10.6f} {4:>10} "
                        "{5:>10.6f} {6:>10.6f} {7:>10.6f} {8:>10.6f}").\
                        format(' ', self.threadData[key]['comm'], key, \
                        value[idx]['usage'], value[idx]['count'], \
                        value[idx]['max'], value[idx]['min'], \
                        value[idx]['maxPeriod'], value[idx]['minPeriod']))
            SysMgr.printPipe(oneLine)

        # print user event history #
        if SysMgr.showAll and len(self.userEventData) > 0:
            SysMgr.clearPrint()
            SysMgr.printPipe('\n[Thread User Event History]')
            SysMgr.printPipe(twoLine)
            SysMgr.printPipe(\
                "{0:^32} {1:^6} {2:^10} {3:>16}({4:>5}) {5:^16} {6:>10}".\
                format('EVENT', 'TYPE', 'TIME', 'COMM', 'TID', 'CALLER', 'ELAPSED'))
            SysMgr.printPipe(twoLine)

            cnt = long(0)
            callTable = {}
            for val in self.userEventData:
                elapsed = '-'

                skipFlag = False
                for fval in SysMgr.filterGroup:
                    if SysMgr.isEffectiveTid(val[3], fval) or \
                        fval in val[2]:
                        skipFlag = False
                        break
                    skipFlag = True

                if skipFlag:
                    continue
                elif val[0] == 'ENTER':
                    cid = '%s%s' % (val[1], val[3])
                    callTable[cid] = val[4]
                elif val[0] == 'EXIT':
                    cid = '%s%s' % (val[1], val[3])
                    try:
                        elapsed = '%.6f' % (val[4] - callTable[cid])
                    except:
                        pass

                cnt += 1
                SysMgr.printPipe((\
                    "{0:^32} {1:>6} {2:>10.6f} {3:>16}({4:>5}) "
                    "{5:>16} {6:>10}").\
                    format(val[1], val[0], val[4], val[2], \
                    val[3], val[5], elapsed))
            if cnt == 0:
                SysMgr.printPipe("\tNone")
            SysMgr.printPipe(oneLine)

        # print kernel event info #
        if len(self.kernelEventInfo) > 0:
            SysMgr.clearPrint()
            SysMgr.printPipe('\n[Thread Kernel Event Info]')
            SysMgr.printPipe(twoLine)
            SysMgr.printPipe((\
                "{0:^32} {1:>16}({2:^5}) {3:>10} {4:>10} "
                "{5:>10} {6:>10} {7:>10} {8:>10}").\
                format('Event', 'Comm', 'Tid', 'Usage', 'Count', 'ProcMax', \
                'ProcMin', 'InterMax', 'InterMin'))
            SysMgr.printPipe(twoLine)

            newLine = False
            for idx, val in sorted(\
                self.kernelEventInfo.items(),\
                key=lambda e: e[1]['usage'], reverse=True):

                if newLine:
                    SysMgr.printPipe()
                else:
                    newLine = True
                SysMgr.printPipe(\
                    ("{0:^32} {1:>16}({2:^5}) {3:>10.6f} {4:>10} {5:>10.6f} "
                    "{6:>10.6f} {7:>10.6f} {8:>10.6f}").\
                    format(idx, 'TOTAL', '-', val['usage'], \
                    val['count'], val['max'], val['min'], \
                    val['maxPeriod'], val['minPeriod']))

                for key, value in sorted(self.kernelInfo.items(), \
                    key=lambda e: 0 if not idx in e[1] else e[1][idx]['usage'], \
                    reverse=True):

                    try:
                        value[idx]
                        self.threadData[key]['comm']
                    except:
                        continue

                    SysMgr.printPipe(\
                        ("{0:^32} {1:>16}({2:>5}) {3:>10.6f} {4:>10} "
                        "{5:>10.6f} {6:>10.6f} {7:>10.6f} {8:>10.6f}").\
                        format(' ', self.threadData[key]['comm'], key, \
                        value[idx]['usage'], value[idx]['count'], \
                        value[idx]['max'], value[idx]['min'], \
                        value[idx]['maxPeriod'], value[idx]['minPeriod']))
            SysMgr.printPipe(oneLine)

        # print kernel event history #
        if not SysMgr.showAll or len(self.kernelEventData) == 0:
            return

        SysMgr.clearPrint()
        SysMgr.printPipe('\n[Thread Kernel Event History]')
        SysMgr.printPipe(twoLine)
        SysMgr.printPipe((\
            "{0:^32} {1:^6} {2:^10} {3:>16}({4:>5}) "
            "{5:^22} {6:>10} {7:<1}").\
            format('EVENT', 'TYPE', 'TIME', 'COMM', \
            'TID', 'CALLER', 'ELAPSED', 'ARG'))
        SysMgr.printPipe(twoLine)

        cnt = long(0)
        callTable = {}
        for val in self.kernelEventData:
            elapsed = '-'

            skipFlag = False
            for fval in SysMgr.filterGroup:
                if SysMgr.isEffectiveTid(val[4], fval) or \
                    fval in val[3]:
                    skipFlag = False
                    break
                skipFlag = True

            if skipFlag:
                continue
            elif val[0] == 'ENTER':
                cid = '%s%s' % (val[1], val[4])
                callTable[cid] = val[5]
            elif val[0] == 'EXIT':
                cid = '%s%s' % (val[1], val[4])
                try:
                    elapsed = '%.6f' % (val[5] - callTable[cid])
                except:
                    pass

            cnt += 1
            args = (' '.join(val[7].split(' arg'))).replace('=','>')
            SysMgr.printPipe((\
                "{0:^32} {1:>6} {2:>10.6f} {3:>16}({4:>5}) "
                "{5:>22} {6:>10} {7:<1}").\
                format(val[1], val[0], val[5], val[3], \
                val[4], val[6], elapsed, args))
        if cnt == 0:
            SysMgr.printPipe("\tNone")
        SysMgr.printPipe(oneLine)



    def printUsage(self):
        # print thread usage #
        self.printResourceUsage()

        # print communication usage #
        self.printComInfo()

        # print event usage #
        self.printEventInfo()

        # print block usage #
        self.printBlockInfo()

        # print resource usage of threads on timeline #
        self.printIntervalInfo()

        # print kernel module info #
        self.printModuleInfo()

        # print dependency of threads #
        self.printDepInfo()

        # print futex and flock of threads #
        self.printFutexInfo()
        self.printFlockInfo()

        # print systemcall usage #
        self.printSyscallInfo()

        # print kernel messages #
        self.printConsoleInfo()



    def printResourceUsage(self):
        # pylint: disable=undefined-variable

        title = 'Thread Info'

        SysMgr.printLogo(big=True)

        # print system information #
        SysMgr.printInfoBuffer()

        convertFunc = UtilMgr.convSize2Unit
        convertNum = UtilMgr.convNum

        # check trace event #
        if not (SysMgr.cpuEnable or \
            SysMgr.memEnable or \
            SysMgr.blockEnable):
            return

        # print menu #
        SysMgr.printPipe((\
            "[%s] [ %s: %0.3f ] [ %s: %0.3f ] [ ActiveThread: %s ] " + \
            "[ ContextSwitch: %s ] [ LogSize: %s ] (Unit: Sec/MB/NR)") % \
            (title, 'Elapsed', round(float(self.totalTime), 7), \
            'Start', round(float(SysMgr.startTime), 7), \
            convertNum(self.getRunTaskNum()), \
            convertNum(self.cxtSwitch), \
            convertFunc(SysMgr.logSize)))
        SysMgr.printPipe(twoLine)

        lastAField = "{0:_^17}|{1:_^16}".format("Mem Info", "Process")
        lastBField = "%3s|%3s|%4s(%2s)" % ('Rcl', 'Wst', 'DRcl', 'Nr')

        SysMgr.printPipe(\
            "{0:_^32}|{1:_^35}|{2:_^22}|{3:_^26}|{4:_^34}|".format(\
                title, "CPU Info", "SCHED Info", "BLOCK Info", lastAField))

        SysMgr.printPipe(\
            "{0:^32}|{0:^35}|{0:^22}|{0:^26}|{0:^34}|".format(""))

        SysMgr.printPipe((\
            "%16s(%5s/%5s)|%2s|%5s(%5s)|%5s|%6s|%3s|%5s|"
            "%5s|%5s|%5s|%4s|%5s(%3s/%4s)|%5s(%3s)|%4s(%3s/%3s/%3s)|%s|") % \
            ('Name', 'Tid', 'Pid', 'LF', 'Usage', '%', 'Prmt', 'Latc', 'Pri', \
            'IRQ', 'Yld', ' Lose', 'Steal', 'Mig', \
            'Read', 'MB', 'Cnt', 'Write', 'MB', \
            'Sum', 'Usr', 'Buf', 'Ker', lastBField))
        SysMgr.printPipe(twoLine)

        # initialize swapper thread per core #
        for n in range(0, SysMgr.maxCore + 1):
            try:
                if len(SysMgr.perCoreList) > 0 and \
                    n not in SysMgr.perCoreList:
                    continue

                coreId = '0[%s]' % n
                self.threadData[coreId]
            except:
                self.threadData[coreId] = dict(self.init_threadData)
                self.threadData[coreId]['comm'] = 'swapper/' + str(n)
                self.threadData[coreId]['usage'] = long(0)

        # sort by size of io usage and convert read blocks to MB size #
        for key, value in sorted(self.threadData.items(), \
            key=lambda e: e[1]['readBlock'], reverse=True):

            if value['readBlock'] > 0:
                value['readBlock'] = \
                    (value['readBlock'] * SysMgr.blockSize) >> 20
            if value['writeBlock'] > 0:
                value['writeBlock'] = \
                    (value['writeBlock'] * SysMgr.blockSize) >> 20
            if value['awriteBlock'] > 0:
                value['awriteBlock'] = \
                    (value['awriteBlock'] * SysMgr.pageSize) >> 20

        # print total information after sorting by CPU usage #
        count = long(0)
        SysMgr.clearPrint()
        for key, value in sorted(self.threadData.items(), \
            key=lambda e: ThreadAnalyzer.getCoreId(e[1]['comm']), reverse=False):

            if key[0:2] != '0[':
                # convert priority #
                try:
                    prio = long(value['pri']) - 120
                    if prio >= -20:
                        value['pri'] = str(prio)
                    else:
                        value['pri'] = 'R%2s' % abs(prio + 21)
                except:
                    pass

                continue

            # change the name of swapper thread to CORE #
            value['comm'] = value['comm'].replace("swapper", "CORE")

            # modify idle time if this core is not woke up ever #
            if value['usage'] == 0 and value['coreSchedCnt'] == 0:
                value['usage'] = self.totalTime

            # calculate total core usage percentage #
            try:
                idle = float(value['usage']) / float(self.totalTime)
                usagePercent = 100 - (round(idle, 7) * 100)
            except:
                usagePercent = long(0)

            if value['lastOff'] > 0:
                value['offTime'] += float(self.finishTime) - value['lastOff']

            if SysMgr.powerEnable:
                prtTime = offTime = '%5.2f' % value['offTime']
                pri = offCnt = str(value['offCnt'])
            else:
                prtTime = offTime = '-'
                pri = offCnt = '-'

            if SysMgr.cpuEnable:
                cpuTime = '%5.2f' % (self.totalTime - value['usage'])
                cpuPer = '%5.1f' % usagePercent
                schedLatency = '%5.2f' % value['schedLatency']
                yieldCnt = '%5s' % convertFunc(value['yield'])
                preemptedCnt = '%5s' % convertFunc(value['preempted'])
                preemptionCnt = '%5s' % convertFunc(value['preemption'])
                migrateCnt = '%4s' % convertFunc(value['migrate'])
            else:
                cpuTime = '-'
                cpuPer = '-'
                schedLatency = '-'
                yieldCnt = '-'
                preemptedCnt = '-'
                preemptionCnt = '-'
                migrateCnt = '-'

            if SysMgr.irqEnable:
                irqTime = '%5.2f' % value['irq']
            else:
                irqTime = '-'

            if SysMgr.blockEnable:
                ioRdWait = '%5.2f' % value['ioRdWait']
                readBlock = '%3d' % value['readBlock']
                readBlockCnt = '%4d' % value['readBlockCnt']
                ioWrWait = '%5.2f' % value['ioWrWait']
                writeBlock = '%3d' % \
                    (value['writeBlock'] + value['awriteBlock'])
            else:
                ioRdWait = '-'
                readBlock = '-'
                readBlockCnt = '-'
                ioWrWait = '-'
                writeBlock = '-'

            if SysMgr.memEnable:
                usedMem = '%4d' % \
                    ((value['nrPages'] >> 8) + (value['remainKmem'] >> 20))
                userMem = '%3d' % (value['userPages'] >> 8)
                cacheMem = '%3d' % (value['cachePages'] >> 8)
                kernelMem = '%3d' % \
                    ((value['kernelPages'] >> 8) + \
                    (value['remainKmem'] >> 20))
                reclaimedMem = '%3d' % (value['reclaimedPages'] >> 8)
                wastedMem = '%3d' % (value['wasteKmem'] >> 20)
                dreclaimedTime = '%4.2f' % value['dReclaimWait']
                dreclaimedCnt = '%2d' % value['dReclaimCnt']
            else:
                usedMem = '-'
                userMem = '-'
                cacheMem = '-'
                kernelMem = '-'
                reclaimedMem = '-'
                wastedMem = '-'
                dreclaimedTime = '-'
                dreclaimedCnt = '-'

            lastField = "%3s|%3s|%4s(%2s)" % \
                (reclaimedMem, wastedMem, dreclaimedTime, dreclaimedCnt)

            SysMgr.addPrint(\
                ("%16s(%5s/%5s)|%s%s|%5s(%5s)|%5s|%6s|%3s|%5s|"
                "%5s|%5s|%5s|%4s|%5s(%3s/%4s)|%5s(%3s)|"
                "%4s(%3s/%3s/%3s)|%s|\n") % \
                    (value['comm'], '-'*5, '-'*5, '-', '-', \
                    cpuTime, cpuPer, prtTime, schedLatency, pri, irqTime, \
                    yieldCnt, preemptedCnt, preemptionCnt, migrateCnt, \
                    ioRdWait, readBlock, readBlockCnt, ioWrWait, writeBlock, \
                    usedMem, userMem, cacheMem, kernelMem, lastField))
            count += 1

        SysMgr.printPipe("%s# %s: %d\n" % ('', 'CPU', count))
        SysMgr.doPrint()
        SysMgr.printPipe(oneLine)

        # 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]['readBlock'] + e[1]['writeBlock'] + e[1]['awriteBlock'], \
                reverse=True)
        else:
            # set CPU usage as default #
            sortedThreadData = sorted(self.threadData.items(), \
                key=lambda e: e[1]['usage'], reverse=True)

        # set total CPU variables #
        totalCpuTime = long(0)
        totalPrtTime = long(0)
        totalSchedLatency = long(0)
        totalYieldCnt = long(0)
        totalPreemptedCnt = long(0)
        totalPreemptionCnt = long(0)
        totalMigrateCnt = long(0)

        # set total irq variables #
        totalIrqTime = long(0)

        # set total io variables #
        totalIoRdWait = long(0)
        totalReadBlock = long(0)
        totalReadBlockCnt = long(0)
        totalIoWrWait = long(0)
        totalWriteBlock = long(0)

        # set total mem variables #
        totalUsedMem = long(0)
        totalUserMem = long(0)
        totalCacheMem = long(0)
        totalKernelMem = long(0)
        totalReclaimedMem = long(0)
        totalWastedMem = long(0)
        totalDreclaimedTime = long(0)
        totalDreclaimedCnt = long(0)

        # define variables for tasks #
        normCnt = long(0)
        newCnt = long(0)
        dieCnt = long(0)
        normThreadString = ''
        newThreadString = ''
        dieThreadString = ''

        # print thread information after sorting by time of CPU usage #
        count = long(0)
        SysMgr.clearPrint()
        for key, value in sortedThreadData:
            if key[0:2] == '0[':
                continue

            try:
                usagePercent = \
                    round(float(value['usage']) / float(self.totalTime), 7) * 100
            except:
                usagePercent = long(0)

            # set break condition #
            if SysMgr.sort == 'm':
                breakCond = value['nrPages']
            elif SysMgr.sort == 'b':
                breakCond = \
                    value['readBlock'] + value['writeBlock'] + \
                    value['awriteBlock']
            else:
                breakCond = usagePercent

            if breakCond < 1 and \
                not SysMgr.showAll and \
                SysMgr.filterGroup == []:
                break

            if SysMgr.cpuEnable:
                cpuTime = '%5.2f' % value['usage']
                totalCpuTime += value['usage']

                cpuPer = '%5.1f' % usagePercent

                prtTime = '%5.2f' % value['cpuWait']
                totalPrtTime += value['cpuWait']

                schedLatency = '%5.2f' % value['schedLatency']
                totalSchedLatency += value['schedLatency']

                pri = value['pri']

                yieldCnt = '%5s' % convertFunc(value['yield'])
                totalYieldCnt += value['yield']

                preemptedCnt = '%5s' % convertFunc(value['preempted'])
                totalPreemptedCnt += value['preempted']

                preemptionCnt = '%5s' % convertFunc(value['preemption'])
                totalPreemptionCnt += value['preemption']

                migrateCnt = '%4s' % convertFunc(value['migrate'])
                totalMigrateCnt += value['migrate']
            else:
                cpuTime = '-'
                cpuPer = '-'
                prtTime = '-'
                schedLatency = '-'
                pri = '-'
                yieldCnt = '-'
                preemptedCnt = '-'
                preemptionCnt = '-'
                migrateCnt = '-'

                totalCpuPer = '-'
                totalCpuTime = '-'
                totalPrtTime = '-'
                totalSchedLatency = '-'
                totalYieldCnt = '-'
                totalPreemptedCnt = '-'
                totalPreemptionCnt = '-'
                totalMigrateCnt = '-'

            if SysMgr.irqEnable:
                irqTime = '%5.2f' % value['irq']
                totalIrqTime += value['irq']
            else:
                irqTime = '-'
                totalIrqTime = '-'

            if SysMgr.blockEnable:
                ioRdWait = '%5.2f' % value['ioRdWait']
                totalIoRdWait += value['ioRdWait']

                readBlock = '%3d' % value['readBlock']
                totalReadBlock += value['readBlock']

                readBlockCnt = '%4d' % value['readBlockCnt']
                totalReadBlockCnt += value['readBlockCnt']

                ioWrWait = '%5.2f' % value['ioWrWait']
                totalIoWrWait += value['ioWrWait']

                writeBlock = '%3d' % \
                    (value['writeBlock'] + value['awriteBlock'])
                totalWriteBlock += (value['writeBlock'] + value['awriteBlock'])
            else:
                ioRdWait = '-'
                readBlock = '-'
                readBlockCnt = '-'
                ioWrWait = '-'
                writeBlock = '-'

                totalIoRdWait = '-'
                totalReadBlock = '-'
                totalReadBlockCnt = '-'
                totalIoWrWait = '-'
                totalWriteBlock = '-'

            if SysMgr.memEnable:
                usedMem = \
                    ((value['nrPages'] >> 8) + (value['remainKmem'] >> 20))
                totalUsedMem += usedMem
                usedMem = '%4d' % usedMem

                userMem = '%3d' % (value['userPages'] >> 8)
                totalUserMem += (value['userPages'] >> 8)

                cacheMem = '%3d' % (value['cachePages'] >> 8)
                totalCacheMem += (value['cachePages'] >> 8)

                kernelMem = \
                    ((value['kernelPages'] >> 8) + (value['remainKmem'] >> 20))
                totalKernelMem += kernelMem
                kernelMem = '%3d' % kernelMem

                reclaimedMem = '%3d' % (value['reclaimedPages'] >> 8)
                totalReclaimedMem += (value['reclaimedPages'] >> 8)

                wastedMem = '%3d' % (value['wasteKmem'] >> 20)
                totalWastedMem += (value['wasteKmem'] >> 20)

                dreclaimedTime = '%4.2f' % value['dReclaimWait']
                totalDreclaimedTime += value['dReclaimWait']

                dreclaimedCnt = '%2d' % value['dReclaimCnt']
                totalDreclaimedCnt += value['dReclaimCnt']
            else:
                usedMem = '-'
                userMem = '-'
                cacheMem = '-'
                kernelMem = '-'
                reclaimedMem = '-'
                wastedMem = '-'
                dreclaimedTime = '-'
                dreclaimedCnt = '-'

                totalUsedMem = '-'
                totalUserMem = '-'
                totalCacheMem = '-'
                totalKernelMem = '-'
                totalReclaimedMem = '-'
                totalWastedMem = '-'
                totalDreclaimedTime = '-'
                totalDreclaimedCnt = '-'

            # set last field #
            if len(SysMgr.savedProcComm) > 0:
                if key in SysMgr.savedProcComm:
                    lastField = "{0:>16}".format(\
                        SysMgr.savedProcComm[key])
                elif value['tgid'] in SysMgr.savedProcComm:
                    lastField = "{0:>16}".format(\
                        SysMgr.savedProcComm[value['tgid']])
                elif key == value['tgid']:
                    lastField = "{0:>16}".format(value['comm'])
                else:
                    lastField = "{0:>16}".format('?')
            else:
                lastField = "%3s|%3s|%4s(%2s)" % \
                    (reclaimedMem, wastedMem, dreclaimedTime, dreclaimedCnt)

            if value['new'] != ' ':
                newCnt += 1
                newThreadString += (\
                    ("%16s(%5s/%5s)|%s%s|%5s(%5s)|%5s|%6s|%3s|%5s|"
                    "%5s|%5s|%5s|%4s|%5s(%3s/%4s)|%5s(%3s)|"
                    "%4s(%3s/%3s/%3s)|%s|\n") % \
                    (value['comm'], key, value['ptid'], value['new'], value['die'], \
                    cpuTime, cpuPer, prtTime, schedLatency, pri, irqTime, \
                    yieldCnt, preemptedCnt, preemptionCnt, migrateCnt, \
                    ioRdWait, readBlock, readBlockCnt, ioWrWait, writeBlock, \
                    usedMem, userMem, cacheMem, kernelMem, lastField))
            if value['die'] != ' ':
                dieCnt += 1
                dieThreadString += (\
                    ("%16s(%5s/%5s)|%s%s|%5s(%5s)|%5s|%6s|%3s|%5s|"
                    "%5s|%5s|%5s|%4s|%5s(%3s/%4s)|%5s(%3s)|"
                    "%4s(%3s/%3s/%3s)|%s|\n") % \
                    (value['comm'], key, value['ptid'], value['new'], value['die'], \
                    cpuTime, cpuPer, prtTime, schedLatency, pri, irqTime, \
                    yieldCnt, preemptedCnt, preemptionCnt, migrateCnt, \
                    ioRdWait, readBlock, readBlockCnt, ioWrWait, writeBlock, \
                    usedMem, userMem, cacheMem, kernelMem, lastField))

            normCnt += 1
            normThreadString += (\
                ("%16s(%5s/%5s)|%s%s|%5s(%5s)|%5s|%6s|%3s|%5s|"
                "%5s|%5s|%5s|%4s|%5s(%3s/%4s)|%5s(%3s)|"
                "%4s(%3s/%3s/%3s)|%s|\n") % \
                (value['comm'], key, value['tgid'], value['new'], value['die'], \
                cpuTime, cpuPer, prtTime, schedLatency, pri, irqTime, \
                yieldCnt, preemptedCnt, preemptionCnt, migrateCnt, \
                ioRdWait, readBlock, readBlockCnt, ioWrWait, writeBlock, \
                usedMem, userMem, cacheMem, kernelMem, lastField))

        # build total usage string #
        try:
            totalCpuPer = \
                '%5.1f' % (totalCpuTime / float(self.totalTime) * 100)
            totalCpuTime = '%5.2f' % totalCpuTime
            totalPrtTime = '%5.2f' % totalPrtTime
            totalSchedLatency = '%5.2f' % totalSchedLatency
            totalYieldCnt = '%5s' % convertFunc(totalYieldCnt)
            totalPreemptedCnt = '%5s' % convertFunc(totalPreemptedCnt)
            totalPreemptionCnt = '%5s' % convertFunc(totalPreemptionCnt)
            totalMigrateCnt = '%4s' % convertFunc(totalMigrateCnt)
        except:
            pass

        try:
            totalIrqTime = '%5.2f' % totalIrqTime
        except:
            pass

        try:
            totalIoRdWait = '%5.2f' % totalIoRdWait
            totalReadBlock = '%3d' % totalReadBlock
            totalReadBlockCnt = '%4d' % totalReadBlockCnt
            totalIoWrWait = '%5.2f' % totalIoWrWait
            totalWriteBlock = '%3d' % totalWriteBlock
        except:
            pass

        try:
            totalUsedMem = '%4d' % totalUsedMem
            totalUserMem = '%3d' % totalUserMem
            totalCacheMem = '%3d' % totalCacheMem
            totalKernelMem = '%3d' % totalKernelMem
            totalReclaimedMem = '%3d' % totalReclaimedMem
            totalWastedMem = '%3d' % totalWastedMem
            totalDreclaimedTime = '%4.2f' % totalDreclaimedTime
            totalDreclaimedCnt = '%2d' % totalDreclaimedCnt
        except:
            pass

        lastField = "%3s|%3s|%4s(%2s)" % \
            (totalReclaimedMem, totalWastedMem, \
            totalDreclaimedTime, totalDreclaimedCnt)

        # print TOTAL information #
        SysMgr.printPipe(\
            ("%29s|%s%s|%5s(%5s)|%5s|%6s|%3s|%5s|"
            "%5s|%5s|%5s|%4s|%5s(%3s/%4s)|%5s(%3s)|%4s(%3s/%3s/%3s)|%s|") % \
            ('{0:>29}'.format('[ TOTAL ]'), ' ', ' ', \
            totalCpuTime, totalCpuPer, totalPrtTime, totalSchedLatency, '-', \
            totalIrqTime, totalYieldCnt, totalPreemptedCnt, \
            totalPreemptionCnt, totalMigrateCnt, totalIoRdWait, \
            totalReadBlock, totalReadBlockCnt, totalIoWrWait, \
            totalWriteBlock, totalUsedMem, totalUserMem, totalCacheMem, \
            totalKernelMem, lastField))

        # print normal thread info #
        if normCnt > 0:
            SysMgr.printPipe(\
                "%s# %s: %d\n%s\n%s" % \
                    ('', 'Hot', normCnt, normThreadString, oneLine))
        else:
            SysMgr.printPipe("\tNone\n%s" % oneLine)

        # print new thread info #
        if newCnt > 0:
            SysMgr.printPipe(\
                "%s# %s: %d\n%s\n%s" % \
                    ('', 'New', newCnt, newThreadString, oneLine))

        # print die thread info #
        if dieCnt > 0:
            SysMgr.printPipe(\
                "%s# %s: %d\n%s\n%s" % \
                    ('', 'Die', dieCnt, dieThreadString, oneLine))

        # print thread preempted information after sorting by time of CPU usage #
        for val in SysMgr.preemptGroup:
            index = SysMgr.preemptGroup.index(val)
            count = long(0)

            tid = SysMgr.preemptGroup[index]
            try:
                self.threadData[tid]
            except:
                SysMgr.printErr('Fail to find "%s" thread' % tid)
                continue

            SysMgr.clearPrint()
            for key, value in sorted(\
                self.preemptData[index][1].items(), \
                key=lambda e: e[1]['usage'], reverse=True):

                count += 1
                if float(self.preemptData[index][4]) == 0:
                    break
                SysMgr.addPrint("%16s(%5s/%5s)|%s%s|%5.2f(%5s)\n"
                    % (self.threadData[key]['comm'], key, '0', \
                    self.threadData[key]['new'], \
                    self.threadData[key]['die'], value['usage'], \
                    '%.2f' % (value['usage'] / self.preemptData[index][4] * 100)))
            SysMgr.printPipe(\
                "%s# %s: Tid(%s) / Comm(%s) / Total(%6.3f) / Threads(%d)\n" % \
                ('', 'PRT', tid, self.threadData[tid]['comm'], \
                self.preemptData[index][4], count))
            SysMgr.doPrint()
            SysMgr.printPipe(oneLine)

        # prepare to draw graph #
        if not SysMgr.isRecordMode() and \
            SysMgr.graphEnable:
            # check interval value #
            if SysMgr.intervalEnable == 0:
                SysMgr.printErr(\
                    "use -i option if you want to draw graph")
                SysMgr.graphEnable = False
                return

            # get matplotlib object #
            matplotlib = SysMgr.getPkg('matplotlib', False)
            if not matplotlib:
                SysMgr.printPipWarn('matplotlib', 'matplotlib')
                sys.exit(0)
            from matplotlib.ticker import MaxNLocator

            SysMgr.matplotlibVersion = \
                float('.'.join(matplotlib.__version__.split('.')[:2]))

            # set dpi #
            matplotlib.rcParams['figure.dpi'] = SysMgr.matplotlibDpi

            # set backend #
            matplotlib.use('Agg')

            # get pylab object #
            SysMgr.importPkgItems('pylab')

            rc('legend', fontsize=5)
            rcParams.update({'font.size': 8})
        else:
            SysMgr.graphEnable = False



    def printModuleInfo(self):
        if len(self.moduleData) <= 0:
            return

        moduleTable = {}
        init_moduleData = \
            {'startTime': float(0), 'loadCnt': long(0),\
            'elapsed': float(0), 'freeCnt': long(0), 'refCnt': long(0),\
            'getCnt': long(0), 'putCnt': long(0)}

        # print module history #
        SysMgr.clearPrint()
        SysMgr.addPrint('\n[Thread Module History]\n')
        SysMgr.addPrint('%s\n' % twoLine)
        SysMgr.addPrint(\
            "{3:>16} ({4:^5})|{0:^6}|{1:^12}|{2:^32}|{5:^12}|{6:^8}|\n".\
                format("Type", "Time", "Module", "Comm", "Tid", \
                    "Elapsed", "RefCnt"))
        SysMgr.addPrint('%s\n' % twoLine)

        printCnt = long(0)
        for val in self.moduleData:
            event = val[0]
            tid = val[1]
            time = val[2]
            module = val[3]

            current = float(time) - float(SysMgr.startTime)

            try:
                comm = self.threadData[tid]['comm']
            except:
                continue

            moduleTable.setdefault(module, dict(init_moduleData))

            startTime = float(moduleTable[module]['startTime'])

            # module probe #
            if event == 'load':
                moduleTable[module]['startTime'] = time
                moduleTable[module]['loadCnt'] += 1

                moduleTable[module]['refCnt'] = 1
                refCnt = moduleTable[module]['refCnt']

                SysMgr.addPrint(\
                    "{3:>16} ({4:>5})|{0:^6}|{1:12.6f}|{2:^32}|{5:>12}|{6:^8}|\n".\
                    format('LOAD', current, module, comm, tid, '', refCnt))
                printCnt += 1

            # module remove #
            elif event == 'free':
                if startTime > 0:
                    lifetime = '%.6f' % (float(time) - startTime)
                else:
                    lifetime = ''

                moduleTable[module]['freeCnt'] += 1
                moduleTable[module]['refCnt'] = long(0)
                refCnt = moduleTable[module]['refCnt']

                SysMgr.addPrint(\
                    "{3:>16} ({4:>5})|{0:^6}|{1:12.6f}|{2:^32}|{5:>12}|{6:^8}|\n".\
                    format('FREE', current, module, comm, tid, lifetime, refCnt))
                printCnt += 1

            # module refcount increase #
            elif event == 'get':
                moduleTable[module]['getCnt'] += 1
                moduleTable[module]['refCnt'] = val[4]
                refCnt = moduleTable[module]['refCnt']

                SysMgr.addPrint(\
                    "{3:>16} ({4:>5})|{0:^6}|{1:12.6f}|{2:^32}|{5:>12}|{6:^8}|\n".\
                    format('GET', current, module, comm, tid, '', refCnt))
                printCnt += 1

            # module refcount decrease #
            elif event == 'put':
                moduleTable[module]['putCnt'] += 1
                moduleTable[module]['refCnt'] = val[4]
                refCnt = moduleTable[module]['refCnt']

                if startTime > 0:
                    elapsed = float(time) - startTime
                    moduleTable[module]['elapsed'] += elapsed
                    moduleTable[module]['startTime'] = long(0)
                    elapsed = '%.6f' % elapsed
                else:
                    elapsed = ''

                SysMgr.addPrint(\
                    "{3:>16} ({4:>5})|{0:^6}|{1:12.6f}|{2:^32}|{5:>12}|{6:^8}|\n".\
                    format('PUT', current, module, comm, tid, elapsed, refCnt))
                printCnt += 1

        if printCnt == 0:
            SysMgr.addPrint("\tNone\n%s\n" % oneLine)
        else:
            SysMgr.addPrint('%s\n' % oneLine)

        # print module info #
        SysMgr.printPipe('\n[Thread Module Info]')
        SysMgr.printPipe(twoLine)
        SysMgr.printPipe(\
            "{0:^32}|{1:^10}|{2:^12}|{3:^10}|{4:^10}|{5:^10}|".\
            format("Module", "LoadCnt", "LoadTime", \
            "FreeCnt", "GetCnt", "PutCnt"))
        SysMgr.printPipe(twoLine)

        printCnt = long(0)
        for module, value in moduleTable.items():
            elapsed = '%.6f' % value['elapsed']
            SysMgr.printPipe(\
                "{0:^32}|{1:^10}|{2:>12}|{3:^10}|{4:^10}|{5:^10}|".\
                format(module, value['loadCnt'], elapsed, \
                value['freeCnt'], value['getCnt'], value['putCnt']))
            printCnt += 1

        if printCnt == 0:
            SysMgr.printPipe("\tNone\n%s" % oneLine)
        else:
            SysMgr.printPipe('%s' % oneLine)

        SysMgr.doPrint()



    def printDepInfo(self):
        if not SysMgr.depEnable:
            return

        SysMgr.printPipe('\n[Thread Dependency Info]')
        SysMgr.printPipe(twoLine)
        SysMgr.printPipe(\
            "\t%5s/%4s \t%16s(%4s) -> %16s(%4s) \t%5s" % \
            ("Total", "Inter", "From", "Tid", "To", "Tid", "Event"))
        SysMgr.printPipe(twoLine)
        SysMgr.printPipe(\
            "%s# %s: %d\n" % ('', 'Dep', len(self.depData)))

        for icount in range(0, len(self.depData)):
            SysMgr.addPrint(self.depData[icount] + '\n')

        SysMgr.doPrint()
        SysMgr.printPipe(oneLine)



    def printFutexInfo(self):
        SysMgr.clearPrint()

        if len(self.futexData) == 0:
            return

        convertNum = UtilMgr.convNum

        outputCnt = long(0)
        SysMgr.printPipe(\
            '\n[Thread Futex Lock Info] [ Elapsed : %.3f ] (Unit: Sec/NR)' % \
                float(self.totalTime))
        SysMgr.printPipe(twoLine)
        SysMgr.printPipe((\
            '{0:>16}({1:>5}/{2:>5}) {3:>10} {4:>10} {5:>10} {6:>8} {7:>10} '
            '{8:>10} {9:>10} {10:>8} {11:>8} {12:>10} {13:>8} {14:>10}').\
            format('Name', 'Tid', 'Pid', 'Elapsed', 'Process', 'Block', \
            'NrBlock', 'CallMax', 'Lock', 'LockMax', 'NrLock', 'NrWait', \
            'LBlock', 'NrLBlock', 'LastStat'))
        SysMgr.printPipe(twoLine)

        totalInfo = {'ftxTotal': long(0), 'ftxMax': long(0), \
            'ftxLock': long(0), 'ftxLockMax': long(0), 'ftxLockCnt': long(0), \
            'ftxWaitCnt': long(0), 'ftxProcess': long(0), \
            'ftxBlockTotal': long(0), 'ftxLBlockTotal': long(0), \
            'ftxBlockCnt': long(0), 'ftxLSwitch': long(0)}

        # print futex info of threads #
        for key, value in sorted(self.threadData.items(), \
            key=lambda e: e[1]['ftxLockCnt'] + e[1]['ftxWaitCnt'], \
            reverse=True):
            if key[0:2] == '0[':
                continue
            elif value['ftxTotal'] == 0:
                break

            if value['ftxEnter'] == 0:
                status = 'Running'
            else:
                status = 'Wait'

            pid = value['tgid']

            # set thread info #
            ftxTotal = '%.3f' % float(value['ftxTotal'])
            ftxMax = '%.3f' % float(value['ftxMax'])
            ftxLock = '%.3f' % float(value['ftxLock'])
            ftxLockMax = '%.3f' % float(value['ftxLockMax'])
            ftxLockCall = convertNum(value['ftxLockCnt'])
            ftxWaitCall = convertNum(value['ftxWaitCnt'])

            # set total info #
            totalInfo['ftxTotal'] += value['ftxTotal']
            totalInfo['ftxLock'] += value['ftxLock']
            totalInfo['ftxLockCnt'] += value['ftxLockCnt']
            totalInfo['ftxWaitCnt'] += value['ftxWaitCnt']
            if totalInfo['ftxMax'] == 0 or \
                totalInfo['ftxMax'] < value['ftxMax']:
                totalInfo['ftxMax'] = value['ftxMax']
            if totalInfo['ftxLockMax'] == 0 or \
                totalInfo['ftxLockMax'] < value['ftxLockMax']:
                totalInfo['ftxLockMax'] = value['ftxLockMax']

            if SysMgr.cpuEnable:
                ftxProcess = '%.3f' % float(value['ftxProcess'])
                ftxBlock = '%.3f' % float(value['ftxBlockTotal'])
                ftxLBlock = '%.3f' % float(value['ftxLBlockTotal'])
                ftxBlockCall = convertNum(value['ftxBlockCnt'])
                ftxLSwitch = value['ftxLSwitch']

                totalInfo['ftxProcess'] += value['ftxProcess']
                totalInfo['ftxBlockTotal'] += value['ftxBlockTotal']
                totalInfo['ftxLBlockTotal'] += value['ftxLBlockTotal']
                totalInfo['ftxBlockCnt'] += value['ftxBlockCnt']
                totalInfo['ftxLSwitch'] += value['ftxLSwitch']
            else:
                ftxProcess = totalInfo['ftxProcess'] = '-'
                ftxBlock = totalInfo['ftxBlockTotal'] = '-'
                ftxLBlock = totalInfo['ftxLBlockTotal'] = '-'
                ftxBlockCall = totalInfo['ftxBlockCnt'] = '-'
                ftxLSwitch = totalInfo['ftxLSwitch'] = '-'

            futexInfo = \
                ('{0:>16}({1:>5}/{2:>5}) {3:>10} {4:>10} {5:>10} ' + \
                '{6:>8} {7:>10} {8:>10} {9:>10} {10:>8} ' + \
                '{11:>8} {12:>10} {13:>8} {14:>10}').\
                format(value['comm'], key, pid, ftxTotal, ftxProcess, ftxBlock, \
                ftxBlockCall, ftxMax, ftxLock, ftxLockMax, ftxLockCall, \
                ftxWaitCall, ftxLBlock, ftxLSwitch, status)

            SysMgr.addPrint('%s\n%s\n' % (futexInfo, oneLine))
            outputCnt += 1

        if outputCnt == 0:
            SysMgr.printPipe('\tNone\n%s' % oneLine)
        else:
            # print total info #
            totalInfo['ftxTotal'] = '%.3f' % totalInfo['ftxTotal']
            totalInfo['ftxMax'] = '%.3f' % totalInfo['ftxMax']
            totalInfo['ftxLock'] = '%.3f' % totalInfo['ftxLock']
            totalInfo['ftxLockMax'] = '%.3f' % totalInfo['ftxLockMax']
            totalInfo['ftxLockCnt'] = convertNum(totalInfo['ftxLockCnt'])
            totalInfo['ftxWaitCnt'] = convertNum(totalInfo['ftxWaitCnt'])

            if totalInfo['ftxProcess'] != '-':
                totalInfo['ftxProcess'] = '%.3f' % totalInfo['ftxProcess']
            if totalInfo['ftxBlockTotal'] != '-':
                totalInfo['ftxBlockTotal'] = '%.3f' % totalInfo['ftxBlockTotal']
            if totalInfo['ftxLBlockTotal'] != '-':
                totalInfo['ftxLBlockTotal'] = '%.3f' % totalInfo['ftxLBlockTotal']
            if totalInfo['ftxBlockCnt'] != '-':
                totalInfo['ftxBlockCnt'] = convertNum(totalInfo['ftxBlockCnt'])
            if totalInfo['ftxLSwitch'] != '-':
                totalInfo['ftxLSwitch'] = convertNum(totalInfo['ftxLSwitch'])

            totalFutexInfo = \
                ('{0:>29} {1:>10} {2:>10} {3:>10} ' \
                '{4:>8} {5:>10} {6:>10} {7:>10} {8:>8} ' \
                '{9:>8} {10:>10} {11:>8} {12:>10}').\
                format('[ TOTAL ]', \
                totalInfo['ftxTotal'], totalInfo['ftxProcess'], \
                totalInfo['ftxBlockTotal'], totalInfo['ftxBlockCnt'], \
                totalInfo['ftxMax'], totalInfo['ftxLock'], \
                totalInfo['ftxLockMax'], totalInfo['ftxLockCnt'], \
                totalInfo['ftxWaitCnt'], totalInfo['ftxLBlockTotal'], \
                totalInfo['ftxLSwitch'], '-')

            SysMgr.printPipe('%s\n%s' % (totalFutexInfo, oneLine))

            # print thread info #
            SysMgr.doPrint()
            SysMgr.clearPrint()

        if not SysMgr.showAll:
            return

        SysMgr.printPipe(\
            '\n[Thread Futex Lock History] (Unit: Sec/NR)')
        SysMgr.printPipe(twoLine)
        SysMgr.printPipe((\
            "{0:>12} {1:>16}{2:>13} {3:>4} {4:^24} " + \
            "{5:^10} {6:>12} {7:>16} {8:>16} {9:>16}").\
            format("Time", "Name", "(  Tid/  Pid)", "Core", "Operation",\
             "Type", "Elapsed", "Target", "Value", "Timer"))
        SysMgr.printPipe(twoLine)

        cnt = long(0)
        for icount in range(0, len(self.futexData)):
            try:
                value = self.futexData[icount]

                if value[1] == -1:
                    continue

                atime = float(value[1])
                time = '%.6f' % (atime - float(SysMgr.startTime))

                comm = self.threadData[value[0]]['comm']
                tid = '(%5s/%5s)' % \
                    (value[0], self.threadData[value[0]]['tgid'])
                core = value[2]

                try:
                    if icount == 0:
                        raise Exception()

                    if self.futexData[icount-1][2] == value[2]:
                        core = ''

                    if self.futexData[icount-1][0] == value[0]:
                        tid = comm = ''
                except:
                    pass

                if icount + 1 <= len(self.futexData) and \
                    self.futexData[icount+1][0] == value[0] and \
                    self.futexData[icount][4].startswith('ENT') and \
                    self.futexData[icount+1][4].endswith('RET'):
                    otype = '{0:^10}'.format('ALL')
                    elapsed = self.futexData[icount+1][5]
                    self.futexData[icount+1][1] = -1
                else:
                    otype = value[4]
                    elapsed = value[5]

                # convert error code #
                ret = long(value[7])
                if ret < 0:
                    try:
                        ret = '%s' % ConfigMgr.ERR_TYPE[abs(ret+1)]
                    except:
                        pass

                SysMgr.printPipe((\
                    "{0:>12} {1:>16}{2:>13} {3:>4} {4:<24} " + \
                    "{5:>10} {6:>12} {7:>16} {8:>16} {9:>16}").\
                    format(time, comm, tid, core, value[3],\
                    otype, elapsed, value[6], ret, value[8]))

                cnt += 1
            except:
                pass
        if cnt == 0:
            SysMgr.printPipe("\tNone")
        SysMgr.printPipe(oneLine)



    def printFlockInfo(self):
        SysMgr.clearPrint()

        if len(self.flockData) == 0:
            return

        outputCnt = long(0)
        SysMgr.printPipe('\n[Thread File Lock Info] (Unit: Sec/NR)')
        SysMgr.printPipe(twoLine)
        SysMgr.printPipe(\
            '{0:>16}({1:>5})\t{2:>12}\t{3:>12}\t{4:>10}\t{5:>10}'.format(\
            'Name', 'Tid', 'Wait', 'Lock', 'nrTryLock', 'nrLocked'))
        SysMgr.printPipe(twoLine)

        for key, value in sorted(\
            self.threadData.items(), \
            key=lambda e: e[1]['lockWait'], reverse=True):

            if key[0:2] == '0[':
                continue
            elif value['lockWait'] == value['lockTime'] == \
                value['tryLockCnt'] == value['lockCnt'] == 0:
                continue

            lockInfo = \
                '{0:>16}({1:>5})\t{2:>12}\t{3:>12}\t{4:>10}\t{5:>10}'.\
                format(value['comm'], key, '%.3f' % float(value['lockWait']),\
                '%.3f' % float(value['lockTime']),\
                value['tryLockCnt'], value['lockCnt'])
            SysMgr.printPipe('%s\n%s' % (lockInfo, oneLine))
            outputCnt += 1

        if outputCnt == 0:
            SysMgr.printPipe('\tNone\n%s' % oneLine)

        if not SysMgr.showAll:
            return

        SysMgr.printPipe(\
            '\n[Thread File Lock History] (Unit: Sec/NR)')
        SysMgr.printPipe(twoLine)
        SysMgr.printPipe(\
            "{0:>16}({1:>5}) {2:>10} {3:>4} {4:>10} {5:>16} {6:>16} {7:>20}"\
            .format("Name", "Tid", "Time", "Core",\
            "Type", "Device", "Inode", "Context"))
        SysMgr.printPipe(twoLine)

        cnt = long(0)
        for icount in range(0, len(self.flockData)):
            try:
                pos = self.flockData[icount][4].rfind('0x')
                dev = self.flockData[icount][4][:pos]
                inode = self.flockData[icount][4][pos:]
                atime = float(self.flockData[icount][1])
                time = '%.3f' % (atime - float(SysMgr.startTime))

                if icount > 0 and \
                    self.flockData[icount-1][0] == self.flockData[icount][0]:
                    tid = comm = ''
                else:
                    comm = self.threadData[self.flockData[icount][0]]['comm']
                    tid = '(%5s)' % self.flockData[icount][0]

                SysMgr.printPipe(\
                    "{0:>16}{1:>7} {2:>10} {3:>4} {4:>10} {5:>16} {6:>16} {7:>20}".\
                    format(comm, tid, time,\
                    self.flockData[icount][2], self.flockData[icount][3],\
                    dev, inode, self.flockData[icount][5]))
                cnt += 1
            except:
                continue
        if cnt == 0:
            SysMgr.printPipe("\tNone")
        SysMgr.printPipe(oneLine)



    def printSyscallInfo(self):
        if len(self.syscallData) == 0:
            return

        convertNum = UtilMgr.convNum

        outputCnt = long(0)
        SysMgr.printPipe(\
            '\n[Thread Syscall Info] [ Elapsed : %.3f ] (Unit: Sec/NR)' % \
                float(self.totalTime))
        SysMgr.printPipe(twoLine)
        SysMgr.printPipe((\
            '{0:>16}({1:>5}) {2:>30}({3:>3}) {4:>12} {5:>12} '
            '{6:>12} {7:>12} {8:>12} {9:>12}').format(\
            "Name", "Tid", "Syscall", "ID", "Elapsed", "Count",\
            "Error", "Min", "Max", "Avg"))
        SysMgr.printPipe(twoLine)

        totalInfo = dict()

        for key, value in sorted(\
            self.threadData.items(), key=lambda e: e[1]['nrSyscall'], \
            reverse=True):
            threadInfo = ''
            syscallInfo = ''

            # skip swapper #
            if key[0:2] == '0[':
                continue

            try:
                if len(value['syscallInfo']) > 0:
                    threadInfo = "%16s(%5s)" % (value['comm'], key)
                else:
                    continue
            except:
                continue

            for sysId, val in sorted(\
                value['syscallInfo'].items(), \
                key=lambda e: e[1]['usage'], reverse=True):

                if val['count'] == 0:
                    continue

                # apply syscall filter #
                if len(SysMgr.syscallList) > 0 and \
                    long(sysId) not in SysMgr.syscallList:
                    continue

                # print per-thread syscall table #
                try:
                    val['average'] = '%.6f' % (val['usage'] / val['count'])
                    syscall = ConfigMgr.sysList[int(sysId)][4:]
                    syscallInfo = \
                        ('{0:1} {1:>30}({2:>3}) {3:>12} '
                        '{4:>12} {5:>12} {6:>12} {7:>12} {8:>12}\n').format(\
                        '%s%s' % (syscallInfo, ' ' * len(threadInfo)), \
                        syscall, sysId, '%.6f' % val['usage'], \
                        convertNum(val['count']), convertNum(val['err']), \
                        '%.6f' % val['min'], '%.6f' % val['max'], \
                        val['average'])
                except:
                    pass

                # add total info #
                try:
                    if not sysId in totalInfo:
                        totalInfo[sysId] = dict()
                        totalInfo[sysId]['usage'] = long(0)
                        totalInfo[sysId]['count'] = long(0)
                        totalInfo[sysId]['err'] = long(0)
                        totalInfo[sysId]['min'] = long(0)
                        totalInfo[sysId]['max'] = long(0)
                        totalInfo[sysId]['average'] = long(0)

                    totalInfo[sysId]['usage'] += val['usage']
                    totalInfo[sysId]['count'] += val['count']
                    totalInfo[sysId]['err'] += val['err']

                    if totalInfo[sysId]['min'] == 0 or \
                        totalInfo[sysId]['min'] > val['min']:
                        totalInfo[sysId]['min'] = val['min']

                    if totalInfo[sysId]['max'] == 0 or \
                        totalInfo[sysId]['max'] < val['max']:
                        totalInfo[sysId]['max'] = val['max']

                    totalInfo[sysId]['average'] = \
                        totalInfo[sysId]['usage'] / totalInfo[sysId]['count']
                except:
                    pass

            if syscallInfo != '':
                outputCnt += 1
                SysMgr.addPrint('%s\n' % threadInfo)
                SysMgr.addPrint('%s\n%s\n' % (syscallInfo, oneLine))

        if outputCnt == 0:
            SysMgr.printPipe('\tNone\n%s' % oneLine)
        else:
            totalStrInfo = "{0:>23}".format('[ TOTAL ]')
            SysMgr.printPipe(totalStrInfo)

            # print total info #
            syscallInfo = ''
            for sysId, val in sorted(\
                totalInfo.items(), key=lambda e: e[1]['usage'], reverse=True):
                try:
                    syscall = ConfigMgr.sysList[int(sysId)][4:]
                except:
                    continue

                syscallInfo = \
                    ('{0:1} {1:>30}({2:>3}) {3:>12} '
                    '{4:>12} {5:>12} {6:>12} {7:>12} {8:>12}').format(\
                    ' ' * len(totalStrInfo), syscall, sysId, \
                    '%.6f' % val['usage'], convertNum(val['count']), \
                    convertNum(val['err']), '%.6f' % val['min'], \
                    '%.6f' % val['max'], '%.6f' % val['average'])

                SysMgr.printPipe(syscallInfo)
            SysMgr.printPipe('\n%s' % oneLine)

            # print thread info #
            SysMgr.doPrint()
            SysMgr.clearPrint()

        if not SysMgr.showAll:
            return

        SysMgr.printPipe('\n[Thread Syscall History] (Unit: Sec/NR)')
        SysMgr.printPipe(twoLine)
        SysMgr.printPipe((\
            "{0:>10} {1:>16}({2:>5}) {3:>4} {4:>18} {5:>3} "
            "{6:>5} {7:>10} {8:>16} {9:<1}").format(\
            "Time", "Name", "Tid", "Core", "Syscall", \
            "Sid", "Type", "Elapsed", "Return", "Arguments"))
        SysMgr.printPipe(twoLine)

        # remove calls of unavailable threads #
        for icount in range(0, len(self.syscallData)):
            try:
                self.threadData[self.syscallData[icount][2]]
            except:
                try:
                    del self.syscallData[icount]
                except:
                    break

        cnt = long(0)
        proto = ConfigMgr.SYSCALL_PROTOTYPES
        startTime = float(SysMgr.startTime)
        for icount in range(0, len(self.syscallData)):
            try:
                prevData = self.syscallData[icount-1]
                nowData = self.syscallData[icount]

                if nowData[1] == -1:
                    continue

                if len(self.syscallData) > icount + 1:
                    nextData = self.syscallData[icount+1]
                else:
                    nextData = None

                try:
                    syscall = ConfigMgr.sysList[int(nowData[4])]
                except SystemExit:
                    sys.exit(0)
                except:
                    SysMgr.printWarn(\
                        'Fail to recognize syscall %s for %s number' % \
                            (nowData[0], nowData[4]), True)
                    continue

                if nowData[0] == 'ENT':
                    # all #
                    if nextData and \
                        nextData[0] == 'RET' and \
                        nowData[2] == nextData[2] and \
                        nowData[4] == nextData[4]:
                        eventType = '{0:^5}'.format('ALL')
                        eventTime = float(nowData[1]) - startTime
                        elapsed = \
                            '%6.6f' % (float(nextData[1]) - float(nowData[1]))
                        param = nowData[5]
                        ret = nextData[5]
                        nextData[1] = -1
                    else:
                        eventType = '{0:<5}'.format(nowData[0])
                        eventTime = \
                            float(nowData[1]) - startTime
                        elapsed = ' ' * 8
                        param = nowData[5]
                        ret = ' '

                    # trim real arguments #
                    try:
                        call = syscall[4:]
                        nrArgs = len(proto[call][1])
                        if nrArgs > 0:
                            paramlist = param[1:-1].split(',')[:nrArgs]
                            # convert values #
                            for idx, args in enumerate(proto[call][1]):
                                val = paramlist[idx]

                                # check type #
                                if '*' in args[0]:
                                    paramlist[idx] = '0x%s' % val.strip()
                                    continue
                                if not 'int' in args[0] and \
                                    not 'short' in args[0] and \
                                    not 'long' in args[0]:
                                    paramlist[idx] = '0x%s' % val.strip()
                                    continue

                                # type casting #
                                if 'unsigned' in args[0]:
                                    paramlist[idx] = str(long(val, 16))
                                    continue

                                val = long(val, 16)
                                if 'short' in args[0]:
                                    paramlist[idx] = \
                                        -(val & 0x8000) | (val & 0x7fff)
                                elif 'int' in args[0]:
                                    paramlist[idx] = \
                                        -(val & 0x80000000) | (val & 0x7fffffff)

                            param = '(%s)' % ', '.join(list(map(str, paramlist)))
                        else:
                            param = ' '
                    except SystemExit:
                        sys.exit(0)
                    except:
                        SysMgr.printWarn(\
                            "Fail to analyze syscall info", True, reason=True)

                elif nowData[0] == 'RET':
                    eventType = nowData[0]
                    eventTime = float(nowData[1]) - startTime
                    param = ' '
                    ret = nowData[5]

                    try:
                        elapsed = '%6.6f' % nowData[6]
                    except:
                        elapsed = ' ' * 8

                try:
                    # convert error code #
                    nrRet = long(ret)
                    if nrRet < 0:
                        ret = ConfigMgr.ERR_TYPE[abs(nrRet) - 1]
                except:
                    pass

                if icount > 0 and prevData[2] == nowData[2]:
                    tid = comm = ''
                else:
                    comm = self.threadData[nowData[2]]['comm']
                    tid = '(%5s)' % nowData[2]

                if icount > 0 and prevData[3] == nowData[3]:
                    core = ''
                else:
                    core = nowData[3]

                SysMgr.printPipe(\
                    ("{0:>10} {1:>16}{2:>7} {3:>4} {4:>18} {5:>3} "
                    "{6:>5} {7:>10} {8:>16} {9:<1}").\
                    format('%.6f' % eventTime, comm, tid,\
                    core, syscall[4:], nowData[4],\
                    eventType, elapsed, ret, param))

                cnt += 1
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printErr(\
                    "Fail to analyze syscall info", True)

        if cnt == 0:
            SysMgr.printPipe("\tNone")
        SysMgr.printPipe(oneLine)



    def printConsoleInfo(self):
        if len(self.consoleData) == 0 or not SysMgr.showAll:
            return

        SysMgr.printPipe('\n[Thread Message Info]')
        SysMgr.printPipe(twoLine)
        SysMgr.printPipe(\
            "%16s %5s %4s %10s %30s" % \
            ('Name', 'Tid', 'Core', 'Time', 'Console message'))
        SysMgr.printPipe(twoLine)

        startTime = float(SysMgr.startTime)

        cnt = long(0)
        for msg in self.consoleData:
            try:
                SysMgr.printPipe("%16s %5s %4s %10.3f %s" % \
                    (self.threadData[msg[0]]['comm'], msg[0], msg[1], \
                    round(float(msg[2]) - startTime, 7), msg[3]))
                cnt += 1
            except:
                continue

        if cnt == 0:
            SysMgr.printPipe("\tNone")
        SysMgr.printPipe(twoLine)



    def printBlockInfo(self):
        def printBlkUsage(cid, data, opt, tcnt):
            for num, val in sorted(\
                data.items(), key=lambda e:e[1], reverse=True):
                if tcnt == 0:
                    pass
                else:
                    cid = ' '

                try:
                    mountInfo = SysMgr.savedMountTree
                    dev = mountInfo[num]['dev']
                    filesystem = mountInfo[num]['filesystem']
                    mount = mountInfo[num]['mount']
                except:
                    dev = '?'
                    filesystem = '?'
                    mount = '?'

                try:
                    seqPer = round((val[3] / float(val[0])) * 100, 1)
                except:
                    seqPer = '?'

                try:
                    size = format((val[0] >> 10), ',')
                except:
                    size = val[0] >> 10

                try:
                    seqSize = format((val[3] >> 10), ',')
                except:
                    seqSize = '?'

                seqString = '%s(%5s)' % (seqSize, seqPer)

                if tcnt > 0:
                    SysMgr.printPipe()

                SysMgr.printPipe(\
                    "{0:>23} {1:>5} {2:>8} {3:>20} {4:>23} {5:^12} {6:<20}".\
                    format(cid, opt, num, size, seqString, filesystem, dev))

                opt = ''

                # print per-operation size statistics #
                for optSize, cnt in sorted(val[5].items()):
                    start = UtilMgr.convSize2Unit(optSize)
                    end = UtilMgr.convSize2Unit(optSize << 1)
                    SysMgr.printPipe(\
                        "{0:^23} {0:^8} {0:^5} {1:>20} {2:>23} {0:^12} {0:<20}".\
                        format('', '[%7s - %7s]' % (start, end), cnt))

                tcnt += 1

            return tcnt


        # check block option #
        if not SysMgr.blockEnable:
            return

        SysMgr.printPipe('\n[Thread Block Info] (Unit: KB/NR)')
        SysMgr.printPipe(twoLine)
        SysMgr.printPipe(\
            "{0:^23} {1:>5} {2:>8} {3:>20} {4:>23} {5:^12} {6:^20}".\
            format('ID', 'OPT', 'NrDev', 'TOTAL', \
            'SEQUENTIAL(    %)', 'FS', 'PATH'))
        SysMgr.printPipe(\
            "{0:^23} {1:>5} {2:>8} {3:>20} {4:>23} {5:^12} {6:^20}".\
            format('', '', '', '[ACCESS]', 'COUNT', '', ''))
        SysMgr.printPipe(twoLine)

        tcnt = long(0)
        totalStr = '{0:^23}'.format('TOTAL')

        # total read #
        if len(self.blockTable[0]) > 0:
            tcnt = printBlkUsage(totalStr, self.blockTable[0], 'READ', tcnt)

        # total write #
        if len(self.blockTable[1]) > 0:
            tcnt = printBlkUsage(totalStr, self.blockTable[1], 'WRITE', tcnt)

        if tcnt > 0:
            SysMgr.printPipe(oneLine)
        else:
            SysMgr.printPipe("\tNone")
            SysMgr.printPipe(oneLine)

        # sort threads by read size #
        for tid, data in sorted(\
            self.blockTable[2].items(), \
            key=lambda e:sorted(e[1][0]), reverse=True):
            tcnt = long(0)
            comm = self.threadData[tid]['comm']
            cid = '%s(%s)' % (comm, tid)

            # thread read #
            if len(data[0]) > 0:
                tcnt = printBlkUsage(cid, data[0], 'READ', tcnt)

            # thread write #
            if len(data[1]) > 0:
                tcnt = printBlkUsage(cid, data[1], 'WRITE', tcnt)

            if tcnt > 0:
                SysMgr.printPipe(oneLine)



    def printEventIntervalInfo(self):
        # timeline #
        timeLine = ''
        titleLine = "%16s(%5s/%5s):" % ('Name', 'Tid', 'Pid')
        maxLineLen = SysMgr.lineLength
        timeLineLen = titleLineLen = len(titleLine)
        intervalEnable = SysMgr.intervalEnable

        # custom event usage on timeline #
        SysMgr.clearPrint()
        if len(SysMgr.customEventList) > 0:
            for idx, val in sorted(\
                self.customEventInfo.items(), \
                key=lambda e: e[1]['count'], reverse=True):

                for key, value in sorted(self.customInfo.items(), \
                    key=lambda e: 0 if not idx in e[1] else e[1][idx]['count'], \
                    reverse=True):
                    timeLine = ''
                    timeLineLen = titleLineLen
                    lval = long(float(self.totalTime) / intervalEnable) + 1
                    for icount in range(0, lval):
                        newFlag = ' '
                        dieFlag = ' '

                        if timeLineLen + 4 > maxLineLen:
                            timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                            timeLineLen = titleLineLen + 4
                        else:
                            timeLineLen += 4

                        try:
                            self.intData[icount][key]['customEvent']
                        except:
                            timeLine += '%3d ' % 0
                            continue

                        nowVal = self.intData[icount][key]

                        try:
                            prevVal = self.intData[icount - 1][key]
                        except:
                            prevVal = nowVal

                        if icount > 0:
                            try:
                                if nowVal['new'] != prevVal['new']:
                                    newFlag = nowVal['new']
                            except:
                                newFlag = nowVal['new']
                            try:
                                if nowVal['die'] != prevVal['die']:
                                    dieFlag = nowVal['die']
                            except:
                                dieFlag = nowVal['die']
                        else:
                            newFlag = nowVal['new']
                            dieFlag = nowVal['die']

                        cnt = str(nowVal['customEvent'][idx]['count'])

                        timeLine += '%4s' % (newFlag + cnt + dieFlag)

                    if (idx not in value or value[idx]['count'] == 0) and \
                        not SysMgr.showAll:
                        break

                    SysMgr.addPrint("%16s(%5s/%5s): " % \
                        (self.threadData[key]['comm'], key, \
                        self.threadData[key]['tgid']) + timeLine + '\n')

                SysMgr.printPipe("%s# %s\n" % ('', '%s(Cnt)' % idx))
                SysMgr.doPrint()
                SysMgr.printPipe(oneLine)
                SysMgr.clearPrint()

        # user event usage on timeline #
        SysMgr.clearPrint()
        if len(SysMgr.userEventList) > 0:
            for idx, val in sorted(\
                self.userEventInfo.items(), \
                key=lambda e: e[1]['count'], reverse=True):

                for key, value in sorted(self.userInfo.items(), \
                    key=lambda e: 0 if not idx in e[1] else e[1][idx]['usage'], \
                    reverse=True):
                    timeLine = ''
                    timeLineLen = titleLineLen
                    lval = long(float(self.totalTime) / intervalEnable) + 1
                    for icount in range(0, lval):
                        newFlag = ' '
                        dieFlag = ' '

                        if timeLineLen + 4 > maxLineLen:
                            timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                            timeLineLen = titleLineLen + 4
                        else:
                            timeLineLen += 4

                        try:
                            self.intData[icount][key]['userEvent']
                        except:
                            timeLine += '%3d ' % 0
                            continue

                        nowVal = self.intData[icount][key]

                        try:
                            prevVal = self.intData[icount - 1][key]
                        except:
                            prevVal = nowVal

                        if icount > 0:
                            try:
                                if nowVal['new'] != prevVal['new']:
                                    newFlag = nowVal['new']
                            except:
                                newFlag = nowVal['new']
                            try:
                                if nowVal['die'] != prevVal['die']:
                                    dieFlag = nowVal['die']
                            except:
                                dieFlag = nowVal['die']
                        else:
                            newFlag = nowVal['new']
                            dieFlag = nowVal['die']

                        res = str(nowVal['userEvent'][idx]['count'])

                        '''
                        res = str(nowVal['userEvent'][idx]['usage']) / \
                            SysMgr.intervalEnable * 100
                        '''

                        timeLine += '%4s' % (newFlag + res + dieFlag)

                    if (idx not in value or value[idx]['count'] == 0) and \
                        not SysMgr.showAll:
                        break

                    SysMgr.addPrint("%16s(%5s/%5s): " % \
                        (self.threadData[key]['comm'], key, \
                        self.threadData[key]['tgid']) + timeLine + '\n')

                SysMgr.printPipe("%s# %s\n" % ('', '%s(Cnt)' % idx))
                SysMgr.doPrint()
                SysMgr.printPipe(oneLine)
                SysMgr.clearPrint()

        # kernel event usage on timeline #
        SysMgr.clearPrint()
        if len(SysMgr.kernelEventList) > 0:
            for idx, val in sorted(\
                self.kernelEventInfo.items(), \
                key=lambda e: e[1]['count'], reverse=True):

                for key, value in sorted(\
                    self.kernelInfo.items(), \
                    key=lambda e: 0 if not idx in e[1] else e[1][idx]['usage'], \
                    reverse=True):
                    timeLine = ''
                    timeLineLen = titleLineLen
                    lval = long(float(self.totalTime) / intervalEnable) + 1
                    for icount in range(0, lval):
                        newFlag = ' '
                        dieFlag = ' '

                        if timeLineLen + 4 > maxLineLen:
                            timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                            timeLineLen = titleLineLen + 4
                        else:
                            timeLineLen += 4

                        try:
                            self.intData[icount][key]['kernelEvent']
                        except:
                            timeLine += '%3d ' % 0
                            continue

                        nowVal = self.intData[icount][key]

                        try:
                            prevVal = self.intData[icount - 1][key]
                        except:
                            prevVal = nowVal

                        if icount > 0:
                            try:
                                if nowVal['new'] != prevVal['new']:
                                    newFlag = nowVal['new']
                            except:
                                newFlag = nowVal['new']
                            try:
                                if nowVal['die'] != prevVal['die']:
                                    dieFlag = nowVal['die']
                            except:
                                dieFlag = nowVal['die']
                        else:
                            newFlag = nowVal['new']
                            dieFlag = nowVal['die']

                        res = str(nowVal['kernelEvent'][idx]['count'])

                        '''
                        res = str(nowVal['kernelEvent'][idx]['usage']) / \
                            SysMgr.intervalEnable * 100
                        '''

                        timeLine += '%4s' % (newFlag + res + dieFlag)

                    if (idx not in value or value[idx]['count'] == 0) and \
                        not SysMgr.showAll:
                        break

                    SysMgr.addPrint("%16s(%5s/%5s): " % \
                        (self.threadData[key]['comm'], key, \
                        self.threadData[key]['tgid']) + timeLine + '\n')

                SysMgr.printPipe("%s# %s\n" % ('', '%s(Cnt)' % idx))
                SysMgr.doPrint()
                SysMgr.printPipe(oneLine)
                SysMgr.clearPrint()


    def printIntervalInfo(self):
        # pylint: disable=undefined-variable

        if SysMgr.intervalEnable <= 0 or \
            not (SysMgr.cpuEnable or \
            SysMgr.memEnable or \
            SysMgr.blockEnable):
            return

        intervalEnable = SysMgr.intervalEnable

        SysMgr.printPipe(\
            '\n[Thread Interval Info] (Unit: %s Sec)' % intervalEnable)
        SysMgr.printPipe(twoLine)

        # graph list #
        cpuUsageList = []
        cpuThrLabelList = []
        cpuThrUsageList = []
        ioLabelList = []
        ioUsageList = []

        # timeline #
        timeLine = ''
        titleLine = "%16s(%5s/%5s):" % ('Name', 'Tid', 'Pid')
        maxLineLen = SysMgr.lineLength
        timeLineLen = titleLineLen = len(titleLine)
        startTime = float(SysMgr.startTime)
        lval = long(float(self.totalTime) / intervalEnable) + 2
        for icount in range(1, lval):
            checkEvent = ' '
            cnt = icount - 1

            # check suspend event #
            for val in self.suspendData:
                if startTime + cnt * intervalEnable < float(val[0]) < \
                    startTime + ((cnt + 1) * intervalEnable):
                    if val[1] == 'S':
                        checkEvent = '!'
                    elif val[1] == 'F':
                        checkEvent = '^'
                    else:
                        checkEvent = '>'

            # check mark event #
            for val in self.markData:
                if startTime + cnt * intervalEnable < float(val) < \
                    startTime + ((cnt + 1) * intervalEnable):
                    checkEvent = 'v'

            if timeLineLen + 4 > maxLineLen:
                timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                timeLineLen = titleLineLen + 4
            else:
                timeLineLen += 4

            # print timeline #
            if icount * intervalEnable <= float(self.totalTime):
                timeLine += '%s%2d ' % \
                    (checkEvent, icount * intervalEnable)
            else:
                timeLine += '%s%.2f ' % (checkEvent, self.totalTime)

        SysMgr.printPipe("%s %s" % (titleLine, timeLine))
        SysMgr.printPipe(twoLine)
        SysMgr.clearPrint()

        # total CPU usage on timeline #
        for key, value in sorted(self.threadData.items(), \
            key=lambda e: ThreadAnalyzer.getCoreId(e[1]['comm']), reverse=False):
            if not SysMgr.cpuEnable:
                break

            if key[0:2] != '0[':
                continue

            timeLine = ''
            timeLineLen = titleLineLen
            lval = long(float(self.totalTime) / intervalEnable) + 1
            for icount in range(0, lval):
                try:
                    # revise core usage in DVFS system #
                    if self.threadData[key]['coreSchedCnt'] == 0 and \
                        self.threadData[key]['offCnt'] > 0:
                        raise Exception()
                    else:
                        per = (100 - self.intData[icount][key]['cpuPer'])
                        timeLine += '%3d ' % per
                except:
                    timeLine += '%3s ' % '0'

                if timeLineLen + 4 >= maxLineLen:
                    timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                    timeLineLen = titleLineLen + 4
                else:
                    timeLineLen += 4

            SysMgr.addPrint("%16s(%5s/%5s): " % \
                (value['comm'], '0', value['tgid']) + timeLine + '\n')

            # make CPU usage list for graph #
            if SysMgr.graphEnable and SysMgr.cpuEnable:
                timeLine = timeLine.replace('N', '')
                timeLine = timeLine.replace('D', '')
                timeLine = timeLine.replace('F', '')
                timeLineData = [int(n) for n in timeLine.split()]
                cpuUsageList.append(timeLineData)

        # total memory usage on timeline #
        timeLine = ''
        timeLineLen = titleLineLen
        lval = long(float(self.totalTime) / intervalEnable) + 1
        for icount in range(0, lval):
            if timeLineLen + 4 > maxLineLen:
                timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                timeLineLen = titleLineLen + 4
            else:
                timeLineLen += 4

            try:
                timeLine += '%3d ' % \
                    ((self.intData[icount]['toTal']['totalMem'] >> 8) + \
                    (self.intData[icount]['toTal']['totalKmem'] >> 20))
            except:
                timeLine += '%3d ' % (0)

        if SysMgr.memEnable:
            SysMgr.addPrint(\
                "\n%16s(%5s/%5s): " % ('MEM', '0', '-----') + timeLine + '\n')
            if SysMgr.graphEnable:
                timeLineData = [int(n) for n in timeLine.split()]
                ioUsageList.append(timeLineData)
                ioLabelList.append('RAM Usage')

        # total block usage on timeline #
        if SysMgr.blockEnable:
            # total block read usage on timeline #
            brtotal = long(0)
            timeLine = ''
            timeLineLen = titleLineLen
            lval = long(float(self.totalTime) / intervalEnable) + 1
            for icount in range(0, lval):
                if timeLineLen + 4 > maxLineLen:
                    timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                    timeLineLen = titleLineLen + 4
                else:
                    timeLineLen += 4

                try:
                    timeLine += '%3d ' % \
                        ((self.intData[icount]['toTal']['totalBr'] * \
                        SysMgr.blockSize) >> 20)
                    brtotal += self.intData[icount]['toTal']['totalBr']
                except:
                    timeLine += '%3d ' % (0)

            if brtotal > 0:
                SysMgr.addPrint(\
                    "\n%16s(%5s/%5s): " % ('BLK_RD', '0', '-----') + \
                    timeLine + '\n')
                if SysMgr.graphEnable:
                    timeLineData = [int(n) for n in timeLine.split()]
                    ioUsageList.append(timeLineData)
                    ioLabelList.append('Block Read')

            # total block write usage on timeline #
            bwtotal = long(0)
            timeLine = ''
            timeLineLen = titleLineLen
            lval = long(float(self.totalTime) / intervalEnable) + 1
            for icount in range(0, lval):
                if timeLineLen + 4 > maxLineLen:
                    timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                    timeLineLen = titleLineLen + 4
                else:
                    timeLineLen += 4

                try:
                    timeLine += '%3d ' % \
                        ((self.intData[icount]['toTal']['totalBw'] * \
                        SysMgr.blockSize) >> 20)
                    bwtotal += self.intData[icount]['toTal']['totalBw']
                except:
                    timeLine += '%3d ' % (0)

            if bwtotal > 0:
                if brtotal == 0:
                    SysMgr.addPrint('\n')
                SysMgr.addPrint(\
                    "%16s(%5s/%5s): " % ('BLK_WR', '0', '-----') + \
                    timeLine + '\n')
                if SysMgr.graphEnable:
                    timeLineData = [int(n) for n in timeLine.split()]
                    ioUsageList.append(timeLineData)
                    ioLabelList.append('Block Write')

        # total custom event usage on timeline #
        newLine = True
        for evt, value in sorted(\
            self.customEventInfo.items(), key=lambda e: e[1]['count'], \
            reverse=True):

            timeLine = ''
            timeLineLen = titleLineLen
            lval = long(float(self.totalTime) / intervalEnable) + 1
            for icount in range(0, lval):
                if timeLineLen + 4 > maxLineLen:
                    timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                    timeLineLen = titleLineLen + 4
                else:
                    timeLineLen += 4

                try:
                    timeLine += '%3d ' % \
                        self.intData[icount]['toTal']['customEvent'][evt]['count']
                except:
                    timeLine += '%3d ' % (0)

            if newLine:
                SysMgr.addPrint("\n")
                newLine = False

            SysMgr.addPrint(\
                "%16s(%5s/%5s): " % (evt[:16], '0', '-----') + timeLine + '\n')

        # total user event usage on timeline #
        newLine = True
        for evt, value in sorted(\
            self.userEventInfo.items(), key=lambda e: e[1]['count'], \
            reverse=True):

            timeLine = ''
            timeLineLen = titleLineLen
            lval = long(float(self.totalTime) / intervalEnable) + 1
            for icount in range(0, lval):
                if timeLineLen + 4 > maxLineLen:
                    timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                    timeLineLen = titleLineLen + 4
                else:
                    timeLineLen += 4

                try:
                    timeLine += '%3d ' % \
                        self.intData[icount]['toTal']['userEvent'][evt]['count']

                    '''
                    timeLine += '%3d ' % \
                        (self.intData[icount]['toTal']['userEvent'][evt]['usage'] / \
                        intervalEnable * 100)
                    '''
                except:
                    timeLine += '%3d ' % (0)

            if newLine:
                SysMgr.addPrint("\n")
                newLine = False

            SysMgr.addPrint(\
                "%16s(%5s/%5s): " % (evt[:16], '0', '-----') + timeLine + '\n')

        # total kernel event usage on timeline #
        newLine = True
        for evt, value in sorted(\
            self.kernelEventInfo.items(), key=lambda e: e[1]['count'], \
            reverse=True):

            timeLine = ''
            timeLineLen = titleLineLen
            lval = long(float(self.totalTime) / intervalEnable) + 1
            for icount in range(0, lval):
                if timeLineLen + 4 > maxLineLen:
                    timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                    timeLineLen = titleLineLen + 4
                else:
                    timeLineLen += 4

                try:
                    evtVal = self.intData[icount]['toTal']['kernelEvent'][evt]
                    timeLine += '%3d ' % evtVal['count']

                    '''
                    timeLine += '%3d ' % \
                        (evtVal['usage'] / intervalEnable * 100)
                    '''
                except:
                    timeLine += '%3d ' % (0)

            if newLine:
                SysMgr.addPrint("\n")
                newLine = False

            SysMgr.addPrint(\
                "%16s(%5s/%5s): " % (evt[:16], '0', '-----') + timeLine + '\n')

        # print buffered info #
        SysMgr.printPipe("%s# %s\n" % ('', 'Total(%/MB/Cnt)'))
        SysMgr.doPrint()
        SysMgr.printPipe(oneLine)
        SysMgr.clearPrint()

        if SysMgr.graphEnable:
            # get matplotlib object #
            matplotlib = SysMgr.getPkg('matplotlib', False)
            if not matplotlib:
                SysMgr.printPipWarn('matplotlib', 'matplotlib')
                sys.exit(0)
            from matplotlib.ticker import MaxNLocator

            SysMgr.matplotlibVersion = \
                float('.'.join(matplotlib.__version__.split('.')[:2]))

            # set backend #
            matplotlib.pyplot.switch_backend('agg')

            # get pylab object #
            SysMgr.importPkgItems('pylab')

        # draw io graph #
        if SysMgr.graphEnable and len(ioUsageList) > 0:
            timelen = len(ioUsageList[0])
            ax = subplot2grid((6,1), (5,0), rowspan=1, colspan=1)
            ax.xaxis.set_major_locator(MaxNLocator(integer=True))
            ax.yaxis.set_major_locator(MaxNLocator(integer=True))

            for idx, item in enumerate(ioUsageList):
                minIdx = item.index(min(item))
                maxIdx = item.index(max(item))
                nrColor = long(idx) % 3
                if nrColor == 0:
                    color = 'blue'
                elif nrColor == 1:
                    color = 'red'
                else:
                    color = 'green'

                plot(range(intervalEnable,\
                        (timelen+1)*intervalEnable, intervalEnable),\
                    item, '-', c=color)

                ytick = yticks()[0]
                if len(ytick) > 1:
                    margin = (ytick[1] - ytick[0]) / 2
                else:
                    margin = long(0)

                if minIdx > 0:
                    minUsage = str(item[minIdx])
                    text(minIdx + 1, item[minIdx] - margin, minUsage, fontsize=4,\
                        color=color, fontweight='bold')
                if maxIdx > 0:
                    maxUsage = str(item[maxIdx])
                    text(maxIdx + 1, item[maxIdx] - margin, maxUsage, fontsize=4,\
                        color=color, fontweight='bold')

            if SysMgr.matplotlibVersion >= 1.2:
                legend(ioLabelList, bbox_to_anchor=(1.1, 1), \
                    fontsize=3.5, loc='upper right')
            else:
                legend(ioLabelList, bbox_to_anchor=(1.1, 1), loc='upper right')

            # add % unit to each value #
            try:
                ytickLabel = ax.get_yticks().tolist()
                ytickLabel = list(map(long, ytickLabel))

                # convert label units #
                convertNum = UtilMgr.convSize2Unit
                ytickLabel = \
                    [convertNum(val << 20, True) for val in ytickLabel]

                ax.set_yticklabels(ytickLabel)
            except:
                pass

            grid(which='both', linestyle=':', linewidth=0.2)
            yticks(fontsize=5)
            xticks(fontsize=4)
            #ticklabel_format(useOffset=False)
            locator_params(axis='x', nbins=30)
            figure(num=1, figsize=(10, 10), facecolor='b', edgecolor='k').\
                subplots_adjust(left=0.06, top=0.95, bottom=0.05)

        # CPU usage on timeline #
        for key, value in sorted(\
            self.threadData.items(), \
            key=lambda e: e[1]['usage'], reverse=True):

            if key[0:2] == '0[':
                continue

            timeLine = ''
            timeLineLen = titleLineLen
            lval = \
                long(float(self.totalTime) / intervalEnable) + 1
            for icount in range(0, lval):
                newFlag = ' '
                dieFlag = ' '

                if timeLineLen + 4 > maxLineLen:
                    timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                    timeLineLen = titleLineLen + 4
                else:
                    timeLineLen += 4

                try:
                    self.intData[icount][key]
                except:
                    timeLine += '%3d ' % 0
                    continue

                nowVal = self.intData[icount][key]

                try:
                    prevVal = self.intData[icount - 1][key]
                except:
                    prevVal = nowVal

                if icount > 0:
                    try:
                        if nowVal['new'] != prevVal['new']:
                            newFlag = nowVal['new']
                    except:
                        newFlag = nowVal['new']
                    try:
                        if nowVal['die'] != prevVal['die']:
                            dieFlag = nowVal['die']
                    except:
                        dieFlag = nowVal['die']
                else:
                    newFlag = self.intData[icount][key]['new']
                    dieFlag = self.intData[icount][key]['die']

                # Do not use 100% because of output format #
                cpuPer = str(long(self.intData[icount][key]['cpuPer']))
                if cpuPer == '100':
                    cpuPer = '99'

                timeLine += '%4s' % (newFlag + cpuPer + dieFlag)

            SysMgr.addPrint("%16s(%5s/%5s): " % \
                (value['comm'], key, value['tgid']) + timeLine + '\n')

            if SysMgr.graphEnable and SysMgr.cpuEnable:
                timeLine = timeLine.replace('N', '')
                timeLine = timeLine.replace('D', '')
                timeLine = timeLine.replace('F', '')
                cpuThrUsageList.append([int(n) for n in timeLine.split()])
                tinfo = '%s(%s)' % (value['comm'], key)
                cpuThrLabelList.append(tinfo)

            if not SysMgr.showAll and \
                value['usage'] / float(self.totalTime) * 100 < 1:
                break

        # draw CPU graph #
        if SysMgr.graphEnable and len(cpuUsageList) > 0:
            timelen = len(cpuUsageList[0])
            ax = subplot2grid((6,1), (0,0), rowspan=5, colspan=1)
            ax.xaxis.set_major_locator(MaxNLocator(integer=True))
            ax.yaxis.set_major_locator(MaxNLocator(integer=True))

            # CPU total usage #
            totalCpuUsage = None
            for item in cpuUsageList:
                if totalCpuUsage is None:
                    totalCpuUsage = item
                    continue

                totalCpuUsage = list(map(long.__add__, totalCpuUsage, item))

            avgCpuUsage = [x / len(cpuUsageList) for x in totalCpuUsage]
            plot(range(intervalEnable,\
                    (timelen+1)*intervalEnable, intervalEnable),\
                avgCpuUsage, '.-', linewidth=3, solid_capstyle='round')

            # CPU usage of threads #
            for idx, item in enumerate(cpuThrUsageList):
                maxIdx = item.index(max(item))

                color = plot(range(intervalEnable,\
                    (timelen+1)*intervalEnable,\
                    intervalEnable), item, '-')[0].get_color()

                ytick = yticks()[0]
                if len(ytick) > 1:
                    margin = (ytick[1] - ytick[0]) / (len(ytick) * 2)
                else:
                    margin = long(0)

                maxCpuPer = str(item[maxIdx])
                label = '%s[max: %s%%]' % \
                    (cpuThrLabelList[idx], maxCpuPer)
                text(maxIdx + 1, item[maxIdx] + margin, label,\
                    fontsize=3, color=color, fontweight='bold')

            # draw CPU graph #
            totalLabel = [' CPU Average '] + cpuThrLabelList
            if SysMgr.matplotlibVersion >= 1.2:
                legend(totalLabel, bbox_to_anchor=(1.12, 1),\
                    fontsize=3.5, loc='upper right')
            else:
                legend(totalLabel, \
                bbox_to_anchor=(1.12, 1), loc='upper right')

            # add % unit to each value #
            try:
                ytickLabel = ax.get_yticks().tolist()
                ytickLabel = list(map(long, ytickLabel))

                # convert label units #
                ytickLabel = \
                    ['%s%%' % val for val in ytickLabel]

                ax.set_yticklabels(ytickLabel)
            except:
                pass

            suptitle('Guider Graph', fontsize=8)

            grid(which='both', linestyle=':', linewidth=0.2)
            yticks(fontsize=5)
            xticks(fontsize=4)
            #ticklabel_format(useOffset=False)
            locator_params(axis='x', nbins=30)
            figure(num=1, figsize=(10, 10), facecolor='b', edgecolor='k').\
                subplots_adjust(left=0.06, top=0.95, bottom=0.05)

        if SysMgr.cpuEnable:
            SysMgr.printPipe("%s# %s\n" % ('', 'CPU(%)'))
            SysMgr.doPrint()
            SysMgr.printPipe(oneLine)

        # preempted units on timeline #
        SysMgr.clearPrint()
        for key, value in sorted(\
            self.threadData.items(), \
            key=lambda e: e[1]['cpuWait'], reverse=True):

            if value['cpuWait'] / float(self.totalTime) * 100 < 1 and \
                not SysMgr.showAll:
                break
            elif key[0:2] == '0[':
                continue

            timeLine = ''
            timeLineLen = titleLineLen
            lval = long(float(self.totalTime) / intervalEnable) + 1
            for icount in range(0, lval):
                newFlag = ' '
                dieFlag = ' '

                if timeLineLen + 4 > maxLineLen:
                    timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                    timeLineLen = titleLineLen + 4
                else:
                    timeLineLen += 4

                try:
                    self.intData[icount][key]
                except:
                    timeLine += '%3d ' % 0
                    continue

                nowVal = self.intData[icount][key]

                try:
                    prevVal = self.intData[icount - 1][key]
                except:
                    prevVal = nowVal

                if icount > 0:
                    try:
                        if nowVal['new'] != prevVal['new']:
                            newFlag = self.intData[icount][key]['new']
                    except:
                        newFlag = nowVal['new']
                    try:
                        if nowVal['die'] != prevVal['die']:
                            dieFlag = nowVal['die']
                    except:
                        dieFlag = nowVal['die']
                else:
                    newFlag = nowVal['new']
                    dieFlag = nowVal['die']

                # Do not use 100% because of output format #
                totalPrt = nowVal['preempted'] / float(intervalEnable)
                prtPer = str(long(totalPrt * 100))
                if prtPer == '100':
                    prtPer = '99'

                timeLine += '%4s' % (newFlag + prtPer + dieFlag)

            SysMgr.addPrint("%16s(%5s/%5s): " % \
                (value['comm'], key, value['tgid']) + timeLine + '\n')

        if len(SysMgr.bufferString) > 0:
            SysMgr.printPipe("%s# %s\n" % ('', 'Delay(%)'))
            SysMgr.doPrint()
            SysMgr.printPipe(oneLine)

        # memory usage on timeline #
        SysMgr.clearPrint()
        if SysMgr.memEnable:
            for key, value in sorted(\
                self.threadData.items(), \
                key=lambda e: e[1]['nrPages'], reverse=True):

                if not SysMgr.showAll and \
                    (value['nrPages'] >> 8) + (value['remainKmem'] >> 20) < 1:
                    break
                elif key[0:2] == '0[':
                    continue

                timeLine = ''
                timeLineLen = titleLineLen
                lval = \
                    long(float(self.totalTime) / intervalEnable) + 1
                for icount in range(0, lval):
                    newFlag = ' '
                    dieFlag = ' '

                    if timeLineLen + 4 > maxLineLen:
                        timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                        timeLineLen = titleLineLen + 4
                    else:
                        timeLineLen += 4

                    try:
                        self.intData[icount][key]
                    except:
                        timeLine += '%3d ' % 0
                        continue

                    nowVal = self.intData[icount][key]

                    try:
                        prevVal = self.intData[icount - 1][key]
                    except:
                        prevVal = nowVal

                    if icount > 0:
                        try:
                            if nowVal['new'] != prevVal['new']:
                                newFlag = self.intData[icount][key]['new']
                        except:
                            newFlag = nowVal['new']
                        try:
                            if nowVal['die'] != prevVal['die']:
                                dieFlag = nowVal['die']
                        except:
                            dieFlag = nowVal['die']
                    else:
                        newFlag = nowVal['new']
                        dieFlag = nowVal['die']

                    memUsage = self.intData[icount][key]['memUsage'] >> 8
                    kmemUsage = self.intData[icount][key]['kmemUsage'] >> 20
                    timeLine += '%4s' % \
                        (newFlag + str(memUsage + kmemUsage) + dieFlag)
                SysMgr.addPrint("%16s(%5s/%5s): " % \
                    (value['comm'], key, value['tgid']) + timeLine + '\n')

            if len(SysMgr.bufferString) > 0:
                SysMgr.printPipe("%s# %s\n" % ('', 'MEM(MB)'))
                SysMgr.doPrint()
                SysMgr.printPipe(oneLine)

        # block read usage on timeline #
        SysMgr.clearPrint()
        if SysMgr.blockEnable:
            for key, value in sorted(\
                self.threadData.items(), \
                key=lambda e: e[1]['reqRdBlock'], reverse=True):

                if value['readBlock'] < 1 and not SysMgr.showAll:
                    break
                elif key[0:2] == '0[':
                    continue

                timeLine = ''
                timeLineLen = titleLineLen
                lval = long(float(self.totalTime) / intervalEnable) + 1
                for icount in range(0, lval):
                    newFlag = ' '
                    dieFlag = ' '

                    if timeLineLen + 4 > maxLineLen:
                        timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                        timeLineLen = titleLineLen + 4
                    else:
                        timeLineLen += 4

                    try:
                        self.intData[icount][key]
                    except:
                        timeLine += '%3d ' % 0
                        continue

                    nowVal = self.intData[icount][key]

                    try:
                        prevVal = self.intData[icount - 1][key]
                    except:
                        prevVal = nowVal

                    if icount > 0:
                        try:
                            if nowVal['new'] != prevVal['new']:
                                newFlag = self.intData[icount][key]['new']
                        except:
                            newFlag = nowVal['new']
                        try:
                            if nowVal['die'] != prevVal['die']:
                                dieFlag = nowVal['die']
                        except:
                            dieFlag = nowVal['die']
                    else:
                        newFlag = nowVal['new']
                        dieFlag = nowVal['die']

                    timeLine += '%4s' % (newFlag + \
                        str(long((self.intData[icount][key]['brUsage'] * \
                        SysMgr.blockSize) >> 20)) + dieFlag)

                SysMgr.addPrint("%16s(%5s/%5s): " % \
                    (value['comm'], key, value['tgid']) + timeLine + '\n')

            if len(SysMgr.bufferString) > 0:
                SysMgr.printPipe("%s# %s\n" % ('', 'BLK_RD(MB)'))
                SysMgr.doPrint()
                SysMgr.printPipe(oneLine)

        # block write usage on timeline #
        SysMgr.clearPrint()
        if SysMgr.blockEnable:
            for key, value in sorted(self.threadData.items(),\
                key=lambda e: e[1]['reqWrBlock'] + (e[1]['awriteBlock'] << 3), \
                reverse=True):

                if value['reqWrBlock'] + (value['awriteBlock'] << 3) < 1 and \
                    not SysMgr.showAll:
                    break
                elif key[0:2] == '0[':
                    continue

                timeLine = ''
                timeLineLen = titleLineLen
                lval = long(float(self.totalTime) / intervalEnable) + 1
                for icount in range(0, lval):
                    newFlag = ' '
                    dieFlag = ' '

                    if timeLineLen + 4 > maxLineLen:
                        timeLine += ('\n' + (' ' * (titleLineLen + 1)))
                        timeLineLen = titleLineLen + 4
                    else:
                        timeLineLen += 4

                    try:
                        self.intData[icount][key]
                    except:
                        timeLine += '%3d ' % 0
                        continue

                    nowVal = self.intData[icount][key]

                    try:
                        prevVal = self.intData[icount - 1][key]
                    except:
                        prevVal = nowVal

                    if icount > 0:
                        try:
                            if nowVal['new'] != prevVal['new']:
                                newFlag = self.intData[icount][key]['new']
                        except:
                            newFlag = nowVal['new']
                        try:
                            if nowVal['die'] != prevVal['die']:
                                dieFlag = nowVal['die']
                        except:
                            dieFlag = nowVal['die']
                    else:
                        newFlag = nowVal['new']
                        dieFlag = nowVal['die']

                    timeLine += '%4s' % (newFlag + \
                        str(long((self.intData[icount][key]['bwUsage'] * \
                        SysMgr.blockSize) >> 20)) + dieFlag)

                SysMgr.addPrint("%16s(%5s/%5s): " % \
                    (value['comm'], key, value['tgid']) + timeLine + '\n')

            if len(SysMgr.bufferString) > 0:
                SysMgr.printPipe("%s# %s\n" % ('', 'BLK_WR(MB)'))
                SysMgr.doPrint()
                SysMgr.printPipe(oneLine)

        # event usage on timeline #
        self.printEventIntervalInfo()

        # save graph #
        if SysMgr.graphEnable and\
            (len(cpuUsageList) > 0 or len(ioUsageList) > 0):
            self.saveImage(SysMgr.inputFile, 'graph')



    def getNetworkUsage(self, prev, now):
        if prev == now:
            return (0, 0)

        nowIn = nowOut = prevIn = prevOut = long(0)

        try:
            idx = -1

            for line in now:
                idx += 1
                if not line.startswith('IpExt'):
                    continue

                if SysMgr.netInIndex < 0:
                    SysMgr.netInIndex = line.split().index('InOctets')

                try:
                    nowStat = line.split()
                    nowIn = long(nowStat[SysMgr.netInIndex])
                    nowOut = long(nowStat[SysMgr.netInIndex + 1])

                    prevStat = prev[idx].split()
                    prevIn = long(prevStat[SysMgr.netInIndex])
                    prevOut = long(prevStat[SysMgr.netInIndex + 1])

                    inDiff = nowIn - prevIn
                    outDiff = nowOut - prevOut

                    return (inDiff, outDiff)
                except:
                    pass
        except:
            return (0, 0)



    @staticmethod
    def readTraceData(file):
        try:
            if SysMgr.isRecordMode() or \
                not SysMgr.compressEnable:
                with open(file, 'r') as fd:
                    return fd.readlines()

            with open(file, 'rb') as fd:
                # find magic number and command #
                buf = b''
                while 1:
                    char = fd.read(1)
                    if char == b'\n':
                        break
                    buf += char

                if len(buf) < 4 or buf[:4] != b'gzip':
                    raise Exception('it is not gziped')

                compressor = SysMgr.getPkg('gzip')
                fd = compressor.GzipFile(fileobj=fd)

                lines = list()
                tlines = fd.read().decode().split('\n')
                for item in tlines:
                    if len(item) == 0:
                        continue
                    lines.append('%s\n' % item)

                return lines
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printOpenErr(file)
            sys.exit(0)



    @staticmethod
    def setLastField(option):
        SysMgr.affinityEnable = False
        SysMgr.wchanEnable = False
        SysMgr.sigHandlerEnable = False
        SysMgr.oomEnable = False

        if option == 'affinity':
            SysMgr.affinityEnable = True
        elif option == 'wchan':
            SysMgr.wchanEnable = True
        elif option == 'signal':
            SysMgr.sigHandlerEnable = True
        elif option == 'oom':
            SysMgr.oomEnable = True
        else:
            SysMgr.printErr(\
                "Fail to set '%s' as a last field" % option)



    @staticmethod
    def parseProcLine(index, procLine):
        TA = ThreadAnalyzer

        # Get time info #
        if 'time' not in TA.procIntData[index]:
            m = re.match((\
                r'.+\[Time:\s*(?P<time>[0-9]+.[0-9]+)\].+'
                r'\[Ctxt:\s*(?P<nrCtxt>[0-9]+)\].+'
                r'\[IRQ:\s*(?P<nrIrq>[0-9]+)\].+'
                r'\[Core:\s*(?P<nrCore>[0-9]+)\].+'
                r'\[Task:\s*(?P<nrProc>[0-9]+)'
                r'/(?P<nrThread>[0-9]+)'), procLine)
            if m:
                d = m.groupdict()
                TA.procIntData[index]['time'] = d['time']
                TA.procIntData[index]['nrCtxt'] = d['nrCtxt']
                TA.procIntData[index]['nrIrq'] = d['nrIrq']
                TA.procIntData[index]['nrCore'] = d['nrCore']
                TA.procIntData[index]['nrProc'] = d['nrProc']
                TA.procIntData[index]['nrThread'] = d['nrThread']
            return

        # Split stats #
        tokenList = procLine.split('|')

        # Get total resource usage #
        if 'total' not in TA.procIntData[index] and \
            tokenList[0].startswith('Total'):

            # CPU & BLOCK stat #
            m = re.match((\
                r'\s*(?P<cpu>\-*[0-9]+)\s*%\s*\(\s*'
                r'(?P<user>\-*[0-9]+)\s*\/s*\s*'
                r'(?P<kernel>\-*[0-9]+)\s*\/s*\s*'
                r'(?P<block>\-*[0-9]+)'), tokenList[1])
            if not m:
                return

            d = m.groupdict()

            cpu = long(d['cpu'])

            # sum total CPU usage #
            TA.procTotData['total']['cpu'] += cpu

            # get total max CPU usage #
            if TA.procTotData['total']['cpuMax'] < cpu:
                TA.procTotData['total']['cpuMax'] = cpu

            # get total min CPU usage #
            if TA.procTotData['total']['cpuMin'] < 0:
                TA.procTotData['total']['cpuMin'] = cpu
            elif TA.procTotData['total']['cpuMin'] > cpu:
                TA.procTotData['total']['cpuMin'] = cpu

            TA.procIntData[index]['total'] = dict(TA.init_procIntData)

            # save CPU usage on this interval #
            try:
                TA.procIntData[index]['total']['cpu'] = cpu
            except:
                TA.procIntData[index]['total']['cpu'] = long(0)

            # save blkwait on this interval #
            try:
                TA.procIntData[index]['total']['blkwait'] = long(d['block'])
            except:
                TA.procIntData[index]['total']['blkwait'] = long(0)

            # MEM stat #
            m = re.match((\
                r'\s*(?P<free>\-*[0-9]+)\s*\(\s*(?P<freeDiff>\-*[0-9]+)\s*'
                r'/\s*(?P<anon>\-*[0-9]+)\s*/\s*(?P<cache>\-*[0-9]+)\s*'
                r'/\s*(?P<kernel>\-*[0-9]+)'), tokenList[2])
            if not m:
                return

            d = m.groupdict()

            freeMem = long(d['free'])
            freeMemDiff = long(d['freeDiff'])
            anonMem = long(d['anon'])
            cacheMem = long(d['cache'])
            kernelMem = long(d['kernel'])

            if TA.procTotData['total']['initMem'] == 0:
                TA.procTotData['total']['initMem'] = freeMem

            TA.procTotData['total']['lastMem'] = freeMem

            # set minimum free memory #
            if TA.procTotData['total']['minMem'] == 0 or \
                TA.procTotData['total']['minMem'] > freeMem:
                TA.procTotData['total']['minMem'] = freeMem
            # set maximum free memory #
            if TA.procTotData['total']['maxMem'] < freeMem:
                TA.procTotData['total']['maxMem'] = freeMem

            TA.procIntData[index]['total']['mem'] = freeMem
            TA.procIntData[index]['total']['memDiff'] = freeMemDiff
            TA.procIntData[index]['total']['anonmem'] = anonMem
            TA.procIntData[index]['total']['cachemem'] = cacheMem
            TA.procIntData[index]['total']['kernelmem'] = kernelMem

            try:
                TA.procIntData[index]['total']['blk'] = tokenList[5]
            except:
                TA.procIntData[index]['total']['blk'] = '-'

            m = re.match(r'\s*(?P<swap>\-*[0-9]+)', tokenList[3])
            if not m:
                return

            d = m.groupdict()

            TA.procIntData[index]['total']['swap'] = long(d['swap'])

            try:
                TA.procIntData[index]['total']['rclm'] = tokenList[4].strip()
            except:
                TA.procIntData[index]['total']['rclm'] = '-'

            try:
                TA.procIntData[index]['total']['nrFlt'] = long(tokenList[6])
            except:
                TA.procIntData[index]['total']['nrFlt'] = '-'

            try:
                TA.procIntData[index]['total']['netIO'] = tokenList[11].strip()
            except:
                TA.procIntData[index]['total']['netIO'] = '-'

            return

        # Get GPU resource usage #
        elif len(tokenList) == 5:
            m = re.match(\
                r'\s*(?P<gpu>.+)\s*\(\s*(?P<usage>[0-9]+)\s*%\)', tokenList[0])
            if m:
                d = m.groupdict()

                gpu = d['gpu'].strip()
                usage = long(d['usage'])

                TA.procIntData[index]['total'].setdefault(\
                    'gpu', dict())
                TA.procTotData['total'].setdefault('gpu', dict())

                try:
                    TA.procTotData['total']['gpu'][gpu]['usage'] += usage

                    if TA.procTotData['total']['gpu'][gpu]['min'] > usage:
                        TA.procTotData['total']['gpu'][gpu]['min'] = usage
                    elif TA.procTotData['total']['gpu'][gpu]['max'] < usage:
                        TA.procTotData['total']['gpu'][gpu]['max'] = usage
                except:
                    TA.procTotData['total']['gpu'][gpu] = dict()
                    TA.procTotData['total']['gpu'][gpu]['usage'] = usage
                    TA.procTotData['total']['gpu'][gpu]['min'] = usage
                    TA.procTotData['total']['gpu'][gpu]['max'] = usage

                try:
                    TA.procIntData[index]['total']['gpu'][gpu] = usage
                except:
                    pass

                return

        # Get Storage resource usage #
        elif len(tokenList) == 12 and tokenList[0][0] == '/':
            convUnit2Size = UtilMgr.convUnit2Size

            TA.procIntData[index]['total'].setdefault('storage', dict())

            TA.procTotData['total'].setdefault('storage', dict())

            try:
                # get device name #
                dev = tokenList[0].strip()
                dev = dev[dev.rfind('/')+1:]

                TA.procIntData[index]['total']['storage'].setdefault(dev, dict())
                TA.procTotData['total']['storage'].setdefault(dev, dict())

                # get busy time and average queue-length #
                busy = convUnit2Size(tokenList[1].strip()[:-1])
                avq = tokenList[2].strip()

                # get storage stats in MB #
                read = convUnit2Size(tokenList[3].strip())
                write = convUnit2Size(tokenList[4].strip())

                freestat = tokenList[5].strip().split('(')
                free = convUnit2Size(freestat[0].strip())
                freeDiff = convUnit2Size(freestat[1][:-1].strip())

                # busy #
                try:
                    TA.procIntData[index]['total']['storage'][dev]['busy'] = busy
                    TA.procTotData['total']['storage'][dev]['busy'] += busy
                except:
                    TA.procTotData['total']['storage'][dev]['busy'] = busy

                # avq #
                try:
                    TA.procIntData[index]['total']['storage'][dev]['avq'] = avq
                    TA.procTotData['total']['storage'][dev]['avq'] += avq
                except:
                    TA.procTotData['total']['storage'][dev]['avq'] = avq

                # read #
                try:
                    TA.procIntData[index]['total']['storage'][dev]['read'] = read
                    TA.procTotData['total']['storage'][dev]['read'] += read
                except:
                    TA.procTotData['total']['storage'][dev]['read'] = read

                # write #
                try:
                    TA.procIntData[index]['total']['storage'][dev]['write'] = \
                        write
                    TA.procTotData['total']['storage'][dev]['write'] += write
                except:
                    TA.procTotData['total']['storage'][dev]['write'] = write

                # freediff #
                try:
                    TA.procIntData[index]['total']['storage'][dev]['free'] = \
                        freeDiff
                    TA.procTotData['total']['storage'][dev]['free'] += freeDiff
                except:
                    TA.procTotData['total']['storage'][dev]['free'] = freeDiff
            except:
                pass

            return

        # Get Network resource usage #
        elif len(tokenList) == 13 and \
            not tokenList[0].startswith('Total'):
            if tokenList[0].strip() == 'ID' or \
                tokenList[0].strip() == 'Dev':
                return

            convUnit2Size = UtilMgr.convUnit2Size

            TA.procIntData[index]['total'].setdefault('netdev', dict())

            TA.procTotData['total'].setdefault('netdev', dict())

            try:
                # get device name #
                dev = tokenList[0].strip()

                TA.procIntData[index]['total']['netdev'].setdefault(dev, dict())
                TA.procTotData['total']['netdev'].setdefault(dev, dict())

                # get storage stats in MB #
                recv = convUnit2Size(tokenList[2].strip())
                tran = convUnit2Size(tokenList[7].strip())

                # recv #
                try:
                    TA.procIntData[index]['total']['netdev'][dev]['recv'] = recv
                    TA.procTotData['total']['netdev'][dev]['recv'] += recv
                except:
                    TA.procTotData['total']['netdev'][dev]['recv'] = recv

                # tran #
                try:
                    TA.procIntData[index]['total']['netdev'][dev]['tran'] = tran
                    TA.procTotData['total']['netdev'][dev]['tran'] += tran
                except:
                    TA.procTotData['total']['netdev'][dev]['tran'] = tran
            except:
                pass

            return

        # Get process resource usage #
        m = re.match((\
            r'\s*(?P<comm>.+) \(\s*(?P<pid>[0-9]+)\/\s*(?P<ppid>[0-9]+)'
            r'\/\s*(?P<nrThreads>[0-9]+)\/(?P<pri>.{4})\)\|\s*(?P<cpu>\S+)'
            r'\(.+\)\|\s*(?P<vss>[0-9]+)\(\s*(?P<rss>[0-9]+)\/.+\)\|\s*'
            r'(?P<blk>\S+)\(\s*(?P<blkrd>.+)\/\s*(?P<blkwr>.+)\/'), procLine)
        if not m:
            return

        d = m.groupdict()
        pid = d['pid']
        comm = d['comm']

        try:
            # ignore special processes #
            if comm[0] == '[' and comm[2] == ']':
                # define real comm #
                rcomm = comm[3:]

                # check item #
                if rcomm not in TA.lifecycleData:
                    TA.lifecycleData[rcomm] = [0] * 8

                # add died process to list #
                if comm[1] == '-':
                    TA.lifecycleData[rcomm][1] += 1

                    try:
                        TA.procIntData[index-1][pid]['die'] = True
                    except:
                        TA.procIntData[index-1][pid] = \
                            dict(TA.init_procIntData)
                        TA.procIntData[index-1][pid]['die'] = True
                # add created process to list #
                elif comm[1] == '+':
                    TA.lifecycleData[rcomm][0] += 1
                # add zomebie process to list #
                elif comm[1].upper() == 'Z':
                    TA.lifecycleData[rcomm][2] += 1
                # add stopped process to list #
                elif comm[1] == 'T':
                    TA.lifecycleData[rcomm][3] += 1
                # add traced process to list #
                elif comm[1] == 't':
                    TA.lifecycleData[rcomm][4] += 1
                # add wait process to list #
                elif comm[1].upper() == 'D':
                    TA.lifecycleData[rcomm][5] += 1
                # add waking process to list #
                elif comm[1].upper() == 'W':
                    TA.lifecycleData[rcomm][6] += 1
                # add parked process to list #
                elif comm[1].upper() == 'P':
                    TA.lifecycleData[rcomm][7] += 1

                return
        except:
            pass

        # check pid in list #
        if pid not in TA.procTotData:
            TA.procTotData[pid] = dict(TA.init_procTotData)
            TA.procTotData[pid]['startIdx'] = index

        cpu = long(float(d['cpu']))
        blk = long(float(d['blk']))
        try:
            blkrd = long(d['blkrd'])
            blkwr = long(d['blkwr'])

            SysMgr.blockEnable = True
        except:
            blkrd = blkwr = long(0)

        # save process info #
        TA.procTotData[pid]['comm'] = d['comm']
        TA.procTotData[pid]['ppid'] = d['ppid']
        TA.procTotData[pid]['nrThreads'] = d['nrThreads']
        TA.procTotData[pid]['pri'] = d['pri']

        # save CPU usage of process #
        TA.procTotData[pid]['cpu'] += cpu

        if TA.procTotData[pid]['cpuMax'] < cpu:
            TA.procTotData[pid]['cpuMax'] = cpu

        if index > 0 and TA.procTotData[pid]['cpuMin'] < 0:
            TA.procTotData[pid]['cpuMin'] = long(0)
        elif TA.procTotData[pid]['cpuMin'] < 0:
            TA.procTotData[pid]['cpuMin'] = cpu
        elif TA.procTotData[pid]['cpuMin'] > cpu:
            TA.procTotData[pid]['cpuMin'] = cpu

        # save block usage of process #
        TA.procTotData[pid]['blk'] += blk
        TA.procTotData[pid]['blkrd'] += blkrd
        TA.procTotData[pid]['blkwr'] += blkwr

        # set vss #
        vss = long(d['vss'])
        if TA.procTotData[pid]['minVss'] >= vss:
            TA.procTotData[pid]['minVss'] = vss
        if TA.procTotData[pid]['maxVss'] < vss:
            TA.procTotData[pid]['maxVss'] = vss

        # set rss #
        rss = long(d['rss'])
        if TA.procTotData[pid]['minMem'] >= rss:
            TA.procTotData[pid]['minMem'] = rss
        if TA.procTotData[pid]['maxMem'] <= rss:
            TA.procTotData[pid]['maxMem'] = rss

        # set mem #
        if TA.procTotData[pid]['initMem'] == 0:
            TA.procTotData[pid]['initMem'] = rss
            TA.procTotData[pid]['lastMem'] = rss

        # save process stats on this interval #
        if pid not in TA.procIntData[index]:
            TA.procIntData[index][pid] = dict(TA.init_procIntData)
            TA.procIntData[index][pid]['cpu'] = cpu
            TA.procIntData[index][pid]['vss'] = vss
            TA.procIntData[index][pid]['blk'] = blk
            TA.procIntData[index][pid]['blkrd'] = blkrd
            TA.procIntData[index][pid]['blkwr'] = blkwr
            TA.procIntData[index][pid]['mem'] = rss
            TA.procIntData[index][pid]['memDiff'] = \
                rss - TA.procTotData[pid]['lastMem']
            TA.procTotData[pid]['lastMem'] = rss



    @staticmethod
    def summarizeInterval():
        if 'total' not in ThreadAnalyzer.procTotData:
            ThreadAnalyzer.procTotData['total'] = \
                dict(ThreadAnalyzer.init_procTotData)

        idx = long(0)
        for val in reversed(SysMgr.procBuffer):
            if len(ThreadAnalyzer.procIntData) < idx + 1:
                ThreadAnalyzer.procIntData.append({})

            procData = val.split('\n')

            for line in procData:
                ThreadAnalyzer.parseProcLine(idx, line)

            idx += 1
            UtilMgr.printProgress(idx, len(SysMgr.procBuffer))

        UtilMgr.deleteProgress()

        if idx == 0:
            return

        for pid, val in ThreadAnalyzer.procTotData.items():
            val['cpuAvg'] = round(val['cpu'] / float(idx), 1)
            val['memDiff'] = val['lastMem'] - val['initMem']



    @staticmethod
    def printFileTable():
        if not SysMgr.fileInstance:
            return

        nrEvent = nrSocket = nrDevice = nrPipe = nrProc = nrFile = long(0)
        for filename in list(SysMgr.fileInstance.keys()):
            # increase type count per process #
            if filename.startswith('anon'):
                nrEvent  += 1
            elif filename.startswith('socket'):
                nrSocket += 1
            elif filename.startswith('/dev'):
                nrDevice += 1
            elif filename.startswith('pipe'):
                nrPipe += 1
            elif filename.startswith(SysMgr.procPath):
                nrProc += 1
            else:
                nrFile += 1

        SysMgr.printPipe(\
            ('\n[Top File Table] [TOTAL: %d] [FILE: %d] [EVENT: %d] '\
            '[SOCKET: %d] [DEV: %d] [PIPE: %d] [PROC: %d]\n') %\
            (len(SysMgr.fileInstance), nrFile, nrEvent,\
            nrSocket, nrDevice, nrPipe, nrProc))
        SysMgr.printPipe("%s\n" % twoLine)
        SysMgr.printPipe("{0:^5} | {1:^144} |\n".format('REF', 'FILE'))
        SysMgr.printPipe("%s\n" % oneLine)

        for filename, value in sorted(SysMgr.fileInstance.items(),\
            key=lambda e: long(e[1]), reverse=True):
            SysMgr.printPipe(\
                "{0:>5} | {1:<144} |\n".format(value, filename))

        if len(SysMgr.fileInstance) == 0:
            SysMgr.printPipe('\tN/A\n')

        SysMgr.printPipe("%s\n" % oneLine)



    @staticmethod
    def printTimeline():
        SysMgr.printPipe('\n[Top Summary Info]\n')
        SysMgr.printPipe("%s\n" % twoLine)

        # check available memory type #
        if SysMgr.freeMemEnable:
            memTitle = 'Free/User/Cache'
        else:
            memTitle = 'Avl/User/Cache'

        SysMgr.printPipe((\
            "{0:^5} | {1:^27} | {2:^3} | {3:^18} | {4:^7} | {5:^3} | "
            "{6:^4} | {7:^9} | {8:^5} | {9:^6} | {10:^6} | {11:^8} | "
            "{12:^4} | {13:^8} |\n").\
            format('IDX', 'Interval', 'CPU', memTitle, \
                'BlkRW', 'Blk', 'SWAP', 'NrPgRclm', 'NrFlt', 'NrCtx', \
                'NrIRQ', 'NrTask', 'NrCr', 'Network'))
        SysMgr.printPipe("%s\n" % twoLine)

        pCnt = long(0)
        for idx, val in list(enumerate(ThreadAnalyzer.procIntData)):
            if idx == 0:
                before = 'START'
            elif 'time' in ThreadAnalyzer.procIntData[idx - 1]:
                before = ThreadAnalyzer.procIntData[idx - 1]['time']
            else:
                continue

            if 'total' not in val:
                continue

            task = '%s/%s' % (val['nrProc'], val['nrThread'])
            SysMgr.printPipe((\
                "{0:>5} | {1:>12} - {2:>12} | {3:>3} | {4:^18} | "
                "{5:^7} | {6:>3} | {7:>4} | {8:^9} | {9:>5} | {10:>6} | "
                "{11:>6} | {12:>8} | {13:^4} | {14:^8} |\n").\
                format(idx + 1, before, val['time'], val['total']['cpu'],\
                '%s/%s/%s' % (val['total']['mem'], val['total']['anonmem'], \
                val['total']['cachemem']), val['total']['blk'], \
                val['total']['blkwait'], val['total']['swap'], \
                val['total']['rclm'], val['total']['nrFlt'], \
                val['nrCtxt'], val['nrIrq'], task, \
                val['nrCore'], val['total']['netIO']))
            pCnt += 1

        if len(ThreadAnalyzer.procIntData) == 0 or pCnt == 0:
            SysMgr.printPipe('\tNone\n')

        SysMgr.printPipe("%s\n" % oneLine)



    @staticmethod
    def printEventInterval():
        if len(ThreadAnalyzer.procEventData) == 0:
            return

        # remove invalid events #
        try:
            initTime = ThreadAnalyzer.procIntData[0]['time']

            eventList = list(ThreadAnalyzer.procEventData)
            for event in eventList:
                time = event[0]

                # skip unbounded events #
                if float(initTime) > time:
                    del ThreadAnalyzer.procEventData[0]
        except:
            return

        if len(ThreadAnalyzer.procEventData) == 0:
            return

        SysMgr.printPipe('\n[Top Event Info] (Unit: %)\n')
        SysMgr.printPipe("%s\n" % twoLine)
        SysMgr.printPipe(("{0:^12} | {1:^12} | {2:^12} | {3:1}\n").\
            format('Timeline', 'Realtime', 'Duration', 'Event'))
        SysMgr.printPipe("%s\n" % twoLine)

        for idx, event in enumerate(ThreadAnalyzer.procEventData):
            time = '%.2f' % float(event[0])
            name = event[1]
            rtime = '%.2f' % float(event[2])
            try:
                diff = '%.2f' % \
                    (float(ThreadAnalyzer.procEventData[idx+1][2]) - float(rtime))
            except:
                diff = '%.2f' % \
                    (float(ThreadAnalyzer.procIntData[-1]['time']) - float(rtime))
            SysMgr.printPipe(("{0:>12} | {1:>12} | {2:>12} | {3:1}\n").\
                format(time, rtime, diff, name))

        SysMgr.printPipe("%s\n" % oneLine)



    @staticmethod
    def printCpuInterval():
        # set comm and pid size #
        pd = SysMgr.pidDigit
        cl = 26-(SysMgr.pidDigit*2)

        SysMgr.printPipe('\n[Top CPU Info] (Unit: %)\n')
        SysMgr.printPipe("%s\n" % twoLine)

        # Print menu #
        procInfo = \
            "{0:^{cl}} ({1:^{pd}}/{2:^{pd}}/{3:^4}/{4:>4})| {5:^12} |".\
            format('COMM', "ID", "Pid", "Nr", "Pri", "Min/Avg/Max", \
            cl=cl, pd=pd)
        procInfoLen = len(procInfo)
        maxLineLen = SysMgr.lineLength

        # Print timeline #
        timeLine = ''
        lineLen = len(procInfo)
        for i in range(1,len(ThreadAnalyzer.procIntData) + 1):
            if lineLen + 5 > maxLineLen:
                timeLine += ('\n' + (' ' * (procInfoLen - 1)) + '| ')
                lineLen = len(procInfo)

            timeLine = '%s%s' % (timeLine, '{0:>6} '.format(i))
            lineLen += 7

        SysMgr.printPipe(("{0:1} {1:1}\n").format(procInfo, timeLine))
        SysMgr.printPipe("%s\n" % twoLine)

        value = ThreadAnalyzer.procTotData['total']
        cpuInfo = '%d/%.1f/%d' % \
            (value['cpuMin'] if value['cpuMin'] > 0 else 0, \
            value['cpuAvg'], value['cpuMax'])

        # Print total CPU usage #
        procInfo = \
            "{0:^{cl}} ({1:>{pd}}/{2:>{pd}}/{3:>4}/{4:>4})| {5:^12} |".\
            format('[CPU]', '-', '-', '-', '-', cpuInfo, cl=cl, pd=pd)
        procInfoLen = len(procInfo)
        maxLineLen = SysMgr.lineLength

        timeLine = ''
        lineLen = len(procInfo)
        for idx in range(0,len(ThreadAnalyzer.procIntData)):
            if lineLen + 5 > maxLineLen:
                timeLine += ('\n' + (' ' * (procInfoLen - 1)) + '| ')
                lineLen = len(procInfo)

            if 'total' in ThreadAnalyzer.procIntData[idx]:
                usage = ThreadAnalyzer.procIntData[idx]['total']['cpu']
            else:
                usage = long(0)

            timeLine = '%s%s' % (timeLine, '{0:>6} '.format(usage))
            lineLen += 7

        SysMgr.printPipe(("{0:1} {1:1}\n").format(procInfo, timeLine))
        SysMgr.printPipe("%s\n" % oneLine)

        # Print CPU usage of processes #
        for pid, value in sorted(\
            ThreadAnalyzer.procTotData.items(), \
            key=lambda e: e[1]['cpu'], reverse=True):

            if pid == 'total':
                continue

            cpuInfo = '%d/%.1f/%d' % \
                (value['cpuMin'] if value['cpuMin'] > 0 else 0, \
                value['cpuAvg'], value['cpuMax'])

            procInfo = \
                "{0:>{cl}} ({1:>{pd}}/{2:>{pd}}/{3:>4}/{4:>4})| {5:^12} |".\
                format(value['comm'][:cl], pid, value['ppid'], \
                value['nrThreads'], value['pri'], cpuInfo, cl=cl, pd=pd)
            procInfoLen = len(procInfo)
            maxLineLen = SysMgr.lineLength

            timeLine = ''
            lineLen = len(procInfo)
            total = long(0)
            for idx in range(0,len(ThreadAnalyzer.procIntData)):
                if lineLen + 5 > maxLineLen:
                    timeLine += ('\n' + (' ' * (procInfoLen - 1)) + '| ')
                    lineLen = len(procInfo)

                if pid in ThreadAnalyzer.procIntData[idx]:
                    usage = ThreadAnalyzer.procIntData[idx][pid]['cpu']
                    total += ThreadAnalyzer.procIntData[idx][pid]['cpu']
                else:
                    usage = long(0)

                timeLine = '%s%s' % (timeLine, '{0:>6} '.format(usage))
                lineLen += 7

            # skip process used no CPU #
            if total == 0:
                continue

            SysMgr.printPipe(\
                ("{0:1} {1:1}\n").format(procInfo, timeLine))
            SysMgr.printPipe("%s\n" % oneLine)



    @staticmethod
    def printGpuInterval():
        # Check gpu data #
        if 'gpu' not in ThreadAnalyzer.procTotData['total']:
            return

        SysMgr.printPipe('\n[Top GPU Info] (Unit: %)\n')
        SysMgr.printPipe("%s\n" % twoLine)

        # Print menu #
        gpuInfo = "{0:^16} | {1:^12} |".format('GPU', 'Min/Avg/Max')
        gpuInfoLen = len(gpuInfo)
        maxLineLen = SysMgr.lineLength

        # Print timeline #
        timeLine = ''
        lineLen = len(gpuInfo)
        for i in range(1,len(ThreadAnalyzer.procIntData) + 1):
            if lineLen + 5 > maxLineLen:
                timeLine += ('\n' + (' ' * (gpuInfoLen - 1)) + '| ')
                lineLen = len(gpuInfo)

            timeLine = '%s%s' % (timeLine, '{0:>6} '.format(i))
            lineLen += 7

        SysMgr.printPipe(("{0:1} {1:1}\n").format(gpuInfo, timeLine))
        SysMgr.printPipe("%s\n" % twoLine)

        # Print gpu usage #
        for gpu, stat in ThreadAnalyzer.procTotData['total']['gpu'].items():
            try:
                avg = stat['usage'] / len(ThreadAnalyzer.procIntData)
            except:
                avg = long(0)

            # get stats #
            stats = '%d/%d/%d' % \
                (stat['min'] if stat['min'] > 0 else 0, avg, stat['max'])

            gpuInfo = "{0:>16} | {1:^12} |".format(gpu, stats)
            gpuInfoLen = len(gpuInfo)
            maxLineLen = SysMgr.lineLength

            timeLine = ''
            lineLen = len(gpuInfo)
            total = long(0)
            for idx in range(0,len(ThreadAnalyzer.procIntData)):
                if lineLen + 5 > maxLineLen:
                    timeLine += ('\n' + (' ' * (gpuInfoLen - 1)) + '| ')
                    lineLen = len(gpuInfo)

                try:
                    usage = ThreadAnalyzer.procIntData[idx]['total']['gpu'][gpu]
                    total += usage
                except:
                    usage = long(0)

                timeLine = '%s%s' % (timeLine, '{0:>6} '.format(usage))
                lineLen += 7

            SysMgr.printPipe(("{0:1} {1:1}\n").format(gpuInfo, timeLine))
            SysMgr.printPipe("%s\n" % oneLine)



    @staticmethod
    def printRssInterval():
        # set comm and pid size #
        pd = SysMgr.pidDigit
        cl = 26-(SysMgr.pidDigit*2)

        # check memory type #
        if SysMgr.pssEnable:
            mtype = 'PSS'
        elif SysMgr.ussEnable:
            mtype = 'USS'
        else:
            mtype = 'RSS'

        SysMgr.printPipe(\
            '\n[Top %s Info] (Unit: MB)\n' % mtype)
        SysMgr.printPipe("%s\n" % twoLine)

        # Print menu #
        procInfo = "{0:^{cl}} ({1:^{pd}}/{2:^{pd}}/{3:^4}/{4:>4})|{5:^6} |".\
            format('COMM', "ID", "Pid", "Nr", "Pri", " Max", cl=cl, pd=pd)
        procInfoLen = len(procInfo)
        maxLineLen = SysMgr.lineLength

        # Print timeline #
        timeLine = ''
        lineLen = len(procInfo)
        for i in range(1,len(ThreadAnalyzer.procIntData) + 1):
            if lineLen + 5 > maxLineLen:
                timeLine += ('\n' + (' ' * (procInfoLen - 1)) + '| ')
                lineLen = len(procInfo)

            timeLine = '%s%s' % (timeLine, '{0:>6} '.format(i))
            lineLen += 7

        SysMgr.printPipe(("{0:1} {1:1}\n").format(procInfo, timeLine))
        SysMgr.printPipe("%s\n" % twoLine)

        # Print total free memory #
        value = ThreadAnalyzer.procTotData['total']
        procInfo = "{0:^{cl}} ({1:>{pd}}/{2:>{pd}}/{3:>4}/{4:>4})|{5:>6} |".\
            format('[FREE/MIN]', '-', '-', '-', '-', value['minMem'], cl=cl, pd=pd)
        procInfoLen = len(procInfo)
        maxLineLen = SysMgr.lineLength

        timeLine = ''
        lineLen = len(procInfo)
        for idx in range(0,len(ThreadAnalyzer.procIntData)):
            if lineLen + 5 > maxLineLen:
                timeLine += ('\n' + (' ' * (procInfoLen - 1)) + '| ')
                lineLen = len(procInfo)

            if 'total' in ThreadAnalyzer.procIntData[idx]:
                usage = ThreadAnalyzer.procIntData[idx]['total']['mem']
            else:
                usage = long(0)

            timeLine = '%s%s' % (timeLine, '{0:>6} '.format(usage))
            lineLen += 7

        SysMgr.printPipe(("{0:1} {1:1}\n").format(procInfo, timeLine))
        SysMgr.printPipe("%s\n" % oneLine)

        # Print rss of processes #
        for pid, value in sorted(\
            ThreadAnalyzer.procTotData.items(), \
            key=lambda e: 0 if not 'maxMem' in e[1] else e[1]['maxMem'], \
            reverse=True):

            if pid == 'total' or value['maxMem'] == 0:
                continue

            procInfo = \
                "{0:>{cl}} ({1:>{pd}}/{2:>{pd}}/{3:>4}/{4:>4})|{5:>6} |".\
                format(value['comm'][:cl], pid, value['ppid'], \
                value['nrThreads'], value['pri'], value['maxMem'], cl=cl, pd=pd)
            procInfoLen = len(procInfo)
            maxLineLen = SysMgr.lineLength

            prev = long(0)
            timeLine = ''
            minRss = maxRss = long(0)
            lineLen = len(procInfo)
            intData = ThreadAnalyzer.procIntData
            for idx in range(0,len(intData)):
                if lineLen + 5 > maxLineLen:
                    timeLine += ('\n' + (' ' * (procInfoLen - 1)) + '| ')
                    lineLen = len(procInfo)

                # process is shown #
                if pid in intData[idx]:
                    if intData[idx][pid]['die']:
                        try:
                            usage = intData[idx][pid]['mem']
                        except:
                            prev = usage = long(0)
                    else:
                        usage = intData[idx][pid]['mem']
                        if usage == 0 and prev > 0:
                            usage = prev
                        else:
                            prev = usage
                # process was shown previously #
                elif prev > 0:
                    try:
                        # process was terminated #
                        if intData[idx-1][pid]['die']:
                            prev = usage = long(0)
                        # process is alive #
                        else:
                            usage = prev
                    except:
                        usage = prev
                else:
                    prev = usage = long(0)

                if usage == 0:
                    pass
                else:
                    if minRss == 0 or minRss > usage:
                        minRss = usage
                    if maxRss == 0 or maxRss < usage:
                        maxRss = usage

                timeLine = '%s%s' % (timeLine, '{0:>6} '.format(usage))
                lineLen += 7

            if maxRss - minRss  > 0:
                try:
                    procInfo = procInfo.replace(' (', '^(', 1)
                except:
                    pass

            SysMgr.printPipe(\
                ("{0:1} {1:1}\n").format(procInfo, timeLine))
            SysMgr.printPipe("%s\n" % oneLine)



    @staticmethod
    def printVssInterval():
        # set comm and pid size #
        pd = SysMgr.pidDigit
        cl = 26-(SysMgr.pidDigit*2)

        SysMgr.printPipe('\n[Top VSS Info] (Unit: MB)\n')
        SysMgr.printPipe("%s\n" % twoLine)

        # Print menu #
        procInfo = "{0:^{cl}} ({1:^{pd}}/{2:^{pd}}/{3:^4}/{4:>4})|{5:^6} |".\
            format('COMM', "ID", "Pid", "Nr", "Pri", " Max", cl=cl, pd=pd)
        procInfoLen = len(procInfo)
        maxLineLen = SysMgr.lineLength

        # Print timeline #
        timeLine = ''
        lineLen = len(procInfo)
        for i in range(1,len(ThreadAnalyzer.procIntData) + 1):
            if lineLen + 5 > maxLineLen:
                timeLine += ('\n' + (' ' * (procInfoLen - 1)) + '| ')
                lineLen = len(procInfo)

            timeLine = '%s%s' % (timeLine, '{0:>6} '.format(i))
            lineLen += 7

        SysMgr.printPipe(("{0:1} {1:1}\n").format(procInfo, timeLine))
        SysMgr.printPipe("%s\n" % twoLine)

        # Print total free memory #
        value = ThreadAnalyzer.procTotData['total']
        procInfo = "{0:^{cl}} ({1:>{pd}}/{2:>{pd}}/{3:>4}/{4:>4})|{5:>6} |".\
            format('[FREE/MIN]', '-', '-', '-', '-', value['minMem'], cl=cl, pd=pd)
        procInfoLen = len(procInfo)
        maxLineLen = SysMgr.lineLength

        timeLine = ''
        lineLen = len(procInfo)
        for idx in range(0,len(ThreadAnalyzer.procIntData)):
            if lineLen + 5 > maxLineLen:
                timeLine += ('\n' + (' ' * (procInfoLen - 1)) + '| ')
                lineLen = len(procInfo)

            if 'total' in ThreadAnalyzer.procIntData[idx]:
                usage = ThreadAnalyzer.procIntData[idx]['total']['mem']
            else:
                usage = long(0)

            timeLine = '%s%s' % (timeLine, '{0:>6} '.format(usage))
            lineLen += 7

        SysMgr.printPipe(("{0:1} {1:1}\n").format(procInfo, timeLine))
        SysMgr.printPipe("%s\n" % oneLine)

        # Print vss of processes #
        for pid, value in sorted(\
            ThreadAnalyzer.procTotData.items(), \
            key=lambda e: 0 if not 'maxVss' in e[1] else e[1]['maxVss'], \
            reverse=True):

            if pid == 'total' or value['maxVss'] == 0:
                continue

            procInfo = \
                "{0:>{cl}} ({1:>{pd}}/{2:>{pd}}/{3:>4}/{4:>4})|{5:>6} |".\
                format(value['comm'][:cl], pid, value['ppid'], \
                value['nrThreads'], value['pri'], value['maxVss'], cl=cl, pd=pd)
            procInfoLen = len(procInfo)
            maxLineLen = SysMgr.lineLength

            prev = long(0)
            timeLine = ''
            minVss = maxVss = long(0)
            lineLen = len(procInfo)
            intData = ThreadAnalyzer.procIntData
            for idx in range(0,len(intData)):
                if lineLen + 5 > maxLineLen:
                    timeLine += ('\n' + (' ' * (procInfoLen - 1)) + '| ')
                    lineLen = len(procInfo)

                # process is shown #
                if pid in intData[idx]:
                    if intData[idx][pid]['die']:
                        try:
                            usage = intData[idx][pid]['vss']
                        except:
                            prev = usage = long(0)
                    else:
                        usage = intData[idx][pid]['vss']
                        if usage == 0 and prev > 0:
                            usage = prev
                        else:
                            prev = usage
                # process was shown previously #
                elif prev > 0:
                    try:
                        # process was terminated #
                        if intData[idx-1][pid]['die']:
                            prev = usage = long(0)
                        # process is alive #
                        else:
                            usage = prev
                    except:
                        usage = prev
                else:
                    prev = usage = long(0)

                if usage == 0:
                    pass
                else:
                    if minVss == 0 or minVss > usage:
                        minVss = usage
                    if maxVss == 0 or maxVss < usage:
                        maxVss = usage

                timeLine = '%s%s' % (timeLine, '{0:>6} '.format(usage))
                lineLen += 7

            if maxVss - minVss  > 0:
                try:
                    procInfo = procInfo.replace(' (', '^(', 1)
                except:
                    pass

            SysMgr.printPipe(\
                ("{0:1} {1:1}\n").format(procInfo, timeLine))
            SysMgr.printPipe("%s\n" % oneLine)



    @staticmethod
    def printBlkInterval():
        # set comm and pid size #
        pd = SysMgr.pidDigit
        cl = 26-(SysMgr.pidDigit*2)

        SysMgr.printPipe('\n[Top Block Info] (Unit: %)\n')
        SysMgr.printPipe("%s\n" % twoLine)

        # Print menu #
        procInfo = "{0:^{cl}} ({1:^{pd}}/{2:^{pd}}/{3:^4}/{4:>4})| {5:^5} |".\
            format('COMM', "ID", "Pid", "Nr", "Pri", " Sum", cl=cl, pd=pd)
        procInfoLen = len(procInfo)
        maxLineLen = SysMgr.lineLength

        # Print timeline #
        timeLine = ''
        lineLen = len(procInfo)
        for i in range(1,len(ThreadAnalyzer.procIntData) + 1):
            if lineLen + 5 > maxLineLen:
                timeLine += ('\n' + (' ' * (procInfoLen - 1)) + '| ')
                lineLen = len(procInfo)

            timeLine = '%s%s' % (timeLine, '{0:>6} '.format(i))
            lineLen += 7

        SysMgr.printPipe(("{0:1} {1:1}\n").format(procInfo, timeLine))
        SysMgr.printPipe("%s\n" % twoLine)

        # Print block usage of processes #
        itemCnt = long(0)
        for pid, value in sorted(\
            ThreadAnalyzer.procTotData.items(), key=lambda e: e[1]['blk'], \
            reverse=True):

            if pid == 'total' or \
                value['blk'] == value['blkrd'] == value['blkwr'] == 0:
                continue

            if SysMgr.blockEnable:
                bstat = '%s/%s' % (value['blkrd'], value['blkwr'])
            else:
                bstat = value['blk']

            procInfo = \
                "{0:>{cl}} ({1:>{pd}}/{2:>{pd}}/{3:>4}/{4:>4})| {5:>5} |".\
                format(value['comm'], pid, value['ppid'], \
                value['nrThreads'], value['pri'], bstat, cl=cl, pd=pd)
            procInfoLen = len(procInfo)
            maxLineLen = SysMgr.lineLength

            timeLine = ''
            lineLen = len(procInfo)
            for idx in range(0,len(ThreadAnalyzer.procIntData)):
                if lineLen + 5 > maxLineLen:
                    timeLine += ('\n' + (' ' * (procInfoLen - 1)) + '| ')
                    lineLen = len(procInfo)

                if pid in ThreadAnalyzer.procIntData[idx]:
                    target = ThreadAnalyzer.procIntData[idx][pid]
                    if SysMgr.blockEnable:
                        usage = '%s/%s' % (target['blkrd'], target['blkwr'])
                    else:
                        usage = target['blk']
                else:
                    if SysMgr.blockEnable:
                        usage = '0/0'
                    else:
                        usage = long(0)

                timeLine = '%s%s' % (timeLine, '{0:>6} '.format(usage))
                lineLen += 7

            SysMgr.printPipe(("{0:1} {1:1}\n").format(procInfo, timeLine))
            SysMgr.printPipe("%s\n" % oneLine)
            itemCnt += 1

        if itemCnt == 0:
            SysMgr.printPipe('\tNone\n')
            SysMgr.printPipe("%s\n" % oneLine)



    @staticmethod
    def printStorageInterval():
        TA = ThreadAnalyzer

        convSize2Unit = UtilMgr.convSize2Unit

        SysMgr.printPipe('\n[Top Storage Info] (Unit: %)\n')
        SysMgr.printPipe("%s\n" % twoLine)

        # Print menu #
        storageInfo = "{0:^16} | {1:^21} |".\
            format('Storage', 'Busy/Read/Write/Free')
        storageInfoLen = len(storageInfo)
        maxLineLen = SysMgr.lineLength

        # Print timeline #
        timeLine = ''
        lineLen = len(storageInfo)
        for i in range(1,len(TA.procIntData) + 1):
            if lineLen + 21 > maxLineLen:
                timeLine += ('\n' + (' ' * (storageInfoLen - 1)) + '| ')
                lineLen = len(storageInfo)

            timeLine = '%s%s' % (timeLine, '{0:>21} '.format(i))
            lineLen += 21

        SysMgr.printPipe(("{0:1} {1:1}\n").format(storageInfo, timeLine))
        SysMgr.printPipe("%s\n" % twoLine)

        # Check storage data #
        if 'storage' not in TA.procTotData['total']:
            SysMgr.printPipe("\tNone\n%s\n" % oneLine)
            return

        # Print storage usage #
        for dev, val in TA.procTotData['total']['storage'].items():
            if dev == '[ TOTAL ]':
                continue

            try:
                total = '%s/%s/%s/%s' % \
                   ('%.1f' % (val['busy'] / len(TA.procIntData)),\
                   convSize2Unit(val['read'], True),\
                   convSize2Unit(val['write'], True),\
                   convSize2Unit(val['free'], True))
            except:
                continue

            storageInfo = "{0:^16} | {1:^21} |".format(dev, total)
            storageInfoLen = len(storageInfo)
            maxLineLen = SysMgr.lineLength

            timeLine = ''
            lineLen = len(storageInfo)
            for idx in range(0,len(TA.procIntData)):
                if lineLen + 21 > maxLineLen:
                    timeLine += ('\n' + (' ' * (storageInfoLen - 1)) + '| ')
                    lineLen = len(storageInfo)

                try:
                    stats = TA.procIntData[idx]['total']['storage'][dev]
                    usage = '%s/%s/%s/%s' % \
                        (stats['busy'],\
                        convSize2Unit(stats['read'], True),\
                        convSize2Unit(stats['write'], True),\
                        convSize2Unit(stats['free'], True))
                except:
                    continue

                timeLine = '%s%s' % (timeLine, '{0:>21} '.format(usage))
                lineLen += 21

            SysMgr.printPipe(\
                ("{0:1} {1:1}\n").format(storageInfo, timeLine))
            SysMgr.printPipe("%s\n" % oneLine)



    @staticmethod
    def printNetworkInterval():
        TA = ThreadAnalyzer

        convSize2Unit = UtilMgr.convSize2Unit

        SysMgr.printPipe('\n[Top Network Info] (Unit: %)\n')
        SysMgr.printPipe("%s\n" % twoLine)

        # Print menu #
        networkInfo = "{0:^16} | {1:^21} |".format('Network', 'Read/Write')
        networkInfoLen = len(networkInfo)
        maxLineLen = SysMgr.lineLength

        # Print timeline #
        timeLine = ''
        lineLen = len(networkInfo)
        for i in range(1,len(TA.procIntData) + 1):
            if lineLen + 21 > maxLineLen:
                timeLine += ('\n' + (' ' * (networkInfoLen - 1)) + '| ')
                lineLen = len(networkInfo)

            timeLine = '%s%s' % (timeLine, '{0:>21} '.format(i))
            lineLen += 21

        SysMgr.printPipe(("{0:1} {1:1}\n").format(networkInfo, timeLine))
        SysMgr.printPipe("%s\n" % twoLine)

        # Check network data #
        if 'netdev' not in TA.procTotData['total']:
            SysMgr.printPipe("\tNone\n%s\n" % oneLine)
            return

        # Print network usage #
        for dev, val in TA.procTotData['total']['netdev'].items():
            if dev == '[ TOTAL ]':
                continue

            try:
                total = '%s/%s' % \
                   (convSize2Unit(val['recv'], True),\
                   convSize2Unit(val['tran'], True))
            except:
                continue

            networkInfo = "{0:^16} | {1:^21} |".format(dev, total)
            networkInfoLen = len(networkInfo)
            maxLineLen = SysMgr.lineLength

            timeLine = ''
            lineLen = len(networkInfo)
            for idx in range(0,len(TA.procIntData)):
                if lineLen + 21 > maxLineLen:
                    timeLine += ('\n' + (' ' * (networkInfoLen - 1)) + '| ')
                    lineLen = len(networkInfo)

                try:
                    stats = TA.procIntData[idx]['total']['netdev'][dev]
                    usage = '%s/%s' % \
                        (convSize2Unit(stats['recv'], True),\
                        convSize2Unit(stats['tran'], True))
                except:
                    continue

                timeLine = '%s%s' % (timeLine, '{0:>21} '.format(usage))
                lineLen += 21

            SysMgr.printPipe(\
                ("{0:1} {1:1}\n").format(networkInfo, timeLine))
            SysMgr.printPipe("%s\n" % oneLine)



    @staticmethod
    def printIntervalUsage():
        if SysMgr.fileTopEnable:
            ThreadAnalyzer.printFileTable()
        elif SysMgr.jsonOutputEnable or \
            SysMgr.dltTopEnable:
            pass
        else:
            # build summary interval table #
            ThreadAnalyzer.summarizeInterval()

            # print interval info #
            ThreadAnalyzer.printTimeline()
            ThreadAnalyzer.printEventInterval()
            ThreadAnalyzer.printCpuInterval()
            ThreadAnalyzer.printGpuInterval()
            ThreadAnalyzer.printVssInterval()
            ThreadAnalyzer.printRssInterval()
            ThreadAnalyzer.printBlkInterval()
            ThreadAnalyzer.printStorageInterval()
            ThreadAnalyzer.printNetworkInterval()

        # print interval info #
        ThreadAnalyzer.printMemAnalysis()

        # print detailed statistics #
        msg = ' Detailed Statistics '
        stars = '*' * long((long(SysMgr.lineLength) - len(msg)) / 2)
        SysMgr.printPipe('\n\n\n\n%s%s%s\n\n' % (stars, msg, stars))
        if SysMgr.procBuffer == []:
            SysMgr.printPipe("\n\tNone")
        else:
            SysMgr.printPipe(SysMgr.procBuffer)

        # print lifecycle info #
        if SysMgr.processEnable:
            msg = ' Process Lifecycle '
        else:
            msg = ' Thread Lifecycle '
        stars = '*' * long((long(SysMgr.lineLength) - len(msg)) / 2)
        SysMgr.printPipe('\n\n\n\n%s%s%s\n' % (stars, msg, stars))
        ThreadAnalyzer.printProcLifecycle()

        # print process tree #
        if SysMgr.processEnable:
            msg = ' Process Tree '
        else:
            msg = ' Thread Tree '
        stars = '*' * long((long(SysMgr.lineLength) - len(msg)) / 2)
        SysMgr.printPipe('\n\n\n\n%s%s%s\n' % (stars, msg, stars))
        ThreadAnalyzer.printProcTree()

        # print Leak hint #
        msg = ' Leak Hint '
        stars = '*' * long((long(SysMgr.lineLength) - len(msg)) / 2)
        SysMgr.printPipe('\n\n\n\n%s%s%s\n' % (stars, msg, stars))
        ThreadAnalyzer.printLeakHint()

        # initialize parse buffer #
        ThreadAnalyzer.lifecycleData = {}
        ThreadAnalyzer.procTotData = {}
        ThreadAnalyzer.procIntData = []



    @staticmethod
    def printLeakHint():
        if not SysMgr.isTopMode() or \
            not SysMgr.topInstance:
            SysMgr.printPipe("\n\tNone")
            return

        convertNum = UtilMgr.convNum
        convertFunc = UtilMgr.convSize2Unit

        for pid in tuple(SysMgr.procInstance.keys()):
            path = '%s/%s' % (SysMgr.procPath, pid)
            SysMgr.topInstance.updateOOMScore(path, pid)
            SysMgr.topInstance.saveProcStatusData(path, pid)

        if SysMgr.processEnable:
            pidType = 'PID'
            ppidType = 'PPID'
        else:
            pidType = 'TID'
            ppidType = 'PID'

        SysMgr.printPipe((\
            "\n{0:1}\n{1:>16}({2:>5}/{3:>5}) "
            "{4:>8} {5:>8} {6:>8} {7:>12} {8:>20}\n{9:^1}\n").format(\
                twoLine, 'Name', pidType, ppidType, 'VSS', 'RSS', 'SHM', \
                'OOM_SCORE', 'LifeTime', oneLine))

        cnt = long(0)
        commIdx = SysMgr.topInstance.commIdx
        ppidIdx = SysMgr.topInstance.ppidIdx
        vssIdx = SysMgr.topInstance.vssIdx
        rssIdx = SysMgr.topInstance.rssIdx
        shrIdx = SysMgr.topInstance.shrIdx
        starttimeIdx = SysMgr.topInstance.starttimeIdx

        for pid, val in sorted(SysMgr.procInstance.items(), \
            key=lambda x: long(x[1]['oomScore'] if 'oomScore' in x[1] else 0), \
            reverse=True):
            if 'oomScore' not in val or val['oomScore'] == 0:
                break

            stat = val['stat']
            statm = val['statm']
            comm = stat[commIdx][1:-1]
            runtime = \
                SysMgr.uptime - (float(val['stat'][starttimeIdx]) / 100)

            if SysMgr.processEnable:
                ppid = stat[ppidIdx]
            else:
                ppid = val['mainID']

            SysMgr.printPipe((\
                "{0:>16}({1:>5}/{2:>5}) "
                "{3:>8} {4:>8} {5:>8} {6:>12} {7:>20}\n").format(\
                    comm, pid, ppid, \
                    convertFunc(long(stat[vssIdx])), \
                    convertFunc(long(stat[rssIdx]) << 12), \
                    convertFunc(long(statm[shrIdx]) << 12), \
                    convertNum(val['oomScore']), \
                    UtilMgr.convTime(runtime)))

            cnt += 1

        if cnt == 0:
            SysMgr.printPipe("\tNone\n")

        SysMgr.printPipe(oneLine)



    @staticmethod
    def printProcLifecycle():
        if len(ThreadAnalyzer.lifecycleData) == 0:
            SysMgr.printPipe("\n\tNone")
            return

        convertFunc = UtilMgr.convSize2Unit

        SysMgr.printPipe((\
            "\n{0:1}\n{1:^16} {2:>15} {3:>15} {4:>15} "
            "{5:>15} {6:>15} {7:>15} {8:>15} {9:>15}\n{10:1}\n").\
                format(twoLine, "Name", "Created", "Terminated", \
                    "Zombie", "Stopped", "Traced", "Waiting", \
                    "Waking", "Parked", oneLine))

        for comm, event in sorted(ThreadAnalyzer.lifecycleData.items(),\
            key=lambda e: e[1][0] + e[1][1], reverse=True):
            # convert 0 to '-' #
            for idx, value in enumerate(event):
                if value == 0:
                    event[idx] = '-'

            SysMgr.printPipe((\
                "{0:^16} {1:>15} {2:>15} {3:>15} {4:>15} "
                "{5:>15} {6:>15} {7:>15} {8:>15}\n").\
                    format(comm, event[0], event[1], event[2], \
                        event[3], event[4], event[5], event[6], event[7]))

        SysMgr.printPipe(oneLine)



    @staticmethod
    def printProcTree(instance=None):
        if not instance and SysMgr.procInstance:
            instance = SysMgr.procInstance

        if not instance:
            SysMgr.printPipe("\n\tNone")
            return

        # get process/thread tree #
        try:
            procTree = ThreadAnalyzer.getProcTreeFromList(instance)
        except:
            SysMgr.printPipe("\n\tNone")
            return

        # print nodes in tree #
        def printTreeNodes(root, depth, commIdx):
            treestr = ''

            for pid, childs in root.items():
                indent = ''

                try:
                    comm = instance[pid]['stat'][commIdx][1:-1]
                except:
                    continue

                if depth == 0:
                    indent = '\n'

                for idx in range(0, depth):
                    indent = '%s%s|' % (indent, ' ' * 5)

                nrChild = len(childs)
                if nrChild > 0:
                    treestr += '%s- %s(%s)[%s]\n' % \
                        (indent, comm, pid, nrChild)
                else:
                    treestr += '%s- %s(%s)\n' % (indent, comm, pid)

                treestr += printTreeNodes(childs, depth + 1, commIdx)

            return treestr

        commIdx = ConfigMgr.STAT_ATTR.index("COMM")

        # get string for tree #
        finalstr = printTreeNodes(procTree, 0, commIdx)

        # print tree #
        SysMgr.printPipe(finalstr)



    @staticmethod
    def printMemAnalysis():
        if not SysMgr.procInstance:
            return

        statList = ConfigMgr.STAT_ATTR

        # set comm and pid size #
        pd = SysMgr.pidDigit
        cl = 26-(SysMgr.pidDigit*2)

        SysMgr.printPipe('\n[Top Memory Details] (Unit: MB/KB/NR)\n')
        SysMgr.printPipe("%s\n" % twoLine)

        # Print menu #
        SysMgr.printPipe((\
            "{0:^{cl}} ({1:^{pd}}/{2:^{pd}}) | {3:^8} | "
            "{4:^5} | {5:^6} | {6:^6} | {7:^6} | {8:^6} | {9:^6} | {10:^10} | "
            "{11:^12} | {12:^12} | {13:^12} |\n{14}\n").\
            format('COMM', 'ID', 'Pid', 'Type', 'Cnt', \
            'VSS/M', 'RSS/M', 'PSS/M', 'SWAP/M', 'HUGE/M', 'LOCK/K', \
            'PDRT/K', 'SDRT/K', 'NOPM/K', twoLine, cl=cl, pd=pd))

        cnt = 1
        limitProcCnt = 6
        commIdx = statList.index("COMM")
        ppidIdx = statList.index("PPID")

        try:
            sortedList = sorted(SysMgr.procInstance.items(), \
                key=lambda e: long(e[1]['stat'][statList.index("RSS")]), \
                reverse=True)
        except:
            SysMgr.printWarn(\
                "Fail to get memory details because of sort error")
            SysMgr.printPipe("\tNone\n%s\n" % oneLine)
            return

        for key, value in sortedList:
            # check filter #
            if SysMgr.filterGroup != []:
                skip = True
                for item in SysMgr.filterGroup:
                    if key == item or item in value['stat'][commIdx]:
                        skip = False
                        break
                if skip:
                    continue

            # only print memory details of top 4 processes #
            if cnt > limitProcCnt:
                break

            # get memory details #
            if not value['maps']:
                ThreadAnalyzer.saveProcSmapsData(value['taskPath'], key)

            if not value['maps']:
                continue

            cnt += 1

            totalCnt = long(0)
            totalVmem = long(0)
            totalRss = long(0)
            totalPss = long(0)
            totalSwap = long(0)
            totalHuge = long(0)
            totalLock = long(0)
            totalPdirty = long(0)
            totalSdirty = long(0)
            totalRef = long(0)
            totalNone = long(0)

            procInfo = ' '
            procDetails = ''

            for idx, item in sorted(value['maps'].items(), reverse=True):
                if len(item) == 0:
                    continue

                totalCnt += item['count']

                try:
                    vmem = item['Size:'] >> 10
                    totalVmem += vmem
                except:
                    vmem = long(0)

                try:
                    rss = item['Rss:'] >> 10
                    totalRss += rss
                except:
                    rss = long(0)

                try:
                    pss = item['Pss:'] >> 10
                    totalPss += pss
                except:
                    pss = long(0)

                try:
                    swap = item['Swap:'] >> 10
                    totalSwap += swap
                except:
                    swap = long(0)

                try:
                    huge = item['AnonHugePages:'] >> 10
                    totalHuge += huge
                except:
                    huge = long(0)

                try:
                    lock = item['Locked:']
                    totalLock += lock
                except:
                    lock = long(0)

                try:
                    pdirty = item['Private_Dirty:']
                    totalPdirty += pdirty
                except:
                    pdirty = long(0)

                try:
                    sdirty = item['Shared_Dirty:']
                    totalSdirty += sdirty
                except:
                    sdirty = long(0)

                try:
                    ref = item['Referenced:']
                    totalRef += ref
                except:
                    ref = long(0)

                try:
                    none = item['NOPM']
                    totalNone += none
                except:
                    none = long(0)

                procDetails = \
                    "%s%s" % (procDetails, ("{0:>30} | {1:>8} | {2:>5} | "
                    "{3:>6} | {4:>6} | {5:>6} | {6:>6} | {7:>6} | {8:>10} | "
                    "{9:>12} | {10:>12} | {11:>12} |\n").\
                    format(procInfo, idx, item['count'], \
                    vmem, rss, pss, swap, huge, lock, pdirty, sdirty, none))

            if SysMgr.processEnable:
                ppid = value['stat'][ppidIdx]
            else:
                ppid = value['mainID']

            procInfo = "{0:>{cl}} ({1:>{pd}}/{2:>{pd}})".\
                format(value['stat'][commIdx][1:-1][:cl], \
                key, ppid, cl=cl, pd=pd)

            SysMgr.printPipe(("{0:>30} | {1:>8} | {2:>5} | "
                "{3:>6} | {4:>6} | {5:>6} | {6:>6} | {7:>6} | {8:>10} | "
                "{9:>12} | {10:>12} | {11:>12} |\n{12}").\
                format(procInfo, '[TOTAL]', totalCnt, \
                totalVmem, totalRss, totalPss, totalSwap, \
                totalHuge, totalLock, totalPdirty, totalSdirty, \
                totalNone, procDetails))

            SysMgr.printPipe('%s\n' % oneLine)

        if cnt == 1:
            SysMgr.printPipe("\tNone\n%s\n" % oneLine)



    @staticmethod
    def getInitTime(fname):
        fd = None
        systemInfoBuffer = ''

        if SysMgr.isRecordMode():
            nrLine = SysMgr.pageSize
            compressor = None
        else:
            nrLine = long(0)

            try:
                fd = open(fname, 'rb')
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printOpenErr(fname)
                sys.exit(0)

            # check compression #
            try:
                buf = fd.readline()
                if buf.decode().startswith('gzip'):
                    SysMgr.compressEnable = True
                    compressor = SysMgr.getPkg('gzip')
                    fd = compressor.GzipFile(fileobj=fd)
                else:
                    SysMgr.compressEnable = False
                    compressor = None
                    fd.close()
                    fd = None
            except SystemExit:
                sys.exit(0)
            except:
                compressor = None
                SysMgr.printErr(\
                    "Fail to check compression for %s" % fname, True)

        while 1:
            start = end = -1

            # make delay for some logs not written immediately #
            if SysMgr.isRecordMode():
                try:
                    time.sleep(0.1)
                except:
                    return 0

            # update fd #
            try:
                if SysMgr.isRecordMode():
                    verbose = False
                else:
                    verbose = True

                if compressor and fd:
                    if verbose:
                        SysMgr.printStat(\
                            r"start checking %s..." % fname)
                else:
                    try:
                        fd = UtilMgr.getTextLines(fname, verbose, retfd=True)
                    except SystemExit:
                        sys.exit(0)
                    except:
                        SysMgr.printErr("Fail to read %s\n" % fname, reason=True)
                        sys.exit(0)
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printOpenErr(fname)
                sys.exit(0)

            # verify log buffer #
            buf = []
            for idx, line in enumerate(fd):
                # decode line #
                try:
                    line = line.decode('utf-8')
                except:
                    pass

                # check system info #
                if end == -1:
                    buf.append(line)
                if not SysMgr.recordStatus:
                    if line.startswith(SysMgr.magicString):
                        if start == -1:
                            start = idx
                        elif end == -1:
                            end = idx
                            SysMgr.systemInfoBuffer = \
                                ''.join(buf[start+1:end])
                        continue

                # print-tgid option #
                m = re.match((\
                    r'^\s*(?P<comm>\S+)-(?P<thread>[0-9]+)\s+'
                    r'\(\s*(?P<tgid>\S+)\)\s+\[(?P<core>[0-9]+)\]\s+'
                    r'(?P<time>\S+):\s+(?P<func>\S+):(?P<etc>.+)'), line)
                if m:
                    d = m.groupdict()
                    SysMgr.startTime = d['time']
                    return float(d['time'])

                # record-tgid option #
                m = re.match((\
                    r'^\s*(?P<comm>\S+)-(?P<thread>[0-9]+)\s+'
                    r'\[(?P<core>[0-9]+)\]\s+\(\s*(?P<tgid>.+)\)\s+'
                    r'(?P<time>\S+):\s+(?P<func>\S+):(?P<etc>.+)'), line)
                if m:
                    d = m.groupdict()
                    SysMgr.startTime = d['time']
                    return float(d['time'])

                # no tgid option #
                m = re.match((\
                    r'^\s*(?P<comm>\S+)-(?P<thread>[0-9]+)\s+'
                    r'\[(?P<core>[0-9]+)\]\s+(?P<time>\S+):\s+'
                    r'(?P<func>\S+):(?P<etc>.+)'), line)
                if m:
                    d = m.groupdict()
                    SysMgr.tgidEnable = False
                    SysMgr.startTime = d['time']
                    return float(d['time'])

                # check other mode #
                if line.startswith('[Top '):
                    return 0

            # check record status #
            if SysMgr.isDrawMode():
                return 0
            elif not SysMgr.recordStatus:
                SysMgr.printErr(\
                    "Fail to read because there is no log")
                sys.exit(0)



    def saveBlkOpt(self, tid, comm, opt, major, minor, addr, size):
        def getBlkOptSize(size):
            idx = size.bit_length() - 1
            return 1 << idx

        def applyBlkOpt(targetTable, addr, size, blkSize, blkOffset):
            try:
                targetTable[did][0] += size
                targetTable[did][1] += 1
                if targetTable[did][2] == addr:
                    targetTable[did][3] += size
                    targetTable[did][4] += 1
                targetTable[did][2] = blkOffset
            except:
                sizeTable = {}
                targetTable[did] = [size, 1, blkOffset, size, 1, sizeTable]

            try:
                targetTable[did][5][blkSize] += 1
            except:
                targetTable[did][5][blkSize] = 1

        # apply filter #
        if SysMgr.isExceptTarget(tid, self.threadData, comm):
            return

        # total block info #
        readTable = self.blockTable[0]
        writeTable = self.blockTable[1]
        taskTable = self.blockTable[2]
        # [totalSize, totalCnt, lastBlk, seqSize, seqCnt, sizeTable] #

        addr = long(addr)
        size = long(size)

        if size > 1:
            blkOffset = addr + (size >> 9)
        else:
            # convert page to real size #
            size = SysMgr.pageSize
            blkOffset = addr + 1

        blkSize = getBlkOptSize(size)

        # revise real minor number by address #
        for did, val in SysMgr.savedMountTree.items():
            try:
                if did.split(':')[0] == major and \
                    val['start'] <= addr <= val['end']:
                    minor = did.split(':')[1]
                    break
            except:
                pass

        # make device id #
        did = '%s:%s' % (major, minor)

        if opt == 'R':
            targetTable = readTable
        elif opt == 'W':
            targetTable = writeTable
        else:
            SysMgr.printWarn(\
                "Fail to recognize block operation '%s'" % opt)
            return

        # apply total block info #
        applyBlkOpt(targetTable, addr, size, blkSize, blkOffset)

        if tid not in taskTable:
            taskTable[tid] = [{}, {}]

        if opt == 'R':
            targetTable = taskTable[tid][0]
        elif opt == 'W':
            targetTable = taskTable[tid][1]
        else:
            SysMgr.printWarn(\
                "Fail to recognize block operation '%s'" % opt)
            return

        # apply thread block info #
        applyBlkOpt(targetTable, addr, size, blkSize, blkOffset)



    def processIntervalData(self, time):
        if SysMgr.intervalEnable == 0:
            return

        intervalEnable = SysMgr.intervalEnable

        intervalCnt = float(SysMgr.intervalNow + intervalEnable)
        elapsed = float(time) - float(SysMgr.startTime)

        if not elapsed > intervalCnt and self.finishTime == '0':
            return

        SysMgr.intervalNow += intervalEnable

        # check change of all threads #
        for key, value in sorted(self.threadData.items(),\
            key=lambda e: e[1]['usage'], reverse=True):
            index = long(SysMgr.intervalNow / intervalEnable) - 1
            nextIndex = long(SysMgr.intervalNow / intervalEnable)

            try:
                self.intData[index]
            except:
                self.intData.append(dict())

            try:
                self.intData[index]['toTal']
            except:
                self.intData[index]['toTal'] = \
                    {'totalBr': long(0), 'totalBw': long(0), \
                    'totalMem': long(0), 'totalKmem': long(0)}

                # make total custom event list #
                if len(SysMgr.customEventList) > 0:
                    self.intData[index]['toTal']['customEvent'] = {}
                    for evt in SysMgr.customEventList:
                        self.intData[index]['toTal']['customEvent'][evt] = \
                            dict(self.init_eventData)

                # make user event list #
                if len(SysMgr.userEventList) > 0:
                    self.intData[index]['toTal']['userEvent'] = {}
                    for evt in SysMgr.userEventList:
                        self.intData[index]['toTal']['userEvent'][evt] = \
                            dict(self.init_eventData)

                # make kernel event list #
                if len(SysMgr.kernelEventList) > 0:
                    self.intData[index]['toTal']['kernelEvent'] = {}
                    for evt in SysMgr.kernelEventList:
                        self.intData[index]['toTal']['kernelEvent'][evt] = \
                            dict(self.init_eventData)

            # set thread in this interval #
            self.intData[index].setdefault(\
                key, dict(self.init_intData))

            # define thread alias in this interval #
            intervalThread = self.intData[index][key]

            # save start time in this interval #
            intervalThread['firstLogTime'] = float(time)

            # make interval list #
            try:
                self.intData[nextIndex]
            except:
                self.intData.append({})

            # set thread in next interval #
            self.intData[nextIndex].setdefault(\
                key, dict(self.init_intData))

            # save total usage in this interval #
            intervalThread['totalUsage'] = \
                float(self.threadData[key]['usage'])
            intervalThread['totalPreempted'] = \
                float(self.threadData[key]['cpuWait'])
            intervalThread['totalCoreSchedCnt'] = \
                long(self.threadData[key]['coreSchedCnt'])
            intervalThread['totalBrUsage'] = \
                long(self.threadData[key]['reqRdBlock'])
            intervalThread['totalBwUsage'] = \
                long(self.threadData[key]['writeBlock']) + \
                (long(self.threadData[key]['awriteBlock']) << 3)
            intervalThread['totalMemUsage'] = \
                long(self.threadData[key]['nrPages'])
            intervalThread['totalKmemUsage'] = \
                long(self.threadData[key]['remainKmem'])

            # add core time not calculated yet in this interval #
            for idx, val in self.lastTidPerCore.items():
                if self.threadData[val]['lastStatus'] == 'S':
                    # apply core off time #
                    coreId = '0[%s]' % idx
                    if self.threadData[coreId]['lastOff'] > 0:
                        diff = float(time) - self.threadData[coreId]['start']
                        self.threadData[coreId]['usage'] += diff
                        self.intData[index][coreId]['totalUsage'] += diff
                        self.threadData[coreId]['start'] = float(time)
                    continue

                intervalThread['totalUsage'] += \
                    (float(time) - float(self.threadData[val]['start']))

            # mark life flag #
            if self.threadData[key]['new'] != ' ':
                intervalThread['new'] = self.threadData[key]['new']
            if self.threadData[key]['die'] != ' ':
                intervalThread['die'] = self.threadData[key]['die']

            # initialize custom event list #
            if len(SysMgr.customEventList) > 0:
                intervalThread['customEvent'] = {}
                intervalThread['totalCustomEvent'] = {}
                for evt in SysMgr.customEventList:
                    intervalThread['customEvent'][evt] = \
                        dict(self.init_eventData)
                    intervalThread['totalCustomEvent'][evt] = \
                        dict(self.init_eventData)
                    try:
                        intervalThread['totalCustomEvent'][evt]['count'] = \
                            self.threadData[key]['customEvent'][evt]['count']
                    except:
                        pass

            # initialize user event list #
            if len(SysMgr.userEventList) > 0:
                intervalThread['userEvent'] = {}
                intervalThread['totalUserEvent'] = {}
                for evt in SysMgr.userEventList:
                    intervalThread['userEvent'][evt] = \
                        dict(self.init_eventData)
                    intervalThread['totalUserEvent'][evt] = \
                        dict(self.init_eventData)
                    try:
                        intervalThread['totalUserEvent'][evt]['count'] = \
                            self.threadData[key]['userEvent'][evt]['count']

                        intervalThread['totalUserEvent'][evt]['usage'] = \
                            self.threadData[key]['userEvent'][evt]['usage']
                    except:
                        pass

            # initialize kernel event list #
            if len(SysMgr.kernelEventList) > 0:
                intervalThread['kernelEvent'] = {}
                intervalThread['totalKernelEvent'] = {}
                for evt in SysMgr.kernelEventList:
                    intervalThread['kernelEvent'][evt] = \
                        dict(self.init_eventData)
                    intervalThread['totalKernelEvent'][evt] = \
                        dict(self.init_eventData)
                    try:
                        intervalThread['totalKernelEvent'][evt]['count'] = \
                            self.threadData[key]['kernelEvent'][evt]['count']

                        intervalThread['totalKernelEvent'][evt]['usage'] = \
                            self.threadData[key]['kernelEvent'][evt]['usage']
                    except:
                        pass

            # first interval #
            if SysMgr.intervalNow == intervalEnable:
                intervalThread['cpuUsage'] = \
                    float(self.threadData[key]['usage'])
                intervalThread['preempted'] = \
                    float(self.threadData[key]['cpuWait'])
                intervalThread['coreSchedCnt'] = \
                    float(self.threadData[key]['coreSchedCnt'])
                intervalThread['brUsage'] = \
                    long(self.threadData[key]['reqRdBlock'])
                intervalThread['bwUsage'] = \
                    long(self.threadData[key]['writeBlock']) + \
                    (long(self.threadData[key]['awriteBlock']) << 3)
                intervalThread['memUsage'] = \
                    long(self.threadData[key]['nrPages'])
                intervalThread['kmemUsage'] = \
                    long(self.threadData[key]['remainKmem'])

            # later intervals #
            else:
                try:
                    self.intData[index - 1][key]
                except:
                    self.intData[index - 1][key] = dict(self.init_intData)

                # define thread alias in previous interval #
                prevIntervalThread = self.intData[index - 1][key]

                # calculate resource usage in this interval #
                intervalThread['cpuUsage'] += \
                    intervalThread['totalUsage'] - \
                        prevIntervalThread['totalUsage']
                intervalThread['preempted'] += \
                    intervalThread['totalPreempted'] - \
                        prevIntervalThread['totalPreempted']
                intervalThread['coreSchedCnt'] = \
                    intervalThread['totalCoreSchedCnt'] - \
                        prevIntervalThread['totalCoreSchedCnt']
                intervalThread['brUsage'] = \
                    intervalThread['totalBrUsage'] - \
                        prevIntervalThread['totalBrUsage']
                intervalThread['bwUsage'] = \
                    intervalThread['totalBwUsage'] - \
                        prevIntervalThread['totalBwUsage']
                intervalThread['memUsage'] = \
                    intervalThread['totalMemUsage'] - \
                        prevIntervalThread['totalMemUsage']
                intervalThread['kmemUsage'] = \
                    intervalThread['totalKmemUsage'] - \
                        prevIntervalThread['totalKmemUsage']

            # calculate custom event usage in this interval #
            if 'totalCustomEvent' in intervalThread:
                for evt in list(intervalThread['totalCustomEvent'].keys()):
                    try:
                        intervalThread['customEvent'][evt]['count'] = \
                            intervalThread['totalCustomEvent'][evt]['count'] - \
                                prevIntervalThread['totalCustomEvent'][evt]['count']
                    except:
                        intervalThread['customEvent'][evt]['count'] = \
                            intervalThread['totalCustomEvent'][evt]['count']

                    self.intData[index]['toTal']['customEvent'][evt]['count'] += \
                        intervalThread['customEvent'][evt]['count']

            # calculate user event usage in this interval #
            if 'totalUserEvent' in intervalThread:
                for evt in list(intervalThread['totalUserEvent'].keys()):
                    try:
                        intervalThread['userEvent'][evt]['count'] = \
                            intervalThread['totalUserEvent'][evt]['count'] - \
                                prevIntervalThread['totalUserEvent'][evt]['count']

                        intervalThread['userEvent'][evt]['usage'] = \
                            intervalThread['totalUserEvent'][evt]['usage'] - \
                                prevIntervalThread['totalUserEvent'][evt]['usage']
                    except:
                        intervalThread['userEvent'][evt]['count'] = \
                            intervalThread['totalUserEvent'][evt]['count']

                        intervalThread['userEvent'][evt]['usage'] = \
                            intervalThread['totalUserEvent'][evt]['usage']

                    self.intData[index]['toTal']['userEvent'][evt]['count'] += \
                        intervalThread['userEvent'][evt]['count']

                    self.intData[index]['toTal']['userEvent'][evt]['usage'] += \
                        intervalThread['userEvent'][evt]['usage']

            # calculate kernel event usage in this interval #
            if 'totalKernelEvent' in intervalThread:
                for evt in list(intervalThread['totalKernelEvent'].keys()):
                    try:
                        intervalThread['kernelEvent'][evt]['count'] = \
                            intervalThread['totalKernelEvent'][evt]['count'] - \
                                prevIntervalThread['totalKernelEvent'][evt]['count']

                        intervalThread['kernelEvent'][evt]['usage'] = \
                            intervalThread['totalKernelEvent'][evt]['usage'] - \
                                prevIntervalThread['totalKernelEvent'][evt]['usage']
                    except:
                        intervalThread['kernelEvent'][evt]['count'] = \
                            intervalThread['totalKernelEvent'][evt]['count']

                        intervalThread['kernelEvent'][evt]['usage'] = \
                            intervalThread['totalKernelEvent'][evt]['usage']

                    self.intData[index]['toTal']['kernelEvent'][evt]['count'] += \
                        intervalThread['kernelEvent'][evt]['count']

                    self.intData[index]['toTal']['kernelEvent'][evt]['usage'] += \
                        intervalThread['kernelEvent'][evt]['usage']

            # fix CPU usage exceed this interval #
            self.thisInterval = intervalEnable
            if intervalThread['cpuUsage'] > intervalEnable or \
                self.finishTime != '0':
                ftime = float(self.intData[index - 1][key]['firstLogTime'])

                # first interval #
                if index == 0:
                    self.thisInterval = \
                        float(time) - float(SysMgr.startTime)
                # normal intervals #
                elif ftime > 0:
                    self.thisInterval = float(time) - ftime
                # long time running intervals #
                else:
                    for idx in range(index - 1, -1, -1):
                        if ftime > 0:
                            self.thisInterval = float(time) -ftime
                            break
                    if self.thisInterval != intervalEnable:
                        self.thisInterval = \
                            float(time) - float(SysMgr.startTime)

                # recalculate previous intervals if no context switching since profile start #
                remainTime = intervalThread['cpuUsage']
                if intervalThread['cpuUsage'] > self.thisInterval:
                    for idx in range(\
                        long(intervalThread['cpuUsage'] / intervalEnable), -1, -1):
                        try:
                            self.intData[idx][key]
                        except:
                            if not idx in self.intData:
                                continue
                            self.intData[idx][key] = dict(self.init_intData)
                        try:
                            self.intData[idx - 1][key]
                        except:
                            if not idx - 1 in self.intData:
                                continue
                            self.intData[idx - 1][key] = dict(self.init_intData)
                        prevIntervalData = self.intData[idx - 1][key]

                        # make previous intervals of core there was no context switching #
                        longRunCore = self.threadData[key]['longRunCore']
                        if longRunCore >= 0:
                            longRunCoreId = '0[%s]' % longRunCore
                            try:
                                self.intData[idx][longRunCoreId]
                            except:
                                self.intData[idx][longRunCoreId] = \
                                    dict(self.init_intData)

                        if remainTime >= intervalEnable:
                            remainTime = \
                                long(remainTime / intervalEnable) * intervalEnable
                            prevIntervalData['cpuUsage'] = intervalEnable
                            prevIntervalData['cpuPer'] = 100
                        else:
                            if prevIntervalData['cpuUsage'] > remainTime:
                                remainTime = prevIntervalData['cpuUsage']
                            else:
                                prevIntervalData['cpuUsage'] = remainTime
                            prevIntervalData['cpuPer'] = \
                                remainTime / intervalEnable * 100

                        remainTime -= intervalEnable

            # add remainter of CPU usage exceed interval in this interval to previous interval #
            if SysMgr.intervalNow - intervalEnable > 0 and \
                self.thisInterval > intervalEnable:
                diff = self.thisInterval - intervalEnable
                if prevIntervalThread['cpuUsage'] + diff > intervalEnable:
                    diff = intervalEnable - prevIntervalThread['cpuUsage']

                prevIntervalThread['cpuUsage'] += diff
                prevIntervalThread['cpuPer'] = \
                    prevIntervalThread['cpuUsage'] / intervalEnable * 100

            # calculate percentage of CPU usage of this thread in this interval #
            if self.thisInterval > 0:
                intervalThread['cpuPer'] = \
                    intervalThread['cpuUsage'] / self.thisInterval * 100
            else:
                intervalThread['cpuPer'] = long(0)

            # revise thread interval usage in DVFS system #
            if intervalThread['cpuPer'] > 100:
                intervalThread['cpuPer'] = 100
            elif intervalThread['cpuPer'] < 0:
                intervalThread['cpuPer'] = long(0)

            # fix preempted time exceed this interval #
            if intervalThread['preempted'] > intervalEnable:
                # recalculate previous intervals if no context switching since profile start #
                remainTime = intervalThread['preempted']
                if intervalThread['preempted'] > self.thisInterval:
                    for idx in range(index + 1, -1, -1):
                        try:
                            self.intData[idx][key]
                        except:
                            self.intData[idx][key] = dict(self.init_intData)
                        try:
                            self.intData[idx - 1][key]
                        except:
                            self.intData[idx - 1][key] = dict(self.init_intData)

                        if remainTime >= intervalEnable:
                            self.intData[idx - 1][key]['preempted'] = \
                                intervalEnable
                        else:
                            self.intData[idx - 1][key]['preempted'] += remainTime

                        remainTime -= intervalEnable
                        if remainTime <= 0:
                            break

            # calculate total block usage in this interval #
            self.intData[index]['toTal']['totalBr'] += \
                self.intData[index][key]['brUsage']
            self.intData[index]['toTal']['totalBw'] += \
                self.intData[index][key]['bwUsage']

            """
            calculate total memory usage in this interval \
            except for core(swapper) threads because its already calculated
            """
            if key[0:2] == '0[':
                continue

            self.intData[index]['toTal']['totalMem'] += \
                self.intData[index][key]['memUsage']
            self.intData[index]['toTal']['totalKmem'] += \
                self.intData[index][key]['kmemUsage']



    def initThreadData(self):
        self.threadData = {}
        self.irqData = {}
        self.ioData = {}
        self.reclaimData = {}
        self.pageTable = {}
        self.kmemTable = {}
        self.blockTable = [{}, {}, {}]
        self.moduleData = []
        self.intData = []
        self.depData = []
        self.sigData = []
        self.lockTable = {}
        self.flockData = []
        self.futexData = []
        self.customEventData = []
        self.userEventData = []
        self.kernelEventData = []
        self.syscallData = []
        self.lastJob = {}
        self.preemptData = []
        self.suspendData = []
        self.markData = []
        self.consoleData = []

        self.customEventInfo = {}
        self.userEventInfo = {}
        self.kernelEventInfo = {}

        self.customInfo = {}
        self.userInfo = {}
        self.kernelInfo = {}

        self.stopFlag = False
        self.totalTime = long(0)
        self.totalTimeOld = long(0)
        self.cxtSwitch = long(0)
        self.nrNewTask = long(0)
        self.thisInterval = long(0)



    def handleUserEvent(self, event, time):
        # initialize ThreadAnalyzer data #
        if event == 'START':
            self.initThreadData()

            SysMgr.startTime = time

            # initialize preempt thread list #
            if SysMgr.preemptGroup:
                for index in SysMgr.preemptGroup:
                    self.preemptData.append(\
                        [False, {}, float(0), 0, float(0)])
        # finish data processing #
        elif event == 'STOP':
            SysMgr.totalLine = SysMgr.curLine
            self.finishTime = time
            self.stopFlag = True
        # restart data processing #
        elif event == 'RESTART':
            self.threadDataOld = self.threadData
            self.irqDataOld = self.irqData
            self.ioDataOld = self.ioData
            self.reclaimDataOld = self.reclaimData
            self.pageTableOld = self.pageTable
            self.kmemTableOld = self.kmemTable
            self.blockTableOld = self.blockTable
            self.moduleDataOld = self.moduleData
            self.intDataOld = self.intData
            self.depDataOld = self.depData
            self.sigDataOld = self.sigData
            self.lockTableOld = self.lockTable
            self.flockDataOld = self.flockData
            self.customEventDataOld = self.customEventData
            self.userEventDataOld = self.userEventData
            self.kernelEventDataOld = self.kernelEventData
            self.syscallDataOld = self.syscallData
            self.preemptDataOld = self.preemptData
            self.suspendDataOld = self.suspendData
            self.markDataOld = self.markData
            self.consoleDataOld = self.consoleData

            self.totalTimeOld = \
                round(float(time) - float(SysMgr.startTime), 7)

            self.initThreadData()

            SysMgr.startTime = time
        # save mark event #
        elif event == 'MARK':
            self.markData.append(time)

        # add event #
        EventAnalyzer.addEvent(time, event)



    def parse(self, string):
        def printEventWarning(func):
            SysMgr.printWarn(\
                "Fail to recognize '%s' event at line %d" % \
                (func, SysMgr.curLine))

        SysMgr.curLine += 1

        m = SysMgr.getTraceItem(string)
        if not m:
            # handle modified type of event #
            m = SysMgr.getTraceItem(string)
            if m:
                d = m.groupdict()
                comm = d['comm']
                core = str(long(d['core']))
                func = d['func']
                etc = d['etc']
                time = d['time']

                if 'tracing_mark_write' in func:
                    m = re.match(r'^.+EVENT_(?P<event>\S+)', etc)
                    if m:
                        d = m.groupdict()

                        self.handleUserEvent(d['event'], time)
            return

        # get thread info #
        d = m.groupdict()
        comm = d['comm']
        core = str(long(d['core']))
        if d['func'][-1] == ':':
            func = d['func'][:-1]
        else:
            func = d['func']
        etc = d['etc']
        time = d['time']

        SysMgr.logSize += len(string)

        if len(SysMgr.perCoreList) > 0 and \
            long(core) not in SysMgr.perCoreList and \
            (func != "console" and \
            func != "tracing_mark_write"):
            return time
        elif SysMgr.countEnable and \
            SysMgr.repeatCount * SysMgr.intervalEnable <= \
                float(time) - float(SysMgr.startTime):
            self.stopFlag = True
            return time

        self.lastCore = core
        self.lastEvent = func

        if SysMgr.maxCore < long(core):
            SysMgr.maxCore = long(core)

        # make core id #
        coreId = '0[%s]' % core
        if long(d['thread']) == 0:
            thread = coreId
            comm = comm.replace("<idle>", "swapper/" + core)
        else:
            thread = d['thread']

        # make core thread entity in advance for total irq per core #
        try:
            self.threadData[coreId]
        except:
            SysMgr.nrCore += 1
            self.threadData[coreId] = dict(self.init_threadData)
            self.threadData[coreId]['comm'] = "swapper/%s" % core

        # make thread entity #
        self.threadData.setdefault(thread, dict(self.init_threadData))
        if comm[0] != '<':
            self.threadData[thread]['comm'] = comm

        # set tgid #
        try:
            if d['tgid'] != '-----':
                self.threadData[thread]['tgid'] = d['tgid']
            else:
                raise Exception()
        except:
            try:
                self.threadData[thread]['tgid'] = \
                    SysMgr.savedProcTree[thread]
            except:
                pass

        # calculate usage of threads had been running longer than periodic interval #
        if SysMgr.intervalEnable > 0:
            for key, value in sorted(self.lastTidPerCore.items()):
                try:
                    coreId = '0[%s]' % key
                    tid = self.lastTidPerCore[key]

                    # check CPU idle status #
                    if self.threadData[coreId]['lastStatus'] == 'R':
                        self.threadData[coreId]['usage'] += \
                            float(time) - self.threadData[coreId]['start']
                        self.threadData[coreId]['start'] = float(time)
                        continue

                    # check status of thread running on this core #
                    if self.threadData[tid]['lastStatus'] != 'R':
                        continue

                    usage = float(time) - float(self.threadData[tid]['start'])
                    allTime = float(time) - float(SysMgr.startTime)
                    if usage > allTime:
                        usage = allTime

                    self.threadData[tid]['usage'] += usage
                    self.threadData[tid]['start'] = float(time)
                except:
                    continue

        # calculate usage of threads in interval #
        self.processIntervalData(time)

        # define flag for special events #
        handleSpecialEvents = False

        if func == "sched_switch":
            m = re.match((\
                r'^\s*prev_comm=(?P<prev_comm>.*)\s+'
                r'prev_pid=(?P<prev_pid>[0-9]+)\s+'
                r'prev_prio=(?P<prev_prio>\S+)\s+'
                r'prev_state=(?P<prev_state>\S+)\s+==>\s+'
                r'next_comm=(?P<next_comm>.*)\s+'
                r'next_pid=(?P<next_pid>[0-9]+)\s+'
                r'next_prio=(?P<next_prio>\S+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            SysMgr.cpuEnable = True

            self.cxtSwitch += 1

            '''
            /* states in TASK_REPORT: */
            "R (running)",      /* 0x00 */
            "S (sleeping)",     /* 0x01 */
            "D (disk sleep)",   /* 0x02 */
            "T (stopped)",      /* 0x04 */
            "t (tracing stop)", /* 0x08 */
            "X (dead)",     /* 0x10 */
            "Z (zombie)",       /* 0x20 */
            "P (parked)",       /* 0x40 */

            /* states beyond TASK_REPORT: */
            "I (idle)",     /* 0x80 */
            '''

            prev_comm = d['prev_comm']
            prev_pid = d['prev_pid']
            prev_id = prev_pid

            coreId = '0[%s]' % core

            if long(d['prev_pid']) == 0:
                prev_id = coreId
            else:
                prev_id = prev_pid

            next_comm = d['next_comm']
            next_pid = d['next_pid']

            if long(d['next_pid']) == 0:
                next_id = coreId
            else:
                next_id = next_pid

            # check CPU wakeup #
            if self.threadData[coreId]['lastOff'] > 0:
                diff = float(time) - self.threadData[coreId]['lastOff']
                self.threadData[coreId]['offTime'] += diff
                self.threadData[coreId]['lastOff'] = long(0)

            # initialize thread data #
            self.threadData.setdefault(prev_id, dict(self.init_threadData))
            self.threadData.setdefault(next_id, dict(self.init_threadData))

            # initialize core data #
            try:
                self.threadData[coreId]
            except:
                self.threadData[coreId] = dict(self.init_threadData)
                self.threadData[coreId]['comm'] = 'swapper/%s' % core

            if self.wakeupData['valid'] > 0 and \
                self.wakeupData['tid'] == prev_id:
                self.wakeupData['valid'] -= 1

            # update comm #
            self.threadData[prev_id]['comm'] = prev_comm
            self.threadData[next_id]['comm'] = next_comm

            # update anonymous comm #
            if self.threadData[prev_id]['comm'] == '<...>':
                self.threadData[prev_id]['comm'] = prev_comm
            if self.threadData[next_id]['comm'] == '<...>':
                self.threadData[next_id]['comm'] = next_comm

            # check event loss #
            if self.threadData[prev_id]['lastStatus'] != 'R' and \
                self.threadData[coreId]['coreSchedCnt'] > 0:
                self.threadData[prev_id]['start'] = float(time)

            # write current time #
            self.threadData[prev_id]['stop'] = float(time)
            self.threadData[next_id]['start'] = float(time)
            self.threadData[next_id]['waitStartAsParent'] = float(0)

            # update priority of thread to highest one #
            if self.threadData[prev_id]['pri'] == '?' or \
                long(self.threadData[prev_id]['pri']) > long(d['prev_prio']):
                self.threadData[prev_id]['pri'] = d['prev_prio']
            if self.threadData[next_id]['pri'] == '?' or \
                long(self.threadData[next_id]['pri']) > long(d['next_prio']):
                self.threadData[next_id]['pri'] = d['next_prio']

            # update CPU time by futex #
            if self.threadData[prev_id]['ftxEnter'] > 0:
                cstart = self.threadData[prev_id]['start']
                fstart = self.threadData[prev_id]['ftxEnter']

                if cstart > fstart:
                    tstart = cstart
                else:
                    tstart = fstart

                stime = float(time) - tstart
                self.threadData[prev_id]['ftxProcess'] += stime
                self.threadData[prev_id]['ftxBlock'] = float(time)
                self.threadData[prev_id]['ftxBlockCnt'] += 1

                opt = '{0:^24}'.format('BLOCK')
                otype = '{0:<10}'.format('ENT')
                stime = '%.6f' % stime
                self.futexData.append(\
                    [prev_id, time, core, opt, otype, stime, '', '', ''])

            # save block time with lock by futex #
            try:
                if len(self.threadData[prev_id]['futexObj']) > 0:
                    self.threadData[prev_id]['ftxLBlock'] = float(time)
                    self.threadData[prev_id]['ftxLSwitch'] += 1

                    # remove previous BLOCK enter event #
                    if len(self.futexData) > 0 and \
                        self.futexData[-1][1] == time:
                        del self.futexData[-1]

                    opt = '{0:^24}'.format('LOCK_BLOCK')
                    otype = '{0:<10}'.format('ENT')
                    locks = ', '.join(self.threadData[prev_id]['futexObj'])
                    self.futexData.append(\
                        [prev_id, time, core, opt, otype, \
                        '', locks, '', ''])
            except:
                pass

            # update total block time with lock by futex #
            if self.threadData[next_id]['ftxLBlock'] > 0:
                cstop = self.threadData[next_id]['ftxLBlock']
                btime = float(time) - cstop
                self.threadData[next_id]['ftxLBlockTotal'] += btime
                self.threadData[next_id]['ftxLBlock'] = long(0)

                opt = '{0:^24}'.format('LOCK_BLOCK')
                otype = '{0:>10}'.format('RET')
                try:
                    locks = ', '.join(self.threadData[next_id]['futexObj'])
                except:
                    locks = ''
                btime = '%.6f' % btime
                self.futexData.append(\
                    [next_id, time, core, opt, otype, \
                    btime, locks, '', ''])

            # save block time by futex #
            if self.threadData[next_id]['ftxBlock'] > 0:
                cstop = self.threadData[next_id]['ftxBlock']
                btime = float(time) - cstop
                self.threadData[next_id]['ftxBlockTotal'] += btime
                self.threadData[next_id]['ftxBlock'] = long(0)

                opt = '{0:^24}'.format('BLOCK')
                otype = '{0:>10}'.format('RET')
                btime = '%.6f' % btime
                self.futexData.append(\
                    [next_id, time, core, opt, otype, \
                    btime, '', '', ''])

            # calculate running time of previous thread #
            diff = long(0)
            if self.threadData[prev_id]['start'] == 0:
                ''' calculate running time of previous thread started
                    before starting to profile '''
                if self.threadData[coreId]['coreSchedCnt'] == 0:
                    diff = float(time) - float(SysMgr.startTime)
                    self.threadData[prev_id]['usage'] = diff
                # it is possible that log was loss #
                else:
                    pass
            else:
                diff = self.threadData[prev_id]['stop'] - \
                    self.threadData[prev_id]['start']
                if diff >= 0:
                    self.threadData[prev_id]['usage'] += diff

                    if self.threadData[prev_id]['maxRuntime'] < diff:
                        self.threadData[prev_id]['maxRuntime'] = diff
                else:
                    SysMgr.printWarn(\
                        "usage time of %s(%s) is negative at line %d" % \
                        (prev_comm, prev_id, SysMgr.curLine))

            if diff > long(SysMgr.intervalEnable):
                self.threadData[prev_id]['longRunCore'] = long(core)

            # update core info #
            self.threadData[coreId]['coreSchedCnt'] += 1
            self.lastTidPerCore[core] = next_id

            # calculate preempted time of threads blocked #
            if SysMgr.preemptGroup:
                for value in SysMgr.preemptGroup:
                    index = SysMgr.preemptGroup.index(value)
                    if self.preemptData[index][0] and \
                        self.preemptData[index][3] == core:
                        try:
                            self.preemptData[index][1][prev_id]
                        except:
                            self.preemptData[index][1][prev_id] = \
                                dict(self.init_preemptData)

                        self.preemptData[index][1][prev_id]['usage'] +=  \
                            self.threadData[prev_id]['stop'] - \
                            self.threadData[prev_id]['start']
                        self.preemptData[index][4] += \
                            self.threadData[prev_id]['stop'] - \
                            self.threadData[prev_id]['start']

            # set sched status #
            if d['prev_state'][0] == 'R':
                # except for core sched event #
                if prev_id != coreId:
                    self.threadData[prev_id]['preempted'] += 1
                    self.threadData[coreId]['preempted'] += 1

                # except for core sched event #
                if next_id != coreId:
                    self.threadData[next_id]['preemption'] += 1
                    self.threadData[coreId]['preemption'] += 1

                self.threadData[prev_id]['lastStatus'] = 'P'

                if SysMgr.preemptGroup:
                    # enable preempted bit #
                    try:
                        index = SysMgr.preemptGroup.index(prev_id)
                    except:
                        index = -1

                    if index >= 0:
                        self.preemptData[index][0] = True
                        try:
                            self.preemptData[index][1][next_id]
                        except:
                            self.preemptData[index][1][next_id] = \
                                dict(self.init_preemptData)

                        self.preemptData[index][2] = float(time)
                        self.preemptData[index][3] = core

            elif d['prev_state'][0] == 'S' or \
                d['prev_state'][0] == 'D' or \
                d['prev_state'][0] == 't' or \
                d['prev_state'][0] == 'T':
                # except for core sched event #
                if prev_id != coreId:
                    self.threadData[prev_id]['yield'] += 1
                    self.threadData[coreId]['yield'] += 1

                self.threadData[prev_id]['stop'] = long(0)
                self.threadData[prev_id]['lastStatus'] = 'S'

            else:
                self.threadData[prev_id]['stop'] = long(0)
                self.threadData[prev_id]['lastStatus'] = d['prev_state'][0]

            # calculate preempted time of next thread #
            if self.threadData[next_id]['stop'] == 0:
                # no stop time of next thread because of some reasons #
                self.threadData[next_id]['stop'] = long(0)

                # calculate sched latency of next thread #
                if self.threadData[next_id]['schedReady'] > 0:
                    self.threadData[next_id]['schedLatency'] += \
                        (float(time) - self.threadData[next_id]['schedReady'])
                    self.threadData[coreId]['schedLatency'] += \
                        (float(time) - self.threadData[next_id]['schedReady'])
                    self.threadData[next_id]['schedReady'] = long(0)
            # set sched status of next thread #
            elif self.threadData[next_id]['lastStatus'] == 'P':
                preemptedTime = \
                    self.threadData[next_id]['start'] - \
                    self.threadData[next_id]['stop']

                if preemptedTime >= 0:
                    self.threadData[next_id]['cpuWait'] += preemptedTime
                else:
                    SysMgr.printWarn(\
                        "preempted time of %s(%d) is negative at line %d" % \
                        (next_comm, next_id, SysMgr.curLine))

                if preemptedTime > self.threadData[next_id]['maxPreempted']:
                    self.threadData[next_id]['maxPreempted'] = preemptedTime

                try:
                    nextIdx = SysMgr.preemptGroup.index(next_id)
                    self.preemptData[nextIdx][0] = False
                except:
                    pass

            self.threadData[next_id]['lastStatus'] = 'R'

        elif func == "irq_handler_entry":
            m = re.match(r'^\s*irq=(?P<irq>[0-9]+)\s+name=(?P<name>\S+)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            irqId = 'irq/%s' % (d['irq'])

            # make irq list #
            try:
                self.irqData[irqId]
            except:
                self.irqData[irqId] = dict(self.init_irqData)
                self.irqData[irqId]['name'] = {}

            self.irqData[irqId]['name'].setdefault(d['name'], 0)

            # make per-thread irq list #
            self.threadData[thread].setdefault('irqList', dict())
            self.threadData[thread]['irqList'].setdefault(\
                irqId, dict(self.init_irqData))
            self.threadData[thread]['irqList'][irqId]['name'] = d['name']

            # save irq period per thread #
            if self.threadData[thread]['irqList'][irqId]['start'] > 0:
                diff = float(time) - self.threadData[thread]['irqList'][irqId]['start']
                if diff > self.threadData[thread]['irqList'][irqId]['maxPeriod'] or \
                    self.threadData[thread]['irqList'][irqId]['maxPeriod'] <= 0:
                    self.threadData[thread]['irqList'][irqId]['maxPeriod'] = diff
                if diff < self.threadData[thread]['irqList'][irqId]['minPeriod'] or \
                    self.threadData[thread]['irqList'][irqId]['minPeriod'] <= 0:
                    self.threadData[thread]['irqList'][irqId]['minPeriod'] = diff

            # save irq period #
            if self.irqData[irqId]['start'] > 0:
                diff = float(time) - self.irqData[irqId]['start']
                if diff > self.irqData[irqId]['maxPeriod'] or \
                    self.irqData[irqId]['maxPeriod'] <= 0:
                    self.irqData[irqId]['maxPeriod'] = diff
                if diff < self.irqData[irqId]['minPeriod'] or \
                    self.irqData[irqId]['minPeriod'] <= 0:
                    self.irqData[irqId]['minPeriod'] = diff

            self.irqData[irqId]['start'] = float(time)
            self.irqData[irqId]['count'] += 1
            self.threadData[thread]['irqList'][irqId]['start'] = float(time)
            self.threadData[thread]['irqList'][irqId]['count'] += 1

        elif func == "irq_handler_exit":
            m = re.match(r'^\s*irq=(?P<irq>[0-9]+)\s+ret=(?P<return>\S+)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            irqId = 'irq/%s' % (d['irq'])

            # make list #
            try:
                self.irqData[irqId]
                self.threadData[thread]['irqList'][irqId]
            except:
                return time

            if self.threadData[thread]['irqList'][irqId]['start'] > 0:
                # save softirq usage #
                diff = float(time) - \
                    self.threadData[thread]['irqList'][irqId]['start']
                self.threadData[thread]['irqList'][irqId]['usage'] += diff
                self.threadData[thread]['irq'] += diff
                self.irqData[irqId]['usage'] += diff

                # add CPU usage of this thread to core usage #
                if coreId != thread:
                    self.threadData[coreId]['irq'] += diff

                # save softirq period per thread #
                if diff > self.threadData[thread]['irqList'][irqId]['max'] or \
                    self.threadData[thread]['irqList'][irqId]['max'] <= 0:
                    self.threadData[thread]['irqList'][irqId]['max'] = diff
                if diff < self.threadData[thread]['irqList'][irqId]['min'] or \
                    self.threadData[thread]['irqList'][irqId]['min'] <= 0:
                    self.threadData[thread]['irqList'][irqId]['min'] = diff

                self.threadData[thread]['irqList'][irqId]['start'] = long(0)

            if self.irqData[irqId]['start'] > 0:
                diff = float(time) - self.irqData[irqId]['start']
                # save softirq period #
                if diff > self.irqData[irqId]['max'] or \
                    self.irqData[irqId]['max'] <= 0:
                    self.irqData[irqId]['max'] = diff
                if diff < self.irqData[irqId]['min'] or \
                    self.irqData[irqId]['min'] <= 0:
                    self.irqData[irqId]['min'] = diff

                self.irqData[irqId]['start'] = long(0)

        elif func == "softirq_entry":
            m = re.match(\
                r'^\s*vec=(?P<vector>[0-9]+)\s+\[action=(?P<action>\S+)\]', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            irqId = 'softirq/%s' % (d['vector'])

            # make irq list #
            try:
                self.irqData[irqId]
            except:
                self.irqData[irqId] = dict(self.init_irqData)
                self.irqData[irqId]['name'] = {}

            self.irqData[irqId]['name'].setdefault(d['action'], 0)

            # make per-thread irq list #
            try:
                self.threadData[thread]['irqList'][irqId]
            except:
                self.threadData[thread]['irqList'] = {}
            try:
                self.threadData[thread]['irqList'][irqId]
            except:
                self.threadData[thread]['irqList'][irqId] = dict(self.init_irqData)
                self.threadData[thread]['irqList'][irqId]['name'] = d['action']

            # save softirq period per thread #
            if self.threadData[thread]['irqList'][irqId]['start'] > 0:
                diff = float(time) - \
                    self.threadData[thread]['irqList'][irqId]['start']
                if diff > self.threadData[thread]['irqList'][irqId]['maxPeriod'] or \
                    self.threadData[thread]['irqList'][irqId]['maxPeriod'] <= 0:
                    self.threadData[thread]['irqList'][irqId]['maxPeriod'] = diff
                if diff < self.threadData[thread]['irqList'][irqId]['minPeriod'] or \
                    self.threadData[thread]['irqList'][irqId]['minPeriod'] <= 0:
                    self.threadData[thread]['irqList'][irqId]['minPeriod'] = diff

            # save softirq period #
            if self.irqData[irqId]['start'] > 0:
                diff = float(time) - self.irqData[irqId]['start']
                if diff > self.irqData[irqId]['maxPeriod'] or \
                    self.irqData[irqId]['maxPeriod'] <= 0:
                    self.irqData[irqId]['maxPeriod'] = diff
                if diff < self.irqData[irqId]['minPeriod'] or \
                    self.irqData[irqId]['minPeriod'] <= 0:
                    self.irqData[irqId]['minPeriod'] = diff

            self.irqData[irqId]['start'] = float(time)
            self.irqData[irqId]['count'] += 1
            self.threadData[thread]['irqList'][irqId]['start'] = float(time)
            self.threadData[thread]['irqList'][irqId]['count'] += 1

        elif func == "softirq_exit":
            m = re.match(\
                r'^\s*vec=(?P<vector>[0-9]+)\s+\[action=(?P<action>\S+)\]', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            irqId = 'softirq/%s' % (d['vector'])

            # make list #
            try:
                self.irqData[irqId]
                self.threadData[thread]['irqList'][irqId]
            except:
                return time

            if self.threadData[thread]['irqList'][irqId]['start'] > 0:
                # save softirq usage #
                diff = float(time) - \
                    self.threadData[thread]['irqList'][irqId]['start']
                self.threadData[thread]['irqList'][irqId]['usage'] += diff
                self.threadData[thread]['irq'] += diff
                self.irqData[irqId]['usage'] += diff

                # add CPU usage of this thread to core usage #
                if coreId != thread:
                    self.threadData[coreId]['irq'] += diff

                # save softirq period per thread #
                if diff > self.threadData[thread]['irqList'][irqId]['max'] or \
                    self.threadData[thread]['irqList'][irqId]['max'] <= 0:
                    self.threadData[thread]['irqList'][irqId]['max'] = diff
                if diff < self.threadData[thread]['irqList'][irqId]['min'] or \
                    self.threadData[thread]['irqList'][irqId]['min'] <= 0:
                    self.threadData[thread]['irqList'][irqId]['min'] = diff

                self.threadData[thread]['irqList'][irqId]['start'] = long(0)

            if self.irqData[irqId]['start'] > 0:
                diff = float(time) - self.irqData[irqId]['start']
                # save softirq period #
                if diff > self.irqData[irqId]['max'] or \
                    self.irqData[irqId]['max'] <= 0:
                    self.irqData[irqId]['max'] = diff
                if diff < self.irqData[irqId]['min'] or \
                    self.irqData[irqId]['min'] <= 0:
                    self.irqData[irqId]['min'] = diff

                self.irqData[irqId]['start'] = long(0)

        elif func == "sched_migrate_task":
            m = re.match((\
                r'^\s*comm=(?P<comm>.*)\s+pid=(?P<pid>[0-9]+)\s+'
                r'prio=(?P<prio>[0-9]+)\s+orig_cpu=(?P<orig_cpu>[0-9]+)\s+'
                r'dest_cpu=(?P<dest_cpu>[0-9]+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            pid = d['pid']

            self.threadData.setdefault(pid, dict(self.init_threadData))
            self.threadData[pid]['comm'] = d['comm']

            self.threadData[pid]['migrate'] += 1
            self.threadData[coreId]['migrate'] += 1

            # update core data for preempted info #
            if SysMgr.preemptGroup:
                try:
                    index = SysMgr.preemptGroup.index(thread)
                except:
                    index = -1

                if index >= 0:
                    self.preemptData[index][3] = core

        elif func == "mm_page_alloc":
            m = re.match((\
                r'^\s*page=\s*(?P<page>\S+)\s+pfn=(?P<pfn>[0-9]+)\s+'
                r'order=(?P<order>[0-9]+)\s+'
                r'migratetype=(?P<mt>[0-9]+)\s+gfp_flags=(?P<flags>\S+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            SysMgr.memEnable = True

            # check whether it is huge page #
            if d['page'] == '(null)':
                page = 'huge'
            else:
                page = d['page']

            pfn = long(d['pfn'])
            flags = d['flags']
            order = long(d['order'])

            self.threadData[thread]['nrPages'] += pow(2, order)
            self.threadData[coreId]['nrPages'] += pow(2, order)

            if 'NOFS' in flags or \
                'GFP_WRITE' in flags or \
                '0x1000000' in flags:
                pageType = 'CACHE'
                self.threadData[thread]['cachePages'] += pow(2, order)
                self.threadData[coreId]['cachePages'] += pow(2, order)
            elif 'USER' in flags:
                pageType = 'USER'
                self.threadData[thread]['userPages'] += pow(2, order)
                self.threadData[coreId]['userPages'] += pow(2, order)
            else:
                pageType = 'KERNEL'
                self.threadData[thread]['kernelPages'] += pow(2, order)
                self.threadData[coreId]['kernelPages'] += pow(2, order)

            # make PTE in page table #
            for cnt in range(0, pow(2, order)):
                pfnv = pfn + cnt

                try:
                    # this allocated page is not freed #
                    if self.pageTable[pfnv] == {}:
                        raise Exception()
                    else:
                        self.threadData[thread]['nrPages'] -= 1
                        self.threadData[coreId]['nrPages'] -= 1
                except:
                    self.pageTable[pfnv] = dict(self.init_pageData)

                self.pageTable[pfnv]['tid'] = thread
                self.pageTable[pfnv]['page'] = page
                self.pageTable[pfnv]['flags'] = flags
                self.pageTable[pfnv]['type'] = pageType
                self.pageTable[pfnv]['time'] = time

        elif func == "mm_page_free" or func == "mm_page_free_direct":
            m = re.match((\
                r'^\s*page=(?P<page>\S+)\s+pfn=(?P<pfn>[0-9]+)'
                r'\s+order=(?P<order>[0-9]+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            SysMgr.memEnable = True

            page = d['page']
            pfn = long(d['pfn'])
            order = long(d['order'])

            for cnt in range(0, pow(2, order)):
                pfnv = pfn + cnt

                try:
                    owner = self.pageTable[pfnv]['tid']
                    self.threadData[owner]['nrPages'] -= 1
                    self.threadData[coreId]['nrPages'] -= 1

                    if thread != owner:
                        self.threadData[owner]['reclaimedPages'] += 1
                        self.threadData[coreId]['reclaimedPages'] += 1

                    if self.pageTable[pfnv]['type'] == 'CACHE':
                        self.threadData[owner]['cachePages'] -= 1
                        self.threadData[coreId]['cachePages'] -= 1
                    elif self.pageTable[pfnv]['type'] == 'USER':
                        self.threadData[owner]['userPages'] -= 1
                        self.threadData[coreId]['userPages'] -= 1
                    elif self.pageTable[pfnv]['type'] == 'KERNEL':
                        self.threadData[owner]['kernelPages'] -= 1
                        self.threadData[coreId]['kernelPages'] -= 1

                    self.pageTable.pop(pfnv)
                except:
                    # this page is allocated before starting profile #
                    self.threadData[thread]['anonReclaimedPages'] += 1
                    self.threadData[coreId]['anonReclaimedPages'] += 1

        elif func == "mm_filemap_delete_from_page_cache":
            m = re.match((\
                r'^\s*dev (?P<major>[0-9]+):(?P<minor>[0-9]+) .+'
                r'page=(?P<page>\S+)\s+pfn=(?P<pfn>[0-9]+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            SysMgr.memEnable = True

            pfn = long(d['pfn'])

            try:
                owner = self.pageTable[pfn]['tid']

                # attribute of page is changed to file #
                if self.pageTable[pfn]['type'] == 'USER':
                    self.threadData[owner]['userPages'] -= 1
                    self.threadData[coreId]['userPages'] -= 1
                    self.threadData[owner]['cachePages'] += 1
                    self.threadData[coreId]['cachePages'] += 1
                elif self.pageTable[pfn]['type'] == 'KERNEL':
                    self.threadData[owner]['kernelPages'] -= 1
                    self.threadData[coreId]['kernelPages'] -= 1
                    self.threadData[owner]['cachePages'] += 1
                    self.threadData[coreId]['cachePages'] += 1

                self.pageTable[pfn]['type'] = 'CACHE'
            except:
                return time

        elif func == "kmalloc":
            m = re.match((\
                r'^\s*call_site=(?P<caller>\S+)\s+ptr=(?P<ptr>\S+)\s+'
                r'bytes_req=(?P<req>[0-9]+)\s+'
                r'bytes_alloc=(?P<alloc>[0-9]+)\s+'
                r'gfp_flags=(?P<flags>\S+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            SysMgr.memEnable = True

            caller = d['caller']
            ptr = d['ptr']
            req = long(d['req'])
            alloc = long(d['alloc'])

            self.kmemTable.setdefault(ptr, dict(self.init_kmallocData))

            self.kmemTable[ptr]['tid'] = thread
            self.kmemTable[ptr]['caller'] = caller
            self.kmemTable[ptr]['req'] = req
            self.kmemTable[ptr]['alloc'] = alloc
            self.kmemTable[ptr]['waste'] = alloc - req
            self.kmemTable[ptr]['core'] = coreId

            self.threadData[thread]['remainKmem'] += alloc
            self.threadData[thread]['wasteKmem'] += alloc - req
            self.threadData[coreId]['remainKmem'] += alloc
            self.threadData[coreId]['wasteKmem'] += alloc - req

        elif func == "kfree":
            m = re.match(\
                r'^\s*call_site=(?P<caller>\S+)\s+ptr=\s*(?P<ptr>\S+)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            SysMgr.memEnable = True

            caller = d['caller']
            ptr = d['ptr']

            try:
                pageObj = self.kmemTable[ptr]
                self.threadData[pageObj['tid']]['remainKmem'] -= \
                    pageObj['alloc']
                self.threadData[pageObj['core']]['remainKmem'] -= \
                    pageObj['alloc']
                self.threadData[pageObj['tid']]['wasteKmem'] -= \
                    pageObj['waste']
                self.threadData[pageObj['core']]['wasteKmem'] -= \
                    pageObj['waste']

                self.kmemTable.pop(ptr)
            except:
                '''
                this allocated object is not logged or \
                this object is allocated before starting profile
                '''
                return time

        elif func == "sched_wakeup" or func == "sched_wakeup_new":
            m = re.match((\
                r'^\s*comm=(?P<comm>.*)\s+pid=(?P<pid>[0-9]+)\s+'
                r'prio=(?P<prio>[0-9]+)\s+'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            target_comm = d['comm']
            pid = d['pid']

            # skip self-wakeup #
            if thread == pid:
                return time

            self.threadData.setdefault(pid, dict(self.init_threadData))
            self.threadData[pid]['comm'] = target_comm
            self.threadData[pid]['schedReady'] = float(time)

            if self.wakeupData['tid'] == '0':
                self.wakeupData['time'] = \
                    float(time) - float(SysMgr.startTime)
            elif thread[0] == '0' or pid == '0':
                return time
            elif self.wakeupData['valid'] > 0 and \
                (self.wakeupData['from'] != self.wakeupData['tid'] or \
                self.wakeupData['to'] != pid):
                if self.wakeupData['valid'] == 1 and \
                    self.wakeupData['corrupt'] == '0':
                    try:
                        kicker = self.threadData[self.wakeupData['tid']]['comm']
                    except:
                        kicker = "NULL"

                    kicker_pid = self.wakeupData['tid']
                else:
                    kicker = self.threadData[thread]['comm']
                    kicker_pid = thread

                ntime = round(float(time) - \
                    float(SysMgr.startTime), 7)
                self.depData.append(\
                    "\t%.3f/%.3f \t%16s(%4s) -> %16s(%4s) \t%s" % \
                    (ntime, round(ntime - float(self.wakeupData['time']), 7), \
                    kicker, kicker_pid, target_comm, pid, "kick"))

                self.wakeupData['time'] = \
                    float(time) - float(SysMgr.startTime)
                self.wakeupData['from'] = self.wakeupData['tid']
                self.wakeupData['to'] = pid

        elif func == "sys_enter":
            m = re.match(r'^\s*NR (?P<nr>[0-9]+) (?P<args>.+)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            nr = long(d['nr'])
            args = d['args']
            td = self.threadData[thread]

            # apply thread filter #
            if SysMgr.isExceptTarget(thread, self.threadData):
                return time

            # update futex lock stat #
            if nr == ConfigMgr.sysList.index("sys_futex"):
                n = re.match((\
                    r'^\s*(?P<uaddr>\S+), (?P<op>\S+), '
                    r'(?P<val>\S+), (?P<timer>\S+),'), d['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:
                        op = flist[maskedOp]
                    except:
                        op = l['op']

                    # check recursive entry caused by log loss #
                    if td['ftxEnter'] > 0:
                        SysMgr.printWarn((\
                            "Fail to find return of %s for thread %s at %s line\n"\
                            "\tso report results may differ from actual") %\
                            (td['ftxEnt'], thread, SysMgr.curLine))

                    # futex operation #
                    td['ftxEnt'] = op

                    # futex object address #
                    td['futexCandObj'] = addr

                    # try to lock #
                    if maskedOp == flist.index("FUTEX_LOCK_PI") or \
                        maskedOp == flist.index("FUTEX_TRYLOCK_PI"):
                        td['ftxStat'] = 'L'
                        td['ftxLockCnt'] += 1

                        # remove already unlocked futex #
                        try:
                            td['futexObj'].pop(addr, None)
                        except:
                            pass
                    # wait #
                    elif maskedOp == flist.index("FUTEX_WAIT") or \
                        maskedOp == flist.index("FUTEX_WAIT_REQUEUE_PI") or \
                        maskedOp == flist.index("FUTEX_WAIT_BITSET"):
                        td['ftxStat'] = 'W'
                        td['ftxWaitCnt'] += 1
                    # try to unlock #
                    elif maskedOp == flist.index("FUTEX_UNLOCK_PI"):
                        td['ftxStat'] = 'U'
                    else:
                        td['ftxStat'] = '?'

                    td['ftxEnter'] = float(time)
                    otype = '{0:<10}'.format('ENT')
                    self.futexData.append(\
                        [thread, time, core, op, otype, '',\
                        addr, l['val'], l['timer']])

            if self.wakeupData['tid'] == '0':
                self.wakeupData['time'] = \
                    float(time) - float(SysMgr.startTime)

            # write syscall #
            if nr == ConfigMgr.sysList.index("sys_write"):
                self.wakeupData['tid'] = thread
                self.wakeupData['nr'] = str(nr)
                self.wakeupData['args'] = args

                if not (self.wakeupData['valid'] > 0 and \
                    (self.wakeupData['tid'] == thread and \
                    self.wakeupData['from'] == comm)):
                    self.wakeupData['valid'] += 1

                    if self.wakeupData['valid'] > 1:
                        self.wakeupData['corrupt'] = '1'
                    else:
                        self.wakeupData['corrupt'] = '0'

            # register syscall #
            try:
                self.threadData[thread]['syscallInfo']
            except:
                self.threadData[thread]['syscallInfo'] = dict()
            try:
                self.threadData[thread]['syscallInfo'][str(nr)]
            except:
                self.threadData[thread]['syscallInfo'][str(nr)] = \
                    dict(self.init_syscallInfo)

            # save syscall info #
            nrstr = str(nr)
            self.threadData[thread]['nrSyscall'] += 1
            self.threadData[thread]['lastNrSyscall'] = nr
            self.threadData[thread]['syscallInfo'][nrstr]['count'] += 1
            self.threadData[thread]['syscallInfo'][nrstr]['last'] = float(time)

            # save syscall history #
            if len(SysMgr.syscallList) > 0:
                try:
                    idx = SysMgr.syscallList.index(nr)

                    self.syscallData.append(\
                        ['ENT', time, thread, core, str(nr), args])
                except:
                    pass
            else:
                self.syscallData.append(\
                    ['ENT', time, thread, core, str(nr), args])

        elif func == "sys_exit":
            m = re.match(r'^\s*NR (?P<nr>\S+) = (?P<ret>.+)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            nr = long(d['nr'])
            ret = d['ret']
            td = self.threadData[thread]

            # apply filter #
            if SysMgr.isExceptTarget(thread, self.threadData):
                return time

            # handle wrong syscall number #
            if nr < 0 and td['lastNrSyscall'] >= 0:
                nr = td['lastNrSyscall']

            # update futex lock stat #
            if nr == ConfigMgr.sysList.index("sys_futex"):
                lockEnter = td['ftxEnter']
                lockStat = td['ftxStat']

                # futex call status #
                if lockEnter > 0:
                    # elasped time #
                    futexTime = float(time) - lockEnter

                    if futexTime > td['ftxMax']:
                        td['ftxMax'] = futexTime

                    td['ftxTotal'] += futexTime
                    td['ftxEnter'] = long(0)

                    # update CPU time by futex #
                    if td['start'] > lockEnter:
                        ctime = float(time) - td['start']
                        td['ftxProcess'] += ctime
                    elif td['ftxBlock'] == 0 and td['ftxLBlock'] == 0:
                        ctime = float(time) - lockEnter
                        td['ftxProcess'] += ctime

                    # handle lock object #
                    if (lockStat == 'L' or lockStat == 'U') and \
                        ret[0] == '0':
                        # target object #
                        try:
                            candObj = td['futexCandObj']
                        except:
                            candObj = None

                        # lock context #
                        if lockStat == 'L':
                            # register lock object #
                            try:
                                td['futexObj'][candObj] = float(time)
                            except:
                                td['futexObj'] = {}
                                td['futexObj'][candObj] = float(time)
                        # unlock context #
                        elif lockStat == 'U':
                            # remove lock object #
                            try:
                                lockStart = td['futexObj'][candObj]
                                td['futexObj'].pop(candObj, None)
                            except:
                                lockStart = long(0)

                            # calculate lock time #
                            if lockStart > 0:
                                ltime = float(time) - lockStart
                                td['ftxLock'] += ltime
                                if td['ftxLockMax'] < ltime:
                                    td['ftxLockMax'] = ltime

                    futexTime = '%.6f' % futexTime
                else:
                    td['ftxStat'] = '?'
                    futexTime = ''

                if td['ftxEnt']:
                    op = td['ftxEnt']
                    td['ftxEnt'] = None
                else:
                    op = ''

                otype = '{0:>10}'.format('RET')

                # add futex data #
                self.futexData.append(\
                    [thread, time, core, op, otype, \
                    futexTime, '', d['ret'], ''])

            try:
                if not SysMgr.depEnable:
                    raise Exception()
                elif nr == ConfigMgr.sysList.index("sys_write") and \
                    self.wakeupData['valid'] > 0:
                    self.wakeupData['valid'] -= 1
                elif SysMgr.arch != 'aarch64' and \
                    (nr == ConfigMgr.sysList.index("sys_poll") or \
                    nr == ConfigMgr.sysList.index("sys_select") or \
                    nr == ConfigMgr.sysList.index("sys_epoll_wait")):
                    if (self.lastJob[core]['job'] == "sched_switch" or \
                        self.lastJob[core]['job'] == "sched_wakeup" or \
                        self.lastJob[core]['job'] == "sched_wakeup_new") and \
                        self.lastJob[core]['prevWakeupTid'] != thread:
                        ttime = float(time) - float(SysMgr.startTime)
                        itime = ttime - float(self.wakeupData['time'])
                        self.depData.append(\
                            "\t%.3f/%.3f \t%16s %4s     %16s(%4s) \t%s" % \
                            (round(ttime, 7), round(itime, 7), " ", " ", \
                            self.threadData[thread]['comm'], thread, "wakeup"))

                        self.wakeupData['time'] = \
                            float(time) - float(SysMgr.startTime)
                        self.lastJob[core]['prevWakeupTid'] = thread
                elif (SysMgr.arch == 'arm' and \
                    nr == ConfigMgr.sysList.index("sys_recv")) or \
                    nr == ConfigMgr.sysList.index("sys_recvfrom") or \
                    nr == ConfigMgr.sysList.index("sys_recvmsg") or \
                    nr == ConfigMgr.sysList.index("sys_recvmmsg"):
                    if self.lastJob[core]['prevWakeupTid'] != thread:
                        ttime = float(time) - float(SysMgr.startTime)
                        itime = ttime - float(self.wakeupData['time'])
                        self.depData.append(\
                            "\t%.3f/%.3f \t%16s %4s     %16s(%4s) \t%s" % \
                            (round(ttime, 7), round(itime, 7), " ", " ", \
                            self.threadData[thread]['comm'], thread, "recv"))

                        self.wakeupData['time'] = \
                            float(time) - float(SysMgr.startTime)
                        self.lastJob[core]['prevWakeupTid'] = thread
            except:
                pass

            # register syscall #
            try:
                self.threadData[thread]['syscallInfo']
            except:
                self.threadData[thread]['syscallInfo'] = {}
            try:
                self.threadData[thread]['syscallInfo'][str(nr)]
            except:
                self.threadData[thread]['syscallInfo'][str(nr)] = \
                    dict(self.init_syscallInfo)

            # save syscall usage #
            diff = ''
            sysItem = self.threadData[thread]['syscallInfo'][str(nr)]
            if sysItem['last'] > 0:
                diff = float(time) - sysItem['last']
                self.threadData[thread]['syscallInfo'][str(nr)]['usage'] += diff
                self.threadData[thread]['syscallInfo'][str(nr)]['last'] = long(0)

                if sysItem['max'] == 0 or sysItem['max'] < diff:
                    self.threadData[thread]['syscallInfo'][str(nr)]['max'] = diff
                if sysItem['min'] <= 0 or sysItem['min'] > diff:
                    self.threadData[thread]['syscallInfo'][str(nr)]['min'] = diff

                if ret[0] == '-':
                    self.threadData[thread]['syscallInfo'][str(nr)]['err'] += 1

            # save syscall history #
            if len(SysMgr.syscallList) > 0:
                try:
                    idx = SysMgr.syscallList.index(nr)

                    self.syscallData.append(\
                        ['RET', time, thread, core, str(nr), ret, diff])
                except:
                    pass
            else:
                self.syscallData.append(\
                    ['RET', time, thread, core, str(nr), ret, diff])

        elif func == "signal_generate":
            m = re.match((\
                r'^\s*sig=(?P<sig>[0-9]+) errno=(?P<err>[0-9]+) '
                r'code=(?P<code>.*) comm=(?P<comm>.*) '
                r'pid=(?P<pid>[0-9]+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            sig = d['sig']
            target_comm = d['comm']
            pid = d['pid']
            ttime = float(time) - float(SysMgr.startTime)

            self.depData.append(\
                "\t%.3f/%.3f \t%16s(%4s) -> %16s(%4s) \t%s(%s)" % \
                (round(ttime, 7), \
                round(ttime - float(self.wakeupData['time']), 7), \
                self.threadData[thread]['comm'], thread, \
                target_comm, pid, "sigsend", sig))

            self.sigData.append(('SEND', ttime, thread, pid, sig))

            self.wakeupData['time'] = ttime

            try:
                # SIGCHLD #
                if sig == str(signal.SIGCHLD):
                    if self.threadData[pid]['waitStartAsParent'] > 0:
                        if self.threadData[pid]['waitPid'] == 0 or \
                            self.threadData[pid]['waitPid'] == long(thread):
                            diff = float(time) - \
                                self.threadData[pid]['waitStartAsParent']
                            self.threadData[thread]['waitParent'] = diff
                            self.threadData[pid]['waitChild'] += diff
                elif sig == str(signal.SIGSEGV):
                    self.threadData[pid]['die'] = 'F'
            except:
                return time

        elif func == "signal_deliver":
            m = re.match((\
                r'^\s*sig=(?P<sig>[0-9]+) errno=(?P<err>[0-9]+) '
                r'code=(?P<code>.*) sa_handler=(?P<handler>.*) '
                r'sa_flags=(?P<flags>.*)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            sig = d['sig']
            flags = d['flags']

            ttime = float(time) - float(SysMgr.startTime)
            itime = ttime - float(self.wakeupData['time'])
            self.depData.append(\
                "\t%.3f/%.3f \t%16s %4s     %16s(%4s) \t%s(%s)" % \
                (round(ttime, 7), round(itime, 7), "", "", \
                self.threadData[thread]['comm'], thread, "sigrecv", sig))

            self.sigData.append(('RECV', ttime, None, thread, sig))

            self.wakeupData['time'] = ttime

        elif func == "block_bio_queue" or func == "block_bio_remap":
            m = re.match((\
                r'^\s*(?P<major>[0-9]+),(?P<minor>[0-9]+)\s*'
                r'(?P<operation>\S+)\s*(?P<address>\S+)\s+\+\s+'
                r'(?P<size>[0-9]+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            SysMgr.blockEnable = True

            opt = d['operation']

            bio = '%s/%s/%s/%s' % \
                (d['major'], d['minor'], d['operation'][0], d['address'])

            # skip redundant operation #
            if func == "block_bio_queue" and bio in self.ioData:
                return time

            self.ioData[bio] = {'thread': thread, 'time': float(time), \
                'major': d['major'], 'minor': d['minor'], \
                'address': long(d['address']), 'size': long(d['size'])}

            self.saveBlkOpt(thread, comm, opt[0], d['major'], d['minor'], \
                d['address'], SysMgr.blockSize * long(d['size']))

            # read operations #
            if opt[0] == 'R':
                self.threadData[thread]['reqRdBlock'] += long(d['size'])
                self.threadData[thread]['readQueueCnt'] += 1
                self.threadData[thread]['readBlockCnt'] += 1
                self.threadData[thread]['blkCore'] = coreId
                self.threadData[coreId]['readBlockCnt'] += 1

                if self.threadData[thread]['readStart'] == 0:
                    self.threadData[thread]['readStart'] = float(time)
            # synchronous write operation #
            elif opt == 'WS':
                self.threadData[thread]['reqWrBlock'] += long(d['size'])
                self.threadData[thread]['writeQueueCnt'] += 1
                self.threadData[thread]['writeBlockCnt'] += 1
                self.threadData[thread]['blkCore'] = coreId
                self.threadData[coreId]['writeBlockCnt'] += 1

                if self.threadData[thread]['writeStart'] == 0:
                    self.threadData[thread]['writeStart'] = float(time)

        elif func == "block_rq_complete":
            m = re.match((\
                r'^\s*(?P<major>[0-9]+),(?P<minor>[0-9]+)\s*(?P<operation>\S+)'
                r'\s*\(.*\)\s*(?P<address>\S+)\s+\+\s+(?P<size>[0-9]+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            address = d['address']
            size = d['size']
            opt = d['operation']

            bio = '%s/%s/%s/%s' % \
                (d['major'], d['minor'], opt[0], d['address'])

            bioStart = long(address)
            bioEnd = long(address) + long(size)

            for key, request in sorted(\
                self.ioData.items(), key=lambda e: e[1]['address'], \
                reverse=False):

                # skip different requests with device number #
                if request['major'] != d['major'] or \
                    request['minor'] != d['minor']:
                    continue

                rBioEnd = request['address'] + request['size']

                # skip irrelevant requests #
                if not (bioStart <= request['address'] < bioEnd or \
                    bioStart < rBioEnd <= bioEnd):
                    continue

                # remove bio request in table #
                self.ioData.pop(key, None)

                matchBlock = long(0)

                if bioStart < request['address']:
                    matchStart = request['address']
                else:
                    matchStart = bioStart

                if bioEnd > rBioEnd:
                    matchEnd = rBioEnd
                else:
                    matchEnd = bioEnd

                # simple case #
                if matchStart == request['address']:
                    matchBlock = matchEnd - request['address']
                    request['size'] = rBioEnd - matchEnd
                    request['address'] = matchEnd

                    if request['size'] > 0:
                        try:
                            mbio = '%s/%s/%s/%s' % \
                                (request['major'], request['minor'],\
                                opt[0], request['address'] + request['size'])

                            request['size'] += self.ioData[mbio]['size']

                            # remove bio request in table #
                            self.ioData.pop(mbio, None)
                        except:
                            pass

                        # recreate partial ioData uncompleted #
                        bio = '%s/%s/%s/%s' % \
                            (request['major'], request['minor'], \
                            opt[0], request['address'])
                        self.ioData[bio] = request
                # complex case #
                elif matchStart > request['address']:
                    if matchEnd == request['address'] + request['size']:
                        matchBlock = matchEnd - matchStart
                        request['size'] = matchStart - request['address']

                        # recreate partial ioData uncompleted #
                        bio = '%s/%s/%s/%s' % \
                            (request['major'], request['minor'], \
                            opt[0], request['address'])
                        self.ioData[bio] = request
                    else:
                        continue
                else:
                    continue

                # just ignore error ;( #
                if bioEnd < request['address'] + request['size']:
                    pass

                if opt[0] == 'R':
                    self.threadData[request['thread']]['readBlock'] += \
                        matchBlock
                    self.threadData[coreId]['readBlock'] += matchBlock

                    if request['size'] != 0:
                        continue

                    if self.threadData[request['thread']]['readQueueCnt'] > 0:
                        self.threadData[request['thread']]['readQueueCnt'] -= 1

                    """
                    if error of size and time of block read is big then \
                    consider inserting below conditions
                    # self.threadData[request['thread']]['readQueueCnt'] == 0 #
                    """
                    if self.threadData[request['thread']]['readStart'] > 0:
                        waitTime = \
                            float(time) - \
                            self.threadData[request['thread']]['readStart']
                        self.threadData[coreId]['ioRdWait'] += waitTime
                        self.threadData[request['thread']]['ioRdWait'] += waitTime
                        self.threadData[request['thread']]['readStart'] = long(0)

                elif opt == 'WS':
                    self.threadData[request['thread']]['writeBlock'] += matchBlock
                    self.threadData[coreId]['writeBlock'] += matchBlock

                    if thread != request['thread'] or request['size'] != 0:
                        continue

                    if self.threadData[request['thread']]['writeQueueCnt'] > 0:
                        self.threadData[request['thread']]['writeQueueCnt'] -= 1

                    """
                    if error of size and time of block read is big then \
                    consider inserting below conditions
                    # self.threadData[request['thread']]['writeQueueCnt'] == 0 #
                    """
                    if self.threadData[request['thread']]['writeStart'] > 0:
                        waitTime = \
                            float(time) - \
                            self.threadData[request['thread']]['writeStart']
                        self.threadData[coreId]['ioWrWait'] += waitTime
                        self.threadData[request['thread']]['ioWrWait'] += waitTime
                        self.threadData[request['thread']]['writeStart'] = long(0)

        elif func == "writeback_dirty_page":
            m = re.match((\
                r'^\s*bdi\s+(?P<major>[0-9]+):(?P<minor>[0-9]+):\s*'
                r'ino=(?P<ino>\S+)\s+index=(?P<index>\S+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            SysMgr.blockEnable = True

            bid = d['ino'] + d['index']

            self.threadData[thread]['awriteBlock'] += 1
            self.threadData[thread]['awriteBlockCnt'] += 1
            self.threadData[coreId]['awriteBlock'] += 1
            self.threadData[coreId]['awriteBlockCnt'] += 1

            self.saveBlkOpt(\
                thread, comm, 'W', d['major'], d['minor'], bid, 1)

        elif func == "wbc_writepage":
            m = re.match((\
                r'^\s*bdi\s+(?P<major>[0-9]+):(?P<minor>[0-9]+):\s*'
                r'towrt=(?P<towrt>\S+)\s+skip=(?P<skip>\S+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            if d['skip'] == '0':
                SysMgr.blockEnable = True

                self.threadData[thread]['awriteBlock'] += 1
                self.threadData[thread]['awriteBlockCnt'] += 1
                self.threadData[coreId]['awriteBlock'] += 1
                self.threadData[coreId]['awriteBlockCnt'] += 1

                self.saveBlkOpt(\
                    thread, comm, 'W', d['major'], d['minor'], d['towrt'], 1)

        elif func == "mm_vmscan_wakeup_kswapd":
            try:
                self.reclaimData[thread]
            except:
                self.reclaimData[thread] = {'start': float(0)}

            if self.reclaimData[thread]['start'] <= 0:
                self.reclaimData[thread]['start'] = float(time)

            self.threadData[thread]['reclaimCnt'] += 1

        elif func == "mm_vmscan_kswapd_sleep":
            for key, value in self.reclaimData.items():
                self.threadData.setdefault(key, dict(self.init_threadData))
                self.threadData[key]['comm'] = comm

                self.threadData[key]['reclaimWait'] += \
                    float(time) - float(value['start'])
                self.reclaimData.pop(key, None)

        elif func == "mm_vmscan_direct_reclaim_begin":
            if self.threadData[thread]['dReclaimStart'] <= 0:
                self.threadData[thread]['dReclaimStart'] = float(time)

            self.threadData[thread]['dReclaimCnt'] += 1
            self.threadData[coreId]['dReclaimCnt'] += 1

        elif func == "mm_vmscan_direct_reclaim_end":
            m = re.match(r'^\s*nr_reclaimed=(?P<nr>[0-9]+)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            if self.threadData[thread]['dReclaimStart'] > 0:
                self.threadData[thread]['dReclaimWait'] += \
                    float(time) - self.threadData[thread]['dReclaimStart']
                self.threadData[coreId]['dReclaimWait'] += \
                    float(time) - self.threadData[thread]['dReclaimStart']

            self.threadData[thread]['dReclaimStart'] = long(0)

        elif func == "task_newtask":
            m = re.match(r'^\s*pid=(?P<pid>[0-9]+)\s+comm=(?P<comm>\S+)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            pid = d['pid']

            try:
                self.threadData[pid]
                SysMgr.printWarn(\
                    "Fail to handle a new task because it is already exist")
            except:
                self.threadData[pid] = dict(self.init_threadData)
                self.threadData[pid]['comm'] = d['comm']
                self.threadData[pid]['ptid'] = thread
                self.threadData[pid]['new'] = 'N'
                self.threadData[pid]['createdTime'] = float(time)

                if not self.threadData[thread]['childList']:
                    self.threadData[thread]['childList'] = list()

                self.threadData[thread]['childList'].append(pid)
                self.nrNewTask += 1

        elif func == "sched_process_fork":
            m = re.match((\
                r'^\s*comm=(?P<comm>.*)\s+pid=(?P<pid>[0-9]+)\s+'\
                r'child_comm=(?P<child_comm>.*)\s+'\
                r'child_pid=(?P<child_pid>[0-9]+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            cpid = d['child_pid']
            ccomm = d['child_comm']

            try:
                self.threadData[cpid]
                SysMgr.printWarn(\
                    "Fail to handle a new task because it is already exist")
            except:
                self.threadData[cpid] = dict(self.init_threadData)
                self.threadData[cpid]['comm'] = ccomm
                self.threadData[cpid]['ptid'] = thread
                self.threadData[cpid]['new'] = 'N'
                self.threadData[cpid]['createdTime'] = float(time)

                if not self.threadData[thread]['childList']:
                    self.threadData[thread]['childList'] = list()

                self.threadData[thread]['childList'].append(cpid)
                self.nrNewTask += 1

        elif func == "task_rename":
            m = re.match((\
                r'^\s*pid=(?P<pid>[0-9]+)\s+oldcomm=(?P<oldcomm>.*)\s+'
                r'newcomm=(?P<newcomm>.*)\s+oom_score_adj'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            pid = d['pid']
            newcomm = d['newcomm']

            try:
                self.threadData[pid]
            except:
                self.threadData[pid] = dict(self.init_threadData)
                self.threadData[pid]['comm'] = newcomm
                self.threadData[pid]['ptid'] = thread

            self.threadData[pid]['comm'] = newcomm

        elif func == "locks_get_lock_context":
            m = re.match((\
                r'^\s*dev=(?P<dev>.+)\s+ino=(?P<ino>.+)'\
                r'\s+type=(?P<type>.+)\s+ctx=(?P<ctx>.+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            fid = '%s%s' % (d['dev'], d['ino'])
            ltype = d['type']
            ctx = d['ctx']

            # save lock data #
            self.flockData.append([thread, time, core, ltype, fid, ctx])

            # unlock #
            if ltype == 'F_UNLCK':
                try:
                    if self.lockTable[fid]['owner'] == thread:
                        self.threadData[thread]['lockTime'] += \
                            float(time) - self.lockTable[fid]['time']
                        self.threadData[thread]['lockCnt'] += 1
                except:
                    self.lockTable[fid] = {}
                    self.threadData[thread]['lockCnt'] += 1

                # initialize lock data #
                self.lockTable[fid]['owner'] = None
                self.lockTable[fid]['time'] = long(0)
                self.lockTable[fid]['type'] = None
            # try to lock #
            else:
                self.threadData[thread]['tryLockCnt'] += 1

                try:
                    # get lock #
                    if not self.lockTable[fid]['owner']:
                        self.lockTable[fid]['owner'] = thread
                        self.lockTable[fid]['time'] = float(time)
                        self.lockTable[fid]['type'] = ltype
                        self.threadData[thread]['lastLockTime'] = float(time)

                        # add wait time to get lock #
                        if self.threadData[thread]['lastLockWait'] > 0:
                            llw = self.threadData[thread]['lastLockWait']
                            self.threadData[thread]['lockWait'] += \
                                float(time) - llw

                            self.threadData[thread]['lastLockWait'] = long(0)
                    # wait lock #
                    else:
                        # add wait time to get lock #
                        if self.threadData[thread]['lastLockWait'] > 0:
                            llw = self.threadData[thread]['lastLockWait']
                            self.threadData[thread]['lockWait'] += \
                                float(time) - llw

                        self.threadData[thread]['lastLockWait'] = float(time)
                except:
                    # no lock #
                    self.lockTable[fid] = {}
                    self.lockTable[fid]['owner'] = thread
                    self.lockTable[fid]['time'] = float(time)
                    self.lockTable[fid]['type'] = ltype
                    self.threadData[thread]['lastLockTime'] = float(time)

        elif func == "sched_process_exit":
            m = re.match(r'^\s*comm=(?P<comm>.*)\s+pid=(?P<pid>[0-9]+)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            pid = d['pid']

            try:
                self.threadData[pid]
            except:
                self.threadData[pid] = dict(self.init_threadData)
                self.threadData[pid]['comm'] = d['comm']
                self.threadData[pid]['die'] = 'D'

            if self.threadData[pid]['die'] != 'F':
                self.threadData[pid]['die'] = 'D'

        elif func == "sched_process_wait":
            m = re.match(r'^\s*comm=(?P<comm>.*)\s+pid=(?P<pid>[0-9]+)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            self.threadData[thread]['waitStartAsParent'] = float(time)
            self.threadData[thread]['waitPid'] = long(d['pid'])

        elif func == "suspend_resume":
            SysMgr.powerEnable = True

            state = None

            if 'suspend_enter' in etc and \
                'begin' in etc:
                state = 'S'
            elif 'machine_suspend' in etc and \
                'end' in etc:
                state = 'F'
            # Complete a PM transition for all non-sysdev devices #
            elif 'dpm_resume_user' in etc and \
                'end' in etc:
                state = 'R'

            if state:
                self.suspendData.append([time, state])

        elif func == "net_dev_xmit":
            pass

        elif func == "netif_receive_skb":
            pass

        elif func == "module_load":
            m = re.match(r'^\s*(?P<module>.*)\s+(?P<address>.*)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            module = d['module']
            address = d['address']

            self.moduleData.append(['load', thread, time, module, address])

        elif func == "module_free":
            m = re.match(r'^\s*(?P<module>.*)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            module = d['module']

            self.moduleData.append(['free', thread, time, module, None])

        elif func == "module_put":
            m = re.match((\
                r'^\s*(?P<module>.*)\s+call_site=(?P<site>.*)\s+'
                r'refcnt=(?P<refcnt>[0-9]+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            module = d['module']
            refcnt = long(d['refcnt'])

            self.moduleData.append(['put', thread, time, module, refcnt])

        elif func == "module_get":
            m = re.match((\
                r'^\s*(?P<module>.*)\s+call_site=(?P<site>.*)\s+'
                r'refcnt=(?P<refcnt>[0-9]+)'), etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            module = d['module']
            refcnt = long(d['refcnt'])

            self.moduleData.append(['get', thread, time, module, refcnt])

        elif func == "cpu_idle":
            m = re.match(\
                r'^\s*state=(?P<state>[0-9]+)\s+cpu_id=(?P<cpu_id>[0-9]+)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            SysMgr.powerEnable = True

            tid = '0[' + d['cpu_id']+ ']'

            if self.threadData[tid]['lastIdleStatus'] == long(d['state']):
                return time
            else:
                self.threadData[tid]['lastIdleStatus'] = long(d['state'])

            if self.threadData[tid]['coreSchedCnt'] == 0 and \
                self.threadData[tid]['offTime'] == 0:
                self.threadData[tid]['offTime'] = \
                    float(time) - float(SysMgr.startTime)

            # Wake core up, but the number 3 as this condition is not certain #
            if long(d['state']) < 3:
                self.threadData[tid]['offCnt'] += 1
                self.threadData[tid]['lastOff'] = float(time)
            # Start to sleep #
            elif self.threadData[tid]['lastOff'] > 0:
                self.threadData[tid]['offTime'] += \
                    (float(time) - self.threadData[tid]['lastOff'])
                self.threadData[tid]['lastOff'] = float(0)

        elif func == "cpu_frequency":
            # toDo: calculate power consumption for DVFS system #
            SysMgr.powerEnable = True
            return time

        elif func == "console":
            m = re.match(\
                r'^\s*\[\s*(?P<time>\S+)\s*\]\s+EVENT_(?P<event>\S+)', etc)
            if m:
                d = m.groupdict()

                self.handleUserEvent(d['event'], time)

                return time

            # process CPU shutdown event #
            m = re.match((\
                r'^\s*\[\s*(?P<time>\S+)\s*\]\s+'
                r'CPU(?P<core>[0-9]+)\: shutdown'), etc)
            if m:
                ed = m.groupdict()

                try:
                    # set status of thread #
                    lastTid = self.lastTidPerCore[ed['core']]
                    self.threadData[lastTid]['stop'] = float(ed['time'])
                    self.threadData[lastTid]['lastStatus'] = 'S'

                    # set status of core #
                    scoreId = '0[%s]' % ed['core']
                    self.threadData[scoreId]['offCnt'] += 1
                    self.threadData[scoreId]['lastOff'] = float(ed['time'])
                    self.threadData[scoreId]['start'] = float(ed['time'])
                    self.threadData[scoreId]['lastStatus'] = 'R'
                except:
                    pass

            # save consol log #
            self.consoleData.append([d['thread'], core, time, etc])

        elif func == "tracing_mark_write" or func == "0":
            m = re.match(r'^.+EVENT_(?P<event>\S+)', etc)
            if not m:
                printEventWarning(func)
                return time

            d = m.groupdict()

            self.handleUserEvent(d['event'], time)

        else:
            handleSpecialEvents = True

        # custom event #
        if any([True for event in SysMgr.customEventList if func.startswith(event)]):
            # add data into list #
            ntime = float(time) - float(SysMgr.startTime)
            self.customEventData.append(\
                [func, comm, thread, ntime, etc.strip()])

            # make event list #
            if not self.threadData[thread]['customEvent']:
                self.threadData[thread]['customEvent'] = {}

            self.threadData[thread]['customEvent'].setdefault(\
                func, dict(self.init_eventData))

            self.customEventInfo.setdefault(func, dict(self.init_eventData))

            self.threadData[thread]['customEvent'][func]['count'] += 1
            self.customEventInfo[func]['count'] += 1

            # define eventObj #
            eventObj = self.threadData[thread]['customEvent'][func]

            # get interval #
            interDiff = long(0)
            if eventObj['start'] > 0:
                interDiff = float(time) - eventObj['start']

            # update period of thread #
            if interDiff > eventObj['maxPeriod'] or \
                eventObj['maxPeriod'] == 0:
                self.threadData[thread]['customEvent'][func]['maxPeriod'] = interDiff
            if interDiff < eventObj['minPeriod'] or eventObj == 0:
                self.threadData[thread]['customEvent'][func]['minPeriod'] = interDiff

            # update period of system #
            if interDiff > self.customEventInfo[func]['maxPeriod'] or \
                self.customEventInfo[func]['maxPeriod'] == 0:
                self.customEventInfo[func]['maxPeriod'] = interDiff
            if interDiff < self.customEventInfo[func]['minPeriod'] or \
                self.customEventInfo[func]['minPeriod'] == 0:
                self.customEventInfo[func]['minPeriod'] = interDiff

            self.threadData[thread]['customEvent'][func]['start'] = float(time)

            handleSpecialEvents = True

        # check special event flag #
        if not handleSpecialEvents:
            return time

        # user event #
        for name in SysMgr.userEventList:
            if not func.startswith(name):
                continue

            if not self.threadData[thread]['userEvent']:
                self.threadData[thread]['userEvent'] = {}

            self.threadData[thread]['userEvent'].setdefault(\
                name, dict(self.init_eventData))

            self.userEventInfo.setdefault(name, dict(self.init_eventData))

            # define eventObj #
            eventObj = self.threadData[thread]['userEvent'][name]

            if func == '%s_enter' % name:
                # add data into list #
                ntime = float(time) - float(SysMgr.startTime)
                self.userEventData.append(\
                    ['ENTER', name, comm, thread, ntime, ''])

                # get interval #
                interDiff = long(0)
                if eventObj['start'] > 0:
                    interDiff = float(time) - eventObj['start']

                self.threadData[thread]['userEvent'][name]['count'] += 1
                self.threadData[thread]['userEvent'][name]['start'] = float(time)

                # update period of thread #
                if interDiff > eventObj['maxPeriod'] or \
                    eventObj['maxPeriod'] == 0:
                    self.threadData[thread]['userEvent'][name]['maxPeriod'] = interDiff
                if interDiff < eventObj['minPeriod'] or \
                    eventObj['minPeriod'] == 0:
                    self.threadData[thread]['userEvent'][name]['minPeriod'] = interDiff

                self.userEventInfo[name]['count'] += 1

                # update period of system #
                if interDiff > self.userEventInfo[name]['maxPeriod'] or \
                    self.userEventInfo[name]['maxPeriod'] == 0:
                    self.userEventInfo[name]['maxPeriod'] = interDiff
                if interDiff < self.userEventInfo[name]['minPeriod'] or \
                    self.userEventInfo[name]['minPeriod'] == 0:
                    self.userEventInfo[name]['minPeriod'] = interDiff

            elif func == '%s_exit' % name:
                # add data into list #
                ntime = float(time) - float(SysMgr.startTime)
                self.userEventData.append(\
                    ['EXIT', name, comm, thread, ntime, \
                    etc[etc.find('(')+1:etc.rfind('<-')]])

                # get usage #
                usage = long(0)
                if eventObj['start'] > 0:
                    usage = float(time) - eventObj['start']
                    self.threadData[thread]['userEvent'][name]['usage'] += usage
                    self.userEventInfo[name]['usage'] += usage

                    # update usage of thread #
                    if usage > eventObj['max'] or eventObj['max'] == 0:
                        self.threadData[thread]['userEvent'][name]['max'] = usage
                    if usage < eventObj['min'] or eventObj['min'] == 0:
                        self.threadData[thread]['userEvent'][name]['min'] = usage

                    # update usage of system #
                    if usage > self.userEventInfo[name]['max'] or \
                        self.userEventInfo[name]['max'] == 0:
                        self.userEventInfo[name]['max'] = usage
                    if usage < self.userEventInfo[name]['min'] or \
                        self.userEventInfo[name]['min'] == 0:
                        self.userEventInfo[name]['min'] = usage

        # kernel event #
        for name in SysMgr.kernelEventList:
            if not func.startswith(name):
                continue

            if not self.threadData[thread]['kernelEvent']:
                self.threadData[thread]['kernelEvent'] = {}

            self.threadData[thread]['kernelEvent'].setdefault(\
                name, dict(self.init_eventData))

            self.kernelEventInfo.setdefault(name, dict(self.init_eventData))

            # define eventObj #
            eventObj = self.threadData[thread]['kernelEvent'][name]

            if func == '%s_enter' % name:
                # add data into list #
                ntime = float(time) - float(SysMgr.startTime)

                isSaved = True
                m = re.match(\
                    r'^\s*\((?P<name>.+)\+(?P<offset>.+) <(?P<addr>.+)>\)(?P<args>.*)', etc)
                if m:
                    d = m.groupdict()
                    self.kernelEventData.append(\
                        ['ENTER', name, d['addr'], comm, thread, ntime, '', d['args']])
                else:
                    m = re.match(\
                        r'^\s*\((?P<name>.+)\+(?P<offset>.+)\)(?P<args>.*)', etc)
                    if m:
                        d = m.groupdict()
                        self.kernelEventData.append(\
                            ['ENTER', name, '', comm, thread, ntime, '', d['args']])
                    else:
                        isSaved = False
                        SysMgr.printWarn(\
                            "Fail to recognize '%s' kernel event" % etc)

                if not isSaved:
                    continue

                # get interval #
                interDiff = long(0)
                if eventObj['start'] > 0:
                    interDiff = float(time) - eventObj['start']

                self.threadData[thread]['kernelEvent'][name]['count'] += 1
                self.threadData[thread]['kernelEvent'][name]['start'] = float(time)

                # update period of thread #
                if interDiff > eventObj['maxPeriod'] or \
                    eventObj['maxPeriod'] == 0:
                    self.threadData[thread]['kernelEvent'][name]['maxPeriod'] = interDiff
                if interDiff < eventObj['minPeriod'] or \
                    eventObj['minPeriod'] == 0:
                    self.threadData[thread]['kernelEvent'][name]['minPeriod'] = interDiff

                self.kernelEventInfo[name]['count'] += 1

                # update period of system #
                if interDiff > self.kernelEventInfo[name]['maxPeriod'] or \
                    self.kernelEventInfo[name]['maxPeriod'] == 0:
                    self.kernelEventInfo[name]['maxPeriod'] = interDiff
                if interDiff < self.kernelEventInfo[name]['minPeriod'] or \
                    self.kernelEventInfo[name]['minPeriod'] == 0:
                    self.kernelEventInfo[name]['minPeriod'] = interDiff

            elif func == '%s_exit' % name:
                # add data into list #
                ntime = float(time) - float(SysMgr.startTime)

                isSaved = True
                m = re.match((\
                    r'^\s*\((?P<caller>.+)\+(?P<offset>.+) <(?P<caddr>.+)> <- '
                    r'(?P<name>.+) <(?P<addr>.+)>\)(?P<args>.*)'), etc)
                if m:
                    d = m.groupdict()
                    self.kernelEventData.append(\
                        ['EXIT', name, d['addr'], comm, thread, ntime, \
                        d['caller'], d['args'], d['caddr']])
                else:
                    m = re.match((\
                        r'^\s*\((?P<caller>.+)\+(?P<offset>.+) <- '
                        r'(?P<name>.+)\)(?P<args>.*)'), etc)
                    if m:
                        d = m.groupdict()
                        self.kernelEventData.append(\
                            ['EXIT', name, '', comm, thread, ntime, \
                            d['caller'], d['args'], ''])
                    else:
                        isSaved = False
                        SysMgr.printWarn(\
                            "Fail to recognize '%s' kernel event" % etc)

                if not isSaved:
                    continue

                # get usage #
                if eventObj['start'] <= 0:
                    continue

                usage = float(time) - eventObj['start']
                self.threadData[thread]['kernelEvent'][name]['usage'] += usage
                self.kernelEventInfo[name]['usage'] += usage

                # update usage of thread #
                if usage > eventObj['max'] or \
                    eventObj['max'] == 0:
                    self.threadData[thread]['kernelEvent'][name]['max'] = usage
                if usage < eventObj['min'] or \
                    eventObj['min'] == 0:
                    self.threadData[thread]['kernelEvent'][name]['min'] = usage

                # update usage of system #
                if usage > self.kernelEventInfo[name]['max'] or \
                    self.kernelEventInfo[name]['max'] == 0:
                    self.kernelEventInfo[name]['max'] = usage
                if usage < self.kernelEventInfo[name]['min'] or \
                    self.kernelEventInfo[name]['min'] == 0:
                    self.kernelEventInfo[name]['min'] = usage

        # return time #
        return time



    def compareThreadData(self):
        for key, value in sorted(self.threadData.items(), \
            key=lambda e: e[1]['usage'], reverse=True):

            per = float(value['usage']) / float(self.totalTime)
            newPercent = round(per, 7) * 100

            try:
                self.threadDataOld[key]
            except:
                if long(newPercent) < 1:
                    del self.threadData[key]
                continue

            oldPercent = \
                round(float(self.threadDataOld[key]['usage']) / \
                float(self.totalTimeOld), 7) * 100
            if long(oldPercent) >= long(newPercent) or long(newPercent) < 1:
                del self.threadData[key]



    def printFileStat(self, filters):
        # update uptime #
        SysMgr.updateUptime()

        convertNum = UtilMgr.convNum

        # print cpu usage #
        cpuUsage = ThreadAnalyzer.dbgObj.getCpuUsage()
        diff = SysMgr.uptimeDiff
        ttime = cpuUsage[0] / diff
        utime = cpuUsage[1] / diff
        stime = cpuUsage[2] / diff
        cpuStr = '%d%%(Usr:%d%%/Sys:%d%%)' % (ttime, utime, stime)

        SysMgr.addPrint((\
            "[Top File Info] [Time: %7.3f] [Proc: %s] "
            "[FD: %s] [File: %s] [CPU: %s] (Unit: %%/MB/NR)\n") % \
            (SysMgr.uptime, convertNum(self.nrProcess), \
            convertNum(self.nrFd), convertNum(len(self.fileData)), cpuStr))

        SysMgr.addPrint("%s\n" % twoLine + \
            ("{0:^16} ({1:^5}/{2:^5}/{3:^4}/{4:>4})|{5:^4}|{6:^107}|\n{7:1}\n").\
            format("Process", "ID", "Pid", "Nr", "Pri", "FD", "Path", oneLine),\
            newline = 3)

        # set sort value #
        if SysMgr.sort == 'p':
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: long(e[0]))
        else:
            # set the number of files opened as default #
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: len(e[1]['fdList']), reverse=True)

        procFilter, fileFilter = filters

        # print process info #
        procCnt = long(0)
        for idx, value in sortedProcData:
            comm = value['stat'][self.commIdx][1:-1]

            pid = value['stat'][self.ppidIdx]

            if ConfigMgr.SCHED_POLICY[int(value['stat'][self.policyIdx])] == 'C':
                schedValue = "%3d" % (long(value['stat'][self.prioIdx]) - 20)
            else:
                schedValue = "%3d" % (abs(long(value['stat'][self.prioIdx]) + 1))

            procInfo = ("{0:>16} ({1:>5}/{2:>5}/{3:>4}/{4:>4})").\
                format(comm, idx, pid, value['stat'][self.nrthreadIdx], \
                ConfigMgr.SCHED_POLICY[int(value['stat'][self.policyIdx])] + \
                str(schedValue))

            procInfoLen = len(procInfo)

            if 'fdInfo' in value:
                details = '   '.join(["%s: %s" % (fd,path) for fd, path in \
                    sorted(value['fdInfo'].items(), \
                    key=lambda e: long(e[1]), reverse=True)])
            else:
                details = ' '

            procInfo = "%s|%s\n" % \
                (procInfo, '{0:>4}| {1:<106}|'.format(\
                len(value['fdList']), details))

            fdCnt = long(0)
            if SysMgr.sort == 'f':
                if procInfo != '':
                    ret = SysMgr.addPrint(procInfo)
                    procInfo = ''
                    if not ret:
                        break

                fdCnt += 1
                procCnt += 1

                continue

            for fd, path in sorted(value['fdList'].items(),\
                key=lambda e: long(e[0]), reverse=True):
                # get additional info #
                try:
                    if path.startswith('socket'):
                        obj = path.split('[')[1][:-1]
                        addr = SysMgr.getSocketAddrList([obj])
                        if len(addr) > 0:
                            path = '%s (%s)' % (path, addr[0])
                            raise Exception()
                        uds = SysMgr.getSocketPathList([obj])
                        if len(uds) > 0:
                            path = '%s (%s)' % (path, uds[0])
                except SystemExit:
                    sys.exit(0)
                except:
                    pass

                # apply filter #
                if fileFilter != []:
                    found = False
                    for fileItem in fileFilter:
                        if fileItem in path:
                            found = True
                            break
                    if not found:
                        continue

                if procInfo != '':
                    ret = SysMgr.addPrint(procInfo)
                    procInfo = ''
                    if not ret:
                        break

                SysMgr.addPrint(\
                    ("{0:>1}|{1:>4}| {2:<106}|\n").format(\
                    ' ' * procInfoLen, fd, path))

                fdCnt += 1

            if fdCnt > 0:
                procCnt += 1

            if fdCnt > 0:
                ret = SysMgr.addPrint("%s\n" % oneLine)
                if not ret:
                    break

        if procCnt == 0:
            text = "{0:^16}".format('None')
            frame = '%s%s|' % \
                (text, ' ' * (SysMgr.lineLength - len(text) - 1))

            SysMgr.addPrint("{0:1}\n{1:1}\n".format(frame, oneLine))
        elif SysMgr.sort == 'f':
            SysMgr.addPrint("{0:1}\n".format(oneLine))

        SysMgr.printTopStats()



    def saveFileStat(self, filters):
        # save proc and file instance #
        SysMgr.topInstance = self
        SysMgr.procInstance = self.procData
        SysMgr.fileInstance = self.fileData

        procFilter, fileFilter = filters

        # get process list #
        if procFilter:
            pids = SysMgr.convertPidList(procFilter, isThread=True)
            newPids = []
            for pid in pids:
                ret = SysMgr.getTgid(pid)
                if ret:
                    newPids.append(ret)
            pids = list(set(newPids))
        else:
            try:
                pids = os.listdir(SysMgr.procPath)
            except:
                SysMgr.printOpenErr(SysMgr.procPath)
                sys.exit(0)

        # remove myself info #
        try:
            del pids[pids.index(str(SysMgr.pid))]
        except SystemExit:
            sys.exit(0)
        except:
            pass

        # get thread list #
        for pid in pids:
            try:
                long(pid)
                self.nrProcess += 1
            except:
                continue

            # make path of tid #
            procPath = "%s/%s" % (SysMgr.procPath, pid)
            fdlistPath = "%s/%s" % (procPath, 'fd')

            # save stat of process #
            self.saveProcData(procPath, pid)

            # save file info per process #
            try:
                fdlist = os.listdir(fdlistPath)
            except:
                SysMgr.printOpenWarn(fdlistPath)
                continue

            # save fd info of process #
            for fd in fdlist:
                try:
                    long(fd)
                    self.nrFd += 1
                except:
                    continue

                try:
                    # add file info into fdList #
                    fdPath = "%s/%s" % (fdlistPath, fd)
                    filename = os.readlink(fdPath)
                    self.procData[pid]['fdList'][fd] = filename

                    # increase reference count of file #
                    try:
                        self.fileData[filename] += 1
                    except:
                        self.fileData[filename] = 1

                    # initialize fdinfo per process #
                    try:
                        self.procData[pid]['fdInfo']
                    except:
                        self.procData[pid]['fdInfo'] = {}
                        self.procData[pid]['fdInfo']['EVENT'] = long(0)
                        self.procData[pid]['fdInfo']['SOCKET'] = long(0)
                        self.procData[pid]['fdInfo']['DEVICE'] = long(0)
                        self.procData[pid]['fdInfo']['PIPE'] = long(0)
                        self.procData[pid]['fdInfo']['NORMAL'] = long(0)
                        self.procData[pid]['fdInfo']['PROC'] = long(0)

                    # increase type count per process #
                    if filename.startswith('anon'):
                        self.procData[pid]['fdInfo']['EVENT'] += 1
                    elif filename.startswith('socket'):
                        self.procData[pid]['fdInfo']['SOCKET'] += 1
                    elif filename.startswith('/dev'):
                        self.procData[pid]['fdInfo']['DEVICE'] += 1
                    elif filename.startswith('pipe'):
                        self.procData[pid]['fdInfo']['PIPE'] += 1
                    elif filename.startswith(SysMgr.procPath):
                        self.procData[pid]['fdInfo']['PROC'] += 1
                    else:
                        self.procData[pid]['fdInfo']['NORMAL'] += 1
                except:
                    self.nrFd -= 1
                    SysMgr.printOpenWarn(fdPath)



    def saveZoneInfo(self):
        # save zone info #
        try:
            memBuf = None
            SysMgr.zoneFd.seek(0)
            memBuf = SysMgr.zoneFd.readlines()
        except:
            try:
                memPath = "%s/%s" % (SysMgr.procPath, 'zoneinfo')
                SysMgr.zoneFd = open(memPath, 'r')

                memBuf = SysMgr.zoneFd.readlines()
            except:
                SysMgr.printOpenWarn(memPath)

        if memBuf:
            self.prevZoneData = self.zoneData
            self.zoneData = {}

            zone = None
            for line in memBuf:
                zl = line.split()
                item = zl[0]
                if item  == 'Node':
                    zone = '%s-%s' % (zl[1][:-1], zl[3])
                    self.zoneData[zone] = dict()
                elif item == 'pages' and zl[1] == 'free':
                    self.zoneData[zone]['free'] = long(zl[2])
                elif item == 'min' or item == 'low' or item == 'high' or \
                    item == 'spanned' or item == 'present' or item == 'managed':
                    self.zoneData[zone][item] = long(zl[1])
                else:
                    continue



    def saveIrqs(self):
        # save irq info #
        try:
            irqBuf = None
            SysMgr.irqFd.seek(0)
            irqBuf = SysMgr.irqFd.readlines()
        except:
            try:
                irqPath = "%s/%s" % (SysMgr.procPath, 'interrupts')
                SysMgr.irqFd = open(irqPath, 'r')

                irqBuf = SysMgr.irqFd.readlines()
            except:
                SysMgr.printOpenWarn(irqPath)

        # save softirq info #
        try:
            sirqBuf = None
            SysMgr.softirqFd.seek(0)
            sirqBuf = SysMgr.softirqFd.readlines()
            irqBuf += sirqBuf[1:]
        except:
            try:
                sirqPath = "%s/%s" % (SysMgr.procPath, 'softirqs')
                SysMgr.softirqFd = open(sirqPath, 'r')

                sirqBuf = SysMgr.softirqFd.readlines()
                irqBuf += sirqBuf[1:]
            except:
                SysMgr.printOpenWarn(sirqPath)

        if irqBuf:
            self.prevIrqData = self.irqData
            self.irqData = {}
            cpuCnt = len(irqBuf.pop(0).split())

            for line in irqBuf:
                irqList = line.split()
                try:
                    irqSum = sum(list(map(long, irqList[1:cpuCnt])))
                    if irqSum > 0:
                        self.irqData[irqList[0][:-1]] = irqSum
                except:
                    pass



    def saveProcStat(self):
        # get process list #
        try:
            pids = os.listdir(SysMgr.procPath)
        except:
            SysMgr.printOpenErr(SysMgr.procPath)
            sys.exit(0)

        # reset and save proc instance #
        self.saveProcInstance()

        # get thread list #
        for pid in pids:
            if not pid.isdigit():
                continue

            self.nrProcess += 1

            # make path of tid #
            procPath = "%s/%s" % (SysMgr.procPath, pid)
            taskPath = "%s/task" % procPath

            # save info per process #
            if SysMgr.processEnable:
                if SysMgr.exceptCommFilter and \
                    not pid in SysMgr.filterGroup:
                        continue

                # save stat of process #
                ret = self.saveProcData(procPath, pid)

                # calculate number of threads #
                if pid in self.procData:
                    self.nrThread += \
                        long(self.procData[pid]['stat'][self.nrthreadIdx])

                continue

            # save info per thread #
            try:
                tids = os.listdir(taskPath)
            except:
                SysMgr.printOpenWarn(taskPath)
                continue

            for tid in tids:
                if not tid.isdigit():
                    continue

                if SysMgr.exceptCommFilter and \
                    not tid in SysMgr.filterGroup:
                        continue

                self.nrThread += 1

                threadPath = "%s/%s" % (taskPath, tid)

                # save stat of thread #
                ret = self.saveProcData(threadPath, tid, pid)

                # main thread #
                if pid == tid:
                    self.procData[tid]['isMain'] = True
                    self.procData[tid]['tids'] = []
                # sibling thread #
                else:
                    try:
                        self.procData[pid]['tids'].append(tid)
                    except:
                        self.procData[pid] = dict(self.init_procData)
                        self.procData[pid]['tids'] = []
                        self.procData[pid]['tids'].append(tid)



    def saveGenSystemInfo(self):
        # get psutil object #
        psutil = SysMgr.getPkg('psutil')

        '''
        python psutil APIs
        refer to https://psutil.readthedocs.io/en/latest
        '''

        # CPU #
        psutil.cpu_times(percpu=False)
        psutil.cpu_percent(interval=None, percpu=False)
        psutil.cpu_count(logical=True)
        psutil.cpu_stats()
        psutil.cpu_freq(percpu=False)
        psutil.getloadavg()

        # MEMORY #
        psutil.virtual_memory()
        psutil.swap_memory()

        # DISK #
        psutil.disk_partitions(all=False)
        #psutil.disk_usage(path=None)
        psutil.disk_io_counters(perdisk=False, nowrap=True)

        # NETWORK #
        psutil.net_io_counters(pernic=False, nowrap=True)
        psutil.net_connections(kind='inet')
        psutil.net_if_addrs()
        psutil.net_if_stats()

        # ETC #
        psutil.sensors_temperatures(fahrenheit=False)
        psutil.sensors_fans()
        psutil.sensors_battery()
        psutil.users()

        # PROCESS #
        psutil.process_iter(attrs=None, ad_value=None)
        psutil.pid_exists(pid=os.getpid())
        proc = psutil.Process(pid=None)
        procDict = proc.as_dict(attrs=None, ad_value=None)
        procMem = proc.memory_full_info()
        proc.is_running()
        proc.send_signal()
        proc.suspend()
        proc.resume()
        proc.terminate()
        proc.kill()
        proc.wait()



    def saveSystemStat(self):
        # update uptime #
        SysMgr.updateUptime()

        # save CPU info #
        try:
            cpuBuf = None
            SysMgr.statFd.seek(0)
            cpuBuf = SysMgr.statFd.readlines()
        except:
            try:
                cpuPath = "%s/stat" % SysMgr.procPath
                SysMgr.statFd = open(cpuPath, 'r')
                cpuBuf = SysMgr.statFd.readlines()
            except:
                SysMgr.printErr(\
                    'Fail to read %s' % cpuPath, True)

        # stat list from http://man7.org/linux/man-pages/man5/proc.5.html #
        if cpuBuf:
            for line in cpuBuf:
                statList = line.split()
                cpuId = statList[0]
                if cpuId == 'cpu':
                    if not 'all' in self.cpuData:
                        self.cpuData['all'] = \
                            {'user': long(statList[1]), \
                            'nice': long(statList[2]), \
                            'system': long(statList[3]), \
                            'idle': long(statList[4]), \
                            'iowait': long(statList[5]), \
                            'irq': long(statList[6]), \
                            'softirq': long(statList[7])}
                elif cpuId.startswith('cpu'):
                    if not long(cpuId[3:]) in self.cpuData:
                        self.cpuData[int(cpuId[3:])] = \
                            {'user': long(statList[1]), \
                            'nice': long(statList[2]), \
                            'system': long(statList[3]), \
                            'idle': long(statList[4]), \
                            'iowait': long(statList[5]), \
                            'irq': long(statList[6]), \
                            'softirq': long(statList[7])}
                else:
                    if not cpuId in self.cpuData:
                        self.cpuData[cpuId] = {cpuId: long(statList[1])}

            # set the number of core #
            SysMgr.nrCore = long(0)
            for idx, val in sorted(self.cpuData.items(),\
                key=lambda x:str(x[0]), reverse=False):
                try:
                    SysMgr.maxCore = long(idx)
                    SysMgr.nrCore += 1
                except:
                    continue

        # save mem info #
        try:
            memBuf = None
            SysMgr.memFd.seek(0)
            memBuf = SysMgr.memFd.readlines()
        except:
            try:
                memPath = "%s/%s" % (SysMgr.procPath, 'meminfo')
                SysMgr.memFd = open(memPath, 'r')

                memBuf = SysMgr.memFd.readlines()
            except:
                SysMgr.printOpenWarn(memPath)

        if memBuf:
            self.prevMemData = self.memData

            self.memData = {}

            for line in memBuf:
                memList = line.split()
                self.memData[memList[0][:-1]] = long(memList[1])

        # save irq info #
        if SysMgr.irqEnable:
            self.saveIrqs()

        if SysMgr.memEnable:
            self.saveZoneInfo()

        # save vmstat info #
        # vmstat list from https://access.redhat.com/solutions/406773 #
        try:
            vmBuf = None
            SysMgr.vmstatFd.seek(0)
            vmBuf = SysMgr.vmstatFd.readlines()
        except:
            try:
                vmstatPath = "%s/%s" % (SysMgr.procPath, 'vmstat')
                SysMgr.vmstatFd = open(vmstatPath, 'r')

                vmBuf = SysMgr.vmstatFd.readlines()
            except:
                SysMgr.printOpenWarn(vmstatPath)

        if vmBuf:
            self.prevVmData = self.vmData
            self.vmData = {}

            for line in vmBuf:
                vmList = line.split()
                self.vmData[vmList[0]] = long(vmList[1])

        # save swap info #
        try:
            swapBuf = None
            SysMgr.swapFd.seek(0)
            swapBuf = SysMgr.swapFd.readlines()
        except:
            try:
                swapPath = "%s/%s" % (SysMgr.procPath, 'swaps')
                SysMgr.swapFd = open(swapPath, 'r')

                swapBuf = SysMgr.swapFd.readlines()
            except:
                SysMgr.printOpenWarn(swapPath)

        # get swap usage if it changed #
        if self.prevSwaps != swapBuf and swapBuf:
            swapTotal = long(0)
            swapUsed = long(0)

            for line in swapBuf:
                swapList = line.split()
                # swapList = [Filename, Type, Size, Used, Priority] #
                try:
                    swapTotal += long(swapList[2])
                    swapUsed += long(swapList[3])
                except:
                    continue

            self.vmData['swapTotal'] = swapTotal
            self.vmData['swapUsed'] = swapUsed

            self.prevSwaps = swapBuf
        else:
            try:
                self.vmData['swapTotal'] = self.prevVmData['swapTotal']
                self.vmData['swapUsed'] = self.prevVmData['swapUsed']
            except:
                self.vmData['swapTotal'] = long(0)
                self.vmData['swapUsed'] = long(0)

        # save diskstats #
        SysMgr.updateDiskStats()

        # save netstat #
        try:
            SysMgr.netstatFd.seek(0)
            SysMgr.prevNetstat = SysMgr.netstat
            SysMgr.netstat = SysMgr.netstatFd.readlines()
        except:
            try:
                netstatPath = "%s/%s" % (SysMgr.procPath, 'net/netstat')
                SysMgr.netstatFd = open(netstatPath, 'r')
                SysMgr.netstat = SysMgr.netstatFd.readlines()
            except:
                SysMgr.printOpenWarn(netstatPath)

        # save loadavg #
        try:
            SysMgr.loadavgFd.seek(0)
            SysMgr.loadavg = SysMgr.loadavgFd.readlines()[0]
        except:
            try:
                loadavgPath = "%s/%s" % (SysMgr.procPath, 'loadavg')
                SysMgr.loadavgFd = open(loadavgPath, 'r')
                SysMgr.loadavg = SysMgr.loadavgFd.readlines()[0]
            except:
                SysMgr.printOpenWarn(loadavgPath)

        # collect perf data #
        if SysMgr.perfEnable:
            SysMgr.collectSystemPerfData()

        # save gpu stat #
        self.saveGpuData()

        # check systemtop mode #
        if SysMgr.isSystemTopMode() or \
            not SysMgr.taskEnable:
            return

        # save proc stats #
        self.saveProcStat()



    @staticmethod
    def getProcTreeFromList(procInstance):
        procTree = {}
        ppidIdx = ConfigMgr.STAT_ATTR.index("PPID")

        # get a relation list to track ancestors of process #
        def getRelationList(item, procInstance):
            tmpId = item
            relationList = []

            while 1:
                try:
                    relationList.insert(0, tmpId)
                    tmpId = procInstance[tmpId]['stat'][ppidIdx]
                    if tmpId == '0':
                        raise Exception()
                except:
                    return relationList

        # add items in relation list to tree #
        def addItemsToList(relationList, procTree):
            nodePointer = procTree
            for item in relationList:
                try:
                    nodePointer[item]
                except:
                    nodePointer[item] = {}
                nodePointer = nodePointer[item]

        starttimeIdx = ConfigMgr.STAT_ATTR.index("STARTTIME")
        for pid, item in sorted(procInstance.items(), \
            key=lambda e: long(e[1]['stat'][starttimeIdx])):
            ppid = procInstance[pid]['stat'][ppidIdx]

            if ppid == '0':
                procTree[pid] = {}
            else:
                relationList = getRelationList(pid, procInstance)
                addItemsToList(relationList, procTree)

        return procTree



    @staticmethod
    def saveProcSmapsData(path, tid):
        # check root permission #
        if not SysMgr.isRoot():
            return

        buf = ''
        mtype = ''
        stable = {}
        ftable = {}
        isInaccessable = False
        fpath = '%s/%s' % (path, 'smaps')
        ptable = {'ANON': {}, 'FILE': {}, 'STACK': {}, 'ETC': {}, 'SHM': {}}

        checkCnt = long(0)
        checklist = ['Size:', 'Rss:', 'Pss:', 'Shared_Clean:', \
            'Shared_Dirty:', 'Private_Dirty:', 'Referenced:', \
            'AnonHugePages:', 'Swap:', 'Locked:']

        try:
            SysMgr.procInstance[tid]['maps'] = ptable
        except:
            SysMgr.printWarn('Fail to find %s process' % tid)
            return

        try:
            with open(fpath, 'r') as fd:
                buf = fd.readlines()
        except:
            SysMgr.procInstance[tid]['maps'] = None
            SysMgr.printOpenWarn(fpath)
            return

        # check kernel thread #
        if len(buf) == 0:
            return

        for line in buf:
            d = {}
            tmplist = line.split()

            # memory map info #
            if not line[0].isupper():
                checkCnt = long(0)

                d['range'] = tmplist[0]
                d['perm'] = tmplist[1]
                d['offset'] = tmplist[2]
                d['devid'] = tmplist[3]
                d['inode'] = tmplist[4]

                if len(tmplist) > 5:
                    ptype = tmplist[5]
                else:
                    ptype = ''

                # shared memory #
                if d['perm'][3] == 's':
                    mtype = 'SHM'
                    stable[ptype] = long(0)
                # file-mapped memory #
                elif ptype.startswith('/'):
                    mtype = 'FILE'
                    ftable[ptype] = long(0)
                # anonymous memory #
                elif ptype == '':
                    mtype = 'ANON'
                # stack memory #
                elif ptype.startswith('[stack'):
                    mtype = 'STACK'
                # anonymous memory #
                elif ptype == '[heap]':
                    mtype = 'ANON'
                else:
                    mtype = 'ETC'

                # check inaccessible area #
                isInaccessable = d['perm'].startswith('---')

                try:
                    ptable[mtype]['count'] += 1
                except:
                    ptable[mtype]['count'] = long(1)
            # memory detail info #
            else:
                prop = tmplist[0]
                val = tmplist[1]

                try:
                    if checklist[checkCnt] == prop:
                        checkCnt += 1

                        val = long(val)
                        try:
                            ptable[mtype][prop] += val
                        except:
                            ptable[mtype][prop] = val

                        if isInaccessable:
                            try:
                                ptable[mtype]['NOPM'] += val
                            except:
                                ptable[mtype]['NOPM'] = val
                except:
                    pass

        # save the number of mapping #
        ptable['FILE']['count'] = len(ftable)
        ptable['SHM']['count'] = len(stable)

        del buf, ptable, ftable, stable



    def saveProcWchanData(self, path, tid):
        wchanBuf = self.saveTaskData(path, tid, 'wchan')

        try:
            if wchanBuf[0] == '0':
                self.procData[tid]['wchan'] = 'RUNNING'
            else:
                self.procData[tid]['wchan'] = wchanBuf[0]
        except:
            self.procData[tid]['wchan'] = ''



    def saveGpuData(self):
        try:
            if not SysMgr.gpuEnable or \
                not self.gpuCoreList:
                return
        except:
            self.gpuCoreList = {}

        devList = [
            '/sys/devices', # nVIDIA tegra #
            ]

        # get candidate list for target GPU device #
        if not self.gpuCoreList:
            candList = self.gpuCoreList
            for devPath in devList:
                try:
                    for targetDir in os.listdir(devPath):
                        path = '%s/%s' % (devPath, targetDir)
                        if path in candList:
                            continue

                        try:
                            if 'devfreq' in os.listdir(path):
                                candList[path] = dict()
                        except:
                            pass
                except:
                    pass

        # no gpu supported #
        if not self.gpuCoreList:
            SysMgr.gpuEnable = False
            return

        # read gpu stat from list #
        for cand, value in self.gpuCoreList.items():
            try:
                target = None

                # save target device info #
                if not 'uevent' in value:
                    self.gpuCoreList[cand]['uevent'] = \
                        open('%s/uevent' % cand, 'r')
                fd = self.gpuCoreList[cand]['uevent']
                fd.seek(0)
                target = cand[cand.rfind('/')+1:]
                self.gpuData[target] = dict()
                for item in fd.readlines():
                    attr, value = item[:-1].split('=')
                    self.gpuData[target][attr] = value

                # save target device load #
                if not 'load' in value:
                    self.gpuCoreList[cand]['load'] = \
                        open('%s/load' % cand, 'r')
                fd = self.gpuCoreList[cand]['load']
                fd.seek(0)
                self.gpuData[target]['CUR_LOAD'] = \
                    long(fd.readline()[:-1]) / 10

                # save current clock of target device #
                if not 'curfreq' in value:
                    self.gpuCoreList[cand]['curfreq'] = \
                        open('%s/devfreq/%s/cur_freq' % (cand, target), 'r')
                fd = self.gpuCoreList[cand]['curfreq']
                fd.seek(0)
                self.gpuData[target]['CUR_FREQ'] = \
                    long(fd.readline()[:-1]) / 1000000

                # save min clock of target device #
                if not 'minfreq' in value:
                    self.gpuCoreList[cand]['minfreq'] = \
                        open('%s/devfreq/%s/min_freq' % (cand, target), 'r')
                fd = self.gpuCoreList[cand]['minfreq']
                fd.seek(0)
                self.gpuData[target]['MIN_FREQ'] = \
                    long(fd.readline()[:-1]) / 1000000

                # save max clock of target device #
                if not 'maxfreq' in value:
                    self.gpuCoreList[cand]['maxfreq'] = \
                        open('%s/devfreq/%s/max_freq' % (cand, target), 'r')
                fd = self.gpuCoreList[cand]['maxfreq']
                fd.seek(0)
                self.gpuData[target]['MAX_FREQ'] = \
                    long(fd.readline()[:-1]) / 1000000
            except:
                pass



    def saveProcSchedData(self, path, tid):
        self.procData[tid]['execTime'] = long(0)
        self.procData[tid]['waitTime'] = long(0)

        if not SysMgr.schedstatEnable:
            return

        try:
            schedBuf = self.saveTaskData(path, tid, 'schedstat')
            if len(schedBuf) == 0:
                SysMgr.schedstatEnable = False
                return

            SCHED_POLICY = schedBuf[0].split()
            self.procData[tid]['execTime'] = float(SCHED_POLICY[0])
            self.procData[tid]['waitTime'] = float(SCHED_POLICY[1])
            self.procData[tid]['nrSlice'] = float(SCHED_POLICY[2])
        except:
            return



    def isKernelThread(self, tid):
        ppid = self.procData[tid]['stat'][self.ppidIdx]
        if ppid == '2':
            return True
        else:
            return False



    def saveCmdlineData(self, path, tid):
        if not SysMgr.cmdlineEnable:
            return

        # check kernel thread #
        if self.isKernelThread(tid):
            self.procData[tid]['cmdline'] = ''
            return

        # check main thread to remove redundant operation #
        if SysMgr.isThreadTopMode():
            mainID = self.procData[tid]['mainID']
            if mainID in self.procData:
                if 'cmdline' in self.procData[mainID]:
                    self.procData[tid]['cmdline'] = \
                        self.procData[mainID]['cmdline']
                    return

        # save cmdline info #
        self.procData[tid]['cmdline'] = \
            SysMgr.getCmdline(tid)

        if SysMgr.isThreadTopMode():
            if mainID in self.procData:
                self.procData[mainID]['cmdline'] = \
                    self.procData[tid]['cmdline']



    def saveTaskData(self, path, tid, name):
        buf = []

        try:
            fd = '%sFd' % name
            self.prevProcData[tid][fd].seek(0)
            self.procData[tid][fd] = self.prevProcData[tid][fd]
            buf = self.procData[tid][fd].readlines()
        except:
            try:
                newPath = "%s/%s" % (path, name)
                newFd = self.procData[tid][fd] = open(newPath, 'r')
                buf = newFd.readlines()

                # fd resource is about to run out #
                if SysMgr.maxKeepFd < newFd.fileno():
                    newFd.close()
                    self.procData[tid][fd] = None
                    self.reclaimFds()
            except:
                SysMgr.printOpenWarn(newPath)

        return buf



    def saveCgroupData(self, path, tid):
        if not SysMgr.cgroupEnable:
            return

        cgroupBuf = self.saveTaskData(path, tid, 'cgroup')

        cstr = ''
        for item in cgroupBuf:
            clist = item[:-1].split(':')
            if len(clist) != 3 or clist[-1] == '/':
                continue
            cstr = '%s%s:%s, ' % (cstr, clist[1], clist[2])

        if len(cstr) > 0:
            self.procData[tid]['cgroup'] = cstr[:-2]



    def saveProcStatusData(self, path, tid):
        if not tid in self.procData:
            return

        statusBuf = self.saveTaskData(path, tid, 'status')

        if not self.procData[tid]['status']:
            self.procData[tid]['status'] = {}

        # check status change #
        self.procData[tid]['statusOrig'] = statusBuf
        if tid in self.prevProcData and \
            'statusOrig' in self.prevProcData[tid] and \
            self.prevProcData[tid]['statusOrig'] == statusBuf:
            self.procData[tid]['status'] = self.prevProcData[tid]['status']
            del self.prevProcData[tid]['statusOrig']
        else:
            for line in statusBuf:
                try:
                    statusList = line.split(':')
                    self.procData[tid]['status'][statusList[0]] = \
                        statusList[1].strip()
                except:
                    pass

        stat = 'statm'
        mainID = self.procData[tid]['mainID']
        if mainID in self.procData and \
            stat in self.procData[mainID] and  \
            self.procData[mainID][stat]:
            self.procData[tid][stat] = \
                self.procData[mainID][stat]
        else:
            statmBuf = self.saveTaskData(path, tid, stat)
            if statmBuf:
                self.procData[tid][stat] = statmBuf[0].split()
                if mainID in self.procData:
                    self.procData[mainID][stat] = self.procData[tid][stat]



    def saveProcData(self, path, tid, pid=None):
        def getStatBuf(self, path, tid):
            self.procData[tid]['statFd'] = open(path, 'r')
            statBuf = self.procData[tid]['statFd'].readlines()[0]

            if tid in self.prevProcData:
                self.prevProcData[tid]['alive'] = True

            # fd resource is about to run out #
            if SysMgr.maxKeepFd < \
                self.procData[tid]['statFd'].fileno():
                self.procData[tid]['statFd'].close()
                self.procData[tid]['statFd'] = None
                self.reclaimFds()

            return statBuf

        # initialize task #
        if not tid in self.procData:
            if not pid:
                pid = tid
            self.procData[tid] = dict(self.init_procData)
            self.procData[tid]['mainID'] = pid
            self.procData[tid]['taskPath'] = path
            self.procData[tid]['fdList'] = {}

        statPath = "%s/%s" % (path, 'stat')

        # save stat data #
        try:
            if tid in self.prevProcData and \
                'statFd' in self.prevProcData[tid] and \
                self.prevProcData[tid]['statFd']:
                self.prevProcData[tid]['statFd'].seek(0)
                self.procData[tid]['statFd'] = self.prevProcData[tid]['statFd']
                statBuf = self.procData[tid]['statFd'].readlines()[0]
                self.prevProcData[tid]['alive'] = True
            else:
                statBuf = getStatBuf(self, statPath, tid)
        except:
            SysMgr.printOpenWarn(statPath)
            self.procData.pop(tid, None)
            self.abnormalTaskList[pid] = '?'
            return False

        # check stat change #
        self.procData[tid]['statOrig'] = statBuf
        if tid in self.prevProcData and \
            'statOrig' in self.prevProcData[tid] and \
            self.prevProcData[tid]['statOrig'] == statBuf:
            self.procData[tid]['stat'] = self.prevProcData[tid]['stat']
            del self.prevProcData[tid]['statOrig']
            self.procData[tid]['changed'] = False
        else:
            # convert string to list #
            statList = statBuf.split()

            # merge comm parts that splited by space #
            statList = SysMgr.updateStatList(statList, self.commIdx)

            # convert type of values #
            self.procData[tid]['stat'] = statList
            statList[self.majfltIdx] = long(statList[self.majfltIdx])
            statList[self.utimeIdx] = long(statList[self.utimeIdx])
            statList[self.stimeIdx] = long(statList[self.stimeIdx])
            statList[self.btimeIdx] = long(statList[self.btimeIdx])
            statList[self.cutimeIdx] = long(statList[self.cutimeIdx])
            statList[self.cstimeIdx] = long(statList[self.cstimeIdx])

        # set comm #
        comm = self.procData[tid]['stat'][self.commIdx][1:-1]

        # check task status #
        tstat = self.procData[tid]['stat'][self.statIdx]
        if tstat != 'S' and tstat != 'R' and tstat != 'I':
            self.abnormalTaskList[tid] = tstat

        # change sched priority #
        for item in SysMgr.schedFilter:
            target = str(item[2])
            if target == '':
                target = tid
            elif tid != target and \
                not target in comm:
                continue

            # set deadline sched #
            if item[0].upper() == 'D':
                runtime, deadline, period = \
                    SysMgr.getDeadlineArgs(item[1])

                SysMgr.setDeadlinePriority(\
                    long(tid), runtime, deadline, period)
            # set other scheds #
            else:
                SysMgr.setPriority(long(tid), item[0], long(item[1]))

        # change CPU affinity #
        if len(SysMgr.affinityFilter) > 0:
            alist = list(SysMgr.affinityFilter)
            for idx, item in enumerate(alist):
                val = item[1]
                if tid != val and not val in comm:
                    continue

                try:
                    mask = item[0]
                    if val == tid or val in comm:
                        SysMgr.setAffinity(mask, [tid])

                    flag = item[2]
                    if flag != 'CONT':
                        SysMgr.affinityFilter.remove(item)
                except:
                    pass

        # send signal #
        if len(SysMgr.killFilter) > 0:
            slist = list(SysMgr.killFilter)
            for idx, item in enumerate(slist):
                val = item[0]
                sig = item[1]
                flag = item[2]
                if tid != val and not val in comm:
                    continue

                try:
                    os.kill(long(tid), sig)
                    SysMgr.printInfo(\
                        "sent %s to %s(%s)" % \
                            (ConfigMgr.SIG_LIST[sig], comm, tid))
                    if flag != 'CONT':
                        SysMgr.killFilter.remove(item)
                except:
                    pass

        # save io data #
        if SysMgr.blockEnable:
            ioBuf = self.saveTaskData(path, tid, 'io')
            for line in ioBuf:
                line = line.split()
                if line[0] == 'read_bytes:' or line[0] == 'write_bytes:':
                    if self.procData[tid]['io'] is None:
                        self.procData[tid]['io'] = {}
                    self.procData[tid]['io'][line[0][:-1]] = long(line[1])

        # save perf fds #
        if SysMgr.perfGroupEnable and \
            tid in self.prevProcData and \
            'perfFds' in self.prevProcData[tid]:
            self.procData[tid]['perfFds'] = \
                self.prevProcData[tid]['perfFds']

        # save oom_score #
        if SysMgr.oomEnable:
            self.updateOOMScore(path, tid)

        # save namespace #
        if SysMgr.nsEnable:
            self.updateNamespace(path, tid)

        return True



    def updateNamespace(self, path, tid):
        nsPath = "%s/%s" % (path, 'ns')
        try:
            for items in os.walk(nsPath):
                for node in items[2]:
                    value = os.readlink(\
                        os.path.join(items[0], node))[len(node)+1:]
                    if not value:
                        continue

                    value = value[1:-1]

                    if not node in self.nsData:
                        self.nsData[node] = {}

                    if not value in self.nsData[node]:
                        self.nsData[node][value] = {tid: 0}
                    else:
                        self.nsData[node][value][tid] = 0
        except:
            comm = self.procData[tid]['stat'][self.commIdx][1:-1]
            SysMgr.printWarn(\
                'Fail to read namespace value for %s(%s)' % \
                    (comm, tid), reason=True)



    def updateOOMScore(self, path, tid):
        # check main thread to remove redundant operation #
        if SysMgr.isThreadTopMode():
            mainID = self.procData[tid]['mainID']
            if mainID in self.procData:
                if 'oomScore' in self.procData[mainID]:
                    self.procData[tid]['oomScore'] = \
                        self.procData[mainID]['oomScore']
                    self.procData[tid]['oomFd'] = \
                        self.procData[mainID]['oomFd']
                    return

        try:
            self.prevProcData[tid]['oomFd'].seek(0)
            self.procData[tid]['oomFd'] = self.prevProcData[tid]['oomFd']
            self.procData[tid]['oomScore'] = \
                long(self.procData[tid]['oomFd'].readline())
        except:
            try:
                oomPath = "%s/%s" % (path, 'oom_score')
                oomFd = self.procData[tid]['oomFd'] = open(oomPath, 'r')
                self.procData[tid]['oomScore'] = \
                    long(self.procData[tid]['oomFd'].readline())

                # fd resource is about to run out #
                if SysMgr.maxKeepFd < oomFd.fileno():
                    oomFd.close()
                    self.procData[tid]['oomFd'] = None
                    self.reclaimFds()
                elif SysMgr.isThreadTopMode():
                    if mainID in self.procData:
                        self.procData[mainID]['oomScore'] = \
                            self.procData[tid]['oomScore']
                        self.procData[mainID]['oomFd'] = \
                            self.procData[tid]['oomFd']
            except:
                SysMgr.printOpenWarn(oomPath)

                self.procData.pop(tid, None)



    def reclaimFds(self, nrReq=64):
        nrRclm = long(0)
        for pid, val in sorted(self.procData.items(), key=lambda x:int(x[0])):
            try:
                val['schedstatFd'].close()
                val['schedstatFd'] = None
                nrRclm += 1
            except:
                pass

            try:
                val['wchanFd'].close()
                val['wchanFd'] = None
                nrRclm += 1
            except:
                pass

            try:
                val['ioFd'].close()
                val['ioFd'] = None
                nrRclm += 1
            except:
                pass

            try:
                val['statFd'].close()
                val['statFd'] = None
                nrRclm += 1
            except:
                pass

            try:
                val['statusFd'].close()
                val['statusFd'] = None
                nrRclm += 1
            except:
                pass

            try:
                val['cgroupFd'].close()
                val['cgroupFd'] = None
                nrRclm += 1
            except:
                pass

            try:
                val['statmFd'].close()
                val['statmFd'] = None
                nrRclm += 1
            except:
                pass

            try:
                val['oomFd'].close()
                val['oomFd'] = None
                nrRclm += 1
            except:
                pass

            if nrRclm > nrReq:
                return nrRclm



    def printSystemUsage(self):
        vmData = self.vmData
        prevVmData = self.prevVmData
        memData = self.memData
        prevMemData = self.prevMemData

        # total memory #
        try:
            totalMem = memData['MemTotal'] >> 10
        except:
            totalMem = long(0)
            SysMgr.printWarn("Fail to get totalMem")

        # free memory #
        try:
            freeMem = memData['MemFree'] >> 10
            freeMemDiff = freeMem - (prevMemData['MemFree'] >> 10)
        except:
            freeMem = freeMemDiff = long(0)
            SysMgr.printWarn("Fail to get freeMem")

        # available memory #
        try:
            if SysMgr.freeMemEnable:
                raise Exception()

            # assume MemAvailable #
            if not 'MemAvailable' in memData:
                memData['MemAvailable'] = \
                    memData['MemFree'] + \
                    memData['Inactive(file)'] + \
                    memData['SReclaimable'] + \
                    memData['SwapCached']

            availMem = memData['MemAvailable'] >> 10
            if 'MemAvailable' in prevMemData:
                availMemDiff = \
                    availMem - (prevMemData['MemAvailable'] >> 10)
            else:
                availMemDiff = long(0)
        except:
            SysMgr.freeMemEnable = True
            availMem = availMemDiff = long(0)

        # anonymous memory #
        try:
            actAnonMem = vmData['nr_active_anon'] >> 8
            inactAnonMem = vmData['nr_inactive_anon'] >> 8
            totalAnonMem = vmData['nr_anon_pages'] >> 8
            anonMemDiff = (vmData['nr_anon_pages'] - \
                self.prevVmData['nr_anon_pages']) >> 8
        except:
            actAnonMem = inactAnonMem = totalAnonMem = anonMemDiff = long(0)
            SysMgr.printWarn("Fail to get anonMem")

        # file memory #
        try:
            actFileMem = vmData['nr_active_file'] >> 8
            inactFileMem = vmData['nr_inactive_file'] >> 8
            totalFileMem = vmData['nr_file_pages'] >> 8
            fileMemDiff = (vmData['nr_file_pages'] - \
                self.prevVmData['nr_file_pages']) >> 8
        except:
            actFileMem = inactFileMem = totalFileMem = fileMemDiff = long(0)
            SysMgr.printWarn("Fail to get fileMem")

        # dirty memory #
        try:
            pgDirty = vmData['nr_dirty']

            '''
            dirtyRatio = \
                long((vmData['nr_dirty'] / \
                float(vmData['nr_dirty_threshold'])) * 100)
            dirtyBgRatio = \
                long((vmData['nr_dirty'] / \
                float(vmData['nr_dirty_background_threshold'])) * 100)
            '''
        except:
            pgDirty = long(0)
            SysMgr.printWarn("Fail to get dirtyMem")

        # slab memory #
        try:
            slabReclm = vmData['nr_slab_reclaimable'] >> 8
            slabUnReclm = vmData['nr_slab_unreclaimable'] >> 8
            slabReclmDiff = \
                vmData['nr_slab_reclaimable'] - \
                self.prevVmData['nr_slab_reclaimable']
            slabUnReclmDiff = \
                vmData['nr_slab_unreclaimable'] - \
                self.prevVmData['nr_slab_unreclaimable']
            totalSlabMem = \
                (vmData['nr_slab_reclaimable'] + \
                vmData['nr_slab_unreclaimable']) >> 8
            slabMemDiff = (slabReclmDiff + slabUnReclmDiff) >> 8
        except:
            slabReclm = slabUnReclm = slabReclmDiff = \
                slabUnReclmDiff = totalSlabMem = slabMemDiff = long(0)
            SysMgr.printWarn("Fail to get slabMem")

        totalCacheMem = totalFileMem + totalSlabMem

        # kernel memory #
        try:
            totalKernelMem = \
                totalMem - (totalAnonMem + totalCacheMem + freeMem)
        except:
            totalKernelMem =  0

        # fault #
        try:
            nrMajFault = vmData['pgmajfault'] - self.prevVmData['pgmajfault']
            nrTotalFault = vmData['pgfault'] - self.prevVmData['pgfault']
            nrMinFault = nrTotalFault - nrMajFault
        except:
            nrMajFault = nrTotalFault = nrMinFault = long(0)
            SysMgr.printWarn("Fail to get faultMem")

        # paged in/out from/to disk #
        try:
            pgInMemDiff = \
                (vmData['pgpgin'] - self.prevVmData['pgpgin']) >> 10
            pgOutMemDiff = \
                (vmData['pgpgout'] - self.prevVmData['pgpgout']) >> 10
        except:
            pgInMemDiff = pgOutMemDiff = long(0)
            SysMgr.printWarn("Fail to get pgMem")

        # swap memory #
        try:
            swapTotal = vmData['swapTotal'] >> 10
            swapUsage = vmData['swapUsed'] >> 10
            swapUsageDiff = \
                (self.prevVmData['swapUsed'] - vmData['swapUsed']) >> 10
            swapInMem = \
                (vmData['pswpin'] - self.prevVmData['pswpin']) >> 10
            swapOutMem = \
                (vmData['pswpout'] - self.prevVmData['pswpout']) >> 10
        except:
            swapTotal = swapUsage = swapUsageDiff = swapInMem = swapOutMem = long(0)
            SysMgr.printWarn("Fail to get swapMem")

        # background reclaim #
        try:
            pgRclmBg = long(0)
            if 'pgsteal_kswapd' in vmData:
                pgRclmBg += \
                    vmData['pgsteal_kswapd'] - \
                    self.prevVmData['pgsteal_kswapd']
            if 'pgsteal_kswapd_normal' in vmData:
                pgRclmBg += \
                    vmData['pgsteal_kswapd_normal'] - \
                    self.prevVmData['pgsteal_kswapd_normal']
            if 'pgsteal_kswapd_high' in vmData:
                pgRclmBg += \
                    vmData['pgsteal_kswapd_high'] - \
                    self.prevVmData['pgsteal_kswapd_high']
            if 'pgsteal_kswapd_dma' in vmData:
                pgRclmBg += \
                    vmData['pgsteal_kswapd_dma'] - \
                    self.prevVmData['pgsteal_kswapd_dma']
            if 'pgsteal_kswapd_dma32' in vmData:
                pgRclmBg += \
                    vmData['pgsteal_kswapd_dma32'] - \
                    self.prevVmData['pgsteal_kswapd_dma32']
            if 'pgsteal_kswapd_movable' in vmData:
                pgRclmBg += \
                    vmData['pgsteal_kswapd_movable'] - \
                    self.prevVmData['pgsteal_kswapd_movable']

            # convert to MB #
            #pgRclmBg = pgRclmBg >> 8

            try:
                nrBgReclaim = \
                    vmData['pageoutrun'] - \
                    self.prevVmData['pageoutrun']
            except:
                nrBgReclaim = long(0)
        except:
            pgRclmBg = nrBgReclaim = long(0)
            SysMgr.printWarn("Fail to get bgReclmMem")

        # direct reclaim #
        try:
            pgRclmFg = long(0)
            if 'pgsteal_direct' in vmData:
                pgRclmFg += \
                    vmData['pgsteal_direct'] - \
                    self.prevVmData['pgsteal_direct']
            if 'pgsteal_direct_normal' in vmData:
                pgRclmFg += \
                    vmData['pgsteal_direct_normal'] - \
                    self.prevVmData['pgsteal_direct_normal']
            if 'pgsteal_direct_high' in vmData:
                pgRclmFg += \
                    vmData['pgsteal_direct_high'] - \
                    self.prevVmData['pgsteal_direct_high']
            if 'pgsteal_direct_dma' in vmData:
                pgRclmFg += \
                    vmData['pgsteal_direct_dma'] - \
                    self.prevVmData['pgsteal_direct_dma']
            if 'pgsteal_direct_dma32' in vmData:
                pgRclmFg += \
                    vmData['pgsteal_direct_dma32'] - \
                    self.prevVmData['pgsteal_direct_dma32']
            if 'pgsteal_direct_movable' in vmData:
                pgRclmFg += \
                    vmData['pgsteal_direct_movable'] - \
                    self.prevVmData['pgsteal_direct_movable']

            # convert to MB #
            #pgRclmFg = pgRclmFg >> 8

            try:
                nrDrReclaim = \
                    vmData['allocstall'] - \
                    self.prevVmData['allocstall']
            except:
                nrDrReclaim = long(0)
        except:
            pgRclmFg = nrDrReclaim = long(0)
            SysMgr.printWarn("Fail to get drReclmMem")


        # mlock #
        try:
            pgMlock = vmData['nr_mlock']
            #mappedMem = vmData['nr_mapped'] >> 8
        except:
            pgMlock = long(0)
            SysMgr.printWarn("Fail to get mlockMem")

        # pending #
        try:
            nrBlocked = self.cpuData['procs_blocked']['procs_blocked']
        except:
            nrBlocked = long(0)
            SysMgr.printWarn("Fail to get nrBlocked")

        # cma mem #
        try:
            if 'CmaTotal' in memData:
                cmaTotalMem = memData['CmaTotal']

                if 'CmaFree' in memData:
                    cmaFreeMem = memData['CmaFree']
                else:
                    cmaFreeMem = long(0)
                if 'CmaDeviceAlloc' in memData:
                    cmaDevMem = memData['CmaDeviceAlloc']
                else:
                    cmaDevMem = long(0)
            else:
                cmaTotalMem = long(0)
        except:
            cmaTotalMem = cmaFreeMem = cmaDevMem = long(0)
            SysMgr.printWarn("Fail to get cmaMem")

        try:
            pass
            '''
            shMem = vmData['nr_shmem'] >> 8
            pageTableMem = vmData['nr_page_table_pages'] >> 8
            kernelStackMem = vmData['nr_kernel_stack'] * 8 >> 10
            '''
        except:
            SysMgr.printWarn("Fail to get etcMem")

        # check available memory type #
        if SysMgr.freeMemEnable:
            memTitle = 'Free'
        else:
            memTitle = 'Avl'

        # get iowait time #
        #iowait = SysMgr.getIowaitTime()

        # print system status menu #
        SysMgr.addPrint(
            ("%s\n%s%s\n" % (twoLine,\
            (("{0:^7}|{1:>5}({2:^3}/{3:^3}/{4:^3}/{5:^3})|"\
            "{6:>5}({7:>4}/{8:>5}/{9:>5}/{10:>4})|"\
            "{11:>6}({12:>4}/{13:>3}/{14:>3})|{15:^9}|{16:^7}|{17:^7}|"\
            "{18:^7}|{19:^8}|{20:^7}|{21:^8}|{22:^12}|\n").\
            format("ID", "CPU", "Usr", "Ker", "Blk", "IRQ",\
            memTitle, "Diff", "User", "Cache", "Kern", \
            "Swap", "Diff", "In", "Out", "PgRclm", "BlkRW", "NrFlt", \
            "PrBlk", "NrSIRQ", "PgMlk", "PgDrt", "Network")), oneLine)), \
            newline = 3)

        interval = SysMgr.uptimeDiff
        if interval == 0:
            return

        try:
            nrCtxSwc = \
                self.cpuData['ctxt']['ctxt'] - \
                self.prevCpuData['ctxt']['ctxt']
        except:
            nrCtxSwc = long(0)

        try:
            nrIrq = \
                self.cpuData['intr']['intr'] - \
                self.prevCpuData['intr']['intr']
        except:
            nrIrq = long(0)

        try:
            nrSoftIrq = \
                self.cpuData['softirq']['softirq'] - \
                self.prevCpuData['softirq']['softirq']
        except:
            nrSoftIrq = long(0)

        # get total CPU usage #
        nowData = self.cpuData['all']
        prevData = self.prevCpuData['all']

        if SysMgr.cpuAvrEnable:
            nrCore = SysMgr.nrCore
            maxUsage = 100
        else:
            nrCore = 1
            maxUsage = 100 * SysMgr.nrCore

        # initialize accumulated CPU values #
        userUsage = kerUsage = ioUsage = irqUsage = idleUsage = long(0)
        coreStats = dict()

        for idx, value in sorted(self.cpuData.items(),\
            key=lambda x:int(x[0]) if str(x[0]).isdigit() else 0, \
            reverse=False):
            try:
                nowData = self.cpuData[int(idx)]

                if not long(idx) in self.prevCpuData:
                    coreStat = "{0:<7}|{1:>5}({2:^3}/{3:^3}/{4:^3}/{5:^3})|".\
                        format("Core/" + str(idx), '- %', '-', '-', '-', '-')
                    SysMgr.addPrint('%s\n' % coreStat)
                    continue

                prevData = self.prevCpuData[int(idx)]

                coreStats[idx] = dict()

                #-------------------- SIMPLE STAT --------------------#
                userStat = nowData['user'] - prevData['user']
                niceStat = nowData['nice'] - prevData['nice']
                userCoreUsage = long((userStat + niceStat) / interval)

                kerCoreUsage = \
                    long((nowData['system'] - prevData['system']) / interval)

                irqStat = nowData['irq'] - prevData['irq']
                softirqStat = nowData['softirq'] - prevData['softirq']
                irqCoreUsage = long((irqStat + softirqStat) / interval)

                ioCoreUsage = \
                    long((nowData['iowait'] - prevData['iowait']) / interval)

                idleCoreUsage = \
                    long((nowData['idle'] - prevData['idle']) / interval)

                #-------------------- REVISED STAT --------------------#
                # get scale factor #
                totalStat = \
                    userCoreUsage + kerCoreUsage + \
                    ioCoreUsage + irqCoreUsage + idleCoreUsage
                scale = 100 / float(totalStat)

                # get CPU stats #
                coreStats[idx]['user'] = long(userCoreUsage * scale)
                userUsage += coreStats[idx]['user']
                coreStats[idx]['kernel'] = long(kerCoreUsage * scale)
                kerUsage += coreStats[idx]['kernel']
                coreStats[idx]['io'] = long(ioCoreUsage * scale)
                ioUsage += coreStats[idx]['io']
                coreStats[idx]['irq'] = long(irqCoreUsage * scale)
                irqUsage += coreStats[idx]['irq']
                coreStats[idx]['idle'] = long(idleCoreUsage * scale)
                idleUsage += coreStats[idx]['idle']
            except:
                pass

        # divide total CPU usage by the number of cores #
        userUsage = long(userUsage / nrCore)
        kerUsage = long(kerUsage / nrCore)
        ioUsage = long(ioUsage / nrCore)
        irqUsage = long(irqUsage / nrCore)
        idleUsage = long(idleUsage / nrCore)

        # get total usage #
        if idleUsage < maxUsage:
            totalUsage = maxUsage - idleUsage - ioUsage
        else:
            totalUsage = long(0)

        # get network usage in bytes #
        (netIn, netOut) = \
            self.getNetworkUsage(\
            SysMgr.prevNetstat, SysMgr.netstat)

        # convert network usage #
        try:
            netIO = '%s/%s' % \
                (UtilMgr.convSize2Unit(netIn, True),\
                UtilMgr.convSize2Unit(netOut, True))
        except:
            netIO = '-/-'

        # check available memory #
        if availMem == 0:
            availMem = freeMem
            availMemDiff = freeMemDiff

        # make total stat string #
        totalCoreStat = \
            ("{0:<7}|{1:>5}({2:^3}/{3:^3}/{4:^3}/{5:^3})|"
            "{6:>5}({7:>4}/{8:>5}/{9:>5}/{10:>4})|"
            "{11:>6}({12:>4}/{13:>3}/{14:>3})|{15:^9}|{16:^7}|"
            "{17:^7}|{18:^7}|{19:^8}|{20:^7}|{21:^8}|{22:^12}|\n").\
            format("Total", '%d %%' % totalUsage, userUsage, kerUsage, \
            ioUsage, irqUsage, availMem, availMemDiff, totalAnonMem, \
            totalCacheMem, totalKernelMem, swapUsage, swapUsageDiff, \
            swapInMem, swapOutMem, '%s/%s' % (pgRclmBg, pgRclmFg), \
            '%s/%s' % (pgInMemDiff, pgOutMemDiff), \
            nrMajFault, nrBlocked, nrSoftIrq, pgMlock, pgDirty, netIO)

        SysMgr.addPrint(totalCoreStat)

        # get temperature #
        if SysMgr.cpuEnable or SysMgr.gpuEnable:
            coreTempData = {}
            tempDirList = []
            tempPath = '/sys/class/hwmon'

            try:
                self.tempFdList
            except:
                self.tempFdList = dict()

            try:
                for item in os.listdir(tempPath):
                    devPath = '%s/%s/name' % (tempPath, item)
                    if os.path.isfile(devPath):
                        tempDirList.append(devPath)

                    devPath = '%s/%s/device/name' % (tempPath, item)
                    if os.path.isfile(devPath):
                        tempDirList.append(devPath)
            except:
                pass

            tempPath = []
            for tempDir in tempDirList:
                try:
                    if tempDir in self.tempFdList:
                        fd = self.tempFdList[tempDir]
                        fd.seek(0)
                    else:
                        fd = open(tempDir, 'r')
                        self.tempFdList[tempDir] = fd

                    if fd.readline()[:-1] == 'coretemp':
                        tempPath.append(os.path.dirname(tempDir))
                except:
                    pass

            # /sys/class/hwmon #
            for hwPath in tempPath:
                tempDirList = \
                    [ '%s/%s' % (hwPath, item.replace('input', 'label')) \
                    for item in os.listdir(hwPath) if item.endswith('_input') ]
                phyId = long(0)
                tempData = {}

                for tempDir in tempDirList:
                    try:
                        if tempDir in self.tempFdList:
                            lfd = self.tempFdList[tempDir]
                            lfd.seek(0)
                        else:
                            lfd = open(tempDir, 'r')
                            self.tempFdList[tempDir] = lfd

                        name = lfd.readline()[:-1]
                        if name.startswith('Physical id ') or \
                            name.startswith('Package id '):
                            phyId = name[name.rfind(' ')+1:]
                        elif name.startswith('Core '):
                            coreId = name[name.rfind(' ')+1:]

                            tempDir = tempDir.replace('label', 'input')
                            if tempDir in self.tempFdList:
                                tfd = self.tempFdList[tempDir]
                                tfd.seek(0)
                            else:
                                tfd = open(tempDir, 'r')
                                self.tempFdList[tempDir] = tfd

                            tempData[coreId] = \
                                long(tfd.readline()[:-4])
                    except:
                        pass

                for idx, val in sorted(\
                    tempData.items(), key=lambda x:int(x[0])):
                    coreTempData['%s-%s' % (phyId, idx)] = val

            # /sys/class/thermal #
            tempPath = '/sys/class/thermal'
            try:
                tempDirList = \
                    [ '%s/%s' % (tempPath, item) \
                    for item in os.listdir(tempPath) \
                    if item.startswith('thermal_zone') ]
            except:
                tempDirList = []

            for tempDir in sorted(tempDirList):
                try:
                    ctype = None

                    with open('%s/type' % tempDir, 'r') as fd:
                        ctype = fd.readline()[:-1]

                    with open('%s/temp' % tempDir, 'r') as fd:
                        if 'CPU' in ctype:
                            coreTempData['CPU'] = long(fd.readline()[:-4])
                        elif 'GPU' in ctype:
                            coreTempData['GPU'] = long(fd.readline()[:-4])
                except:
                    pass

        # print CPU stat #
        if SysMgr.cpuEnable or \
            SysMgr.reportEnable or \
            SysMgr.jsonOutputEnable:
            percoreStats = {}

            if len(self.cpuData) > 0:
                SysMgr.addPrint('%s\n' % oneLine)

            freqPath = '/sys/devices/system/cpu/cpu'

            for idx, value in sorted(self.cpuData.items(),\
                key=lambda x:int(x[0]) if str(x[0]).isdigit() else 0, \
                reverse=False):
                try:
                    percoreStats[int(idx)] = dict()

                    if SysMgr.checkCutCond():
                        return

                    # get CPU stats #
                    userCoreUsage = coreStats[idx]['user']
                    kerCoreUsage = coreStats[idx]['kernel']
                    ioCoreUsage = coreStats[idx]['io']
                    irqCoreUsage = coreStats[idx]['irq']
                    idleCoreUsage = coreStats[idx]['idle']

                    # get total usage #
                    if idleCoreUsage < 100:
                        totalCoreUsage = 100 - idleCoreUsage - ioCoreUsage
                    else:
                        totalCoreUsage = long(0)

                    # limit total core usage in each modes #
                    if userCoreUsage > 100:
                        userCoreUsage = 100
                    if kerCoreUsage > 100:
                        kerCoreUsage = 100

                    # set percore stats #
                    percoreStats[idx]['user'] = userCoreUsage
                    percoreStats[idx]['kernel'] = kerCoreUsage
                    percoreStats[idx]['iowait'] = ioCoreUsage
                    percoreStats[idx]['irq'] = irqCoreUsage
                    percoreStats[idx]['idle'] = idleCoreUsage
                    percoreStats[idx]['total'] = totalCoreUsage

                    coreStat = "{0:<7}|{1:>5}({2:^3}/{3:^3}/{4:^3}/{5:^3})|".\
                        format("Core/%s" % idx, '%s %%' % totalCoreUsage,\
                        userCoreUsage, kerCoreUsage, ioCoreUsage, irqCoreUsage)
                except SystemExit:
                    sys.exit(0)
                except:
                    continue

                # set default path #
                defPath = '%s%s/cpufreq' % (freqPath, idx)

                # get current CPU frequency #
                try:
                    self.prevCpuData[idx]['curFd'].seek(0)
                    curFreq = self.prevCpuData[idx]['curFd'].readline()[:-1]
                    self.cpuData[idx]['curFd'] = \
                        self.prevCpuData[idx]['curFd']
                except SystemExit:
                    sys.exit(0)
                except:
                    infoPath = '%s/cpuinfo_cur_freq' % defPath
                    scalingPath = '%s/scaling_cur_freq' % defPath

                    if os.path.isfile(infoPath):
                        curPath = infoPath
                    elif os.path.isfile(scalingPath):
                        curPath = scalingPath
                    else:
                        curPath = None

                    try:
                        self.cpuData[idx]['curFd'] = open(curPath, 'r')
                        curFreq = self.cpuData[idx]['curFd'].readline()[:-1]
                    except:
                        curFreq = None

                # get CPU min frequency #
                try:
                    self.prevCpuData[idx]['minFd'].seek(0)
                    minFreq = self.prevCpuData[idx]['minFd'].readline()[:-1]
                    self.cpuData[idx]['minFd'] = \
                        self.prevCpuData[idx]['minFd']
                except SystemExit:
                    sys.exit(0)
                except:
                    infoPath = '%s/cpuinfo_min_freq' % defPath
                    scalingPath = '%s/scaling_min_freq' % defPath

                    if os.path.isfile(infoPath):
                        minPath = infoPath
                    elif os.path.isfile(scalingPath):
                        minPath = scalingPath
                    else:
                        minPath = None

                    try:
                        self.cpuData[idx]['minFd'] = open(minPath, 'r')
                        minFreq = self.cpuData[idx]['minFd'].readline()[:-1]
                    except SystemExit:
                        sys.exit(0)
                    except:
                        minFreq = None

                # get CPU max frequency #
                try:
                    self.prevCpuData[idx]['maxFd'].seek(0)
                    maxFreq = self.prevCpuData[idx]['maxFd'].readline()[:-1]
                    self.cpuData[idx]['maxFd'] = \
                        self.prevCpuData[idx]['maxFd']
                except SystemExit:
                    sys.exit(0)
                except:
                    infoPath = '%s/cpuinfo_max_freq' % defPath
                    scalingPath = '%s/scaling_max_freq' % defPath

                    if os.path.isfile(infoPath):
                        maxPath = infoPath
                    elif os.path.isfile(scalingPath):
                        maxPath = scalingPath
                    else:
                        maxPath = None

                    try:
                        self.cpuData[idx]['maxFd'] = open(maxPath, 'r')
                        maxFreq = self.cpuData[idx]['maxFd'].readline()[:-1]
                    except:
                        maxFreq = None

                # get current governor #
                try:
                    self.prevCpuData[idx]['govFd'].seek(0)
                    gov = self.prevCpuData[idx]['govFd'].readline()[:-1]
                    self.cpuData[idx]['govFd'] = \
                        self.prevCpuData[idx]['govFd']
                except SystemExit:
                    sys.exit(0)
                except:
                    govPath = '%s/scaling_governor' % defPath

                    try:
                        self.cpuData[idx]['govFd'] = open(govPath, 'r')
                        gov = self.cpuData[idx]['govFd'].readline()[:-1]
                    except:
                        gov = None

                # get core package id #
                try:
                    # get core id #
                    if idx in self.prevCpuData and \
                        'cidFd' in self.prevCpuData[idx]:
                        fd = self.prevCpuData[idx]['cidFd']
                        fd.seek(0)
                        coreId = long(fd.readline()[:-1])
                        self.cpuData[idx]['cidFd'] = fd
                    else:
                        cidPath = '%s%s/topology/core_id' % (freqPath, idx)

                        self.cpuData[idx]['cidFd'] = open(cidPath, 'r')
                        coreId = \
                            long(self.cpuData[idx]['cidFd'].readline()[:-1])

                    if coreId < 0:
                        coreId = '?'

                    # get package id #
                    if idx in self.prevCpuData and \
                        'pidFd' in self.prevCpuData[idx]:
                        fd = self.prevCpuData[idx]['pidFd']
                        fd.seek(0)
                        phyId = long(fd.readline()[:-1])
                        self.cpuData[idx]['pidFd'] = fd
                    else:
                        pidPath = \
                            '%s%s/topology/physical_package_id' % \
                                (freqPath, idx)

                        self.cpuData[idx]['pidFd'] = open(pidPath, 'r')
                        phyId = \
                            long(self.cpuData[idx]['pidFd'].readline()[:-1])

                    if phyId < 0:
                        phyId = '?'

                    cid = '%s-%s' % (phyId, coreId)
                except SystemExit:
                    sys.exit(0)
                except:
                    cid = None

                try:
                    # set frequency info #
                    coreFreq = ''
                    if curFreq:
                        coreFreq = '%d Mhz' % (long(curFreq) >> 10)
                    else:
                        coreFreq = '? Mhz'
                    if minFreq and maxFreq:
                        coreFreq = '%s [%d-%d]' % \
                            (coreFreq, long(minFreq) >> 10, long(maxFreq) >> 10)
                    coreFreq = '%20s|' % coreFreq
                except SystemExit:
                    sys.exit(0)
                except:
                    pass

                # merge core info #
                try:
                    coreFreq = '{0:^6} | {1:>3} C | {2:<1}'.\
                        format(cid, coreTempData[cid], coreFreq)
                except SystemExit:
                    sys.exit(0)
                except:
                    try:
                        coreFreq = '{0:^6} | {1:>3} C | {2:<1}'.\
                            format(cid, coreTempData['CPU'], coreFreq)
                    except:
                        if cid:
                            coreFreq = '{0:^6} | {1:>3} C | {2:<1}'.\
                                format(cid, '?', coreFreq)
                        else:
                            coreFreq = '%3s C | %s' % ('?', coreFreq)

                # merge governor info #
                try:
                    coreFreq = '{0:^13} | {1:>1}'.format(gov, coreFreq)
                except:
                    pass

                try:
                    # get length of string #
                    lenTotal = len(totalCoreStat)
                    lenCore = len(coreStat)
                    lenFreq = len(coreFreq)
                    lenLine = SysMgr.lineLength - lenCore - lenFreq - 2

                    # print graph of per-core usage #
                    if totalCoreUsage > 0:
                        coreGraph = '#' * long(lenLine * totalCoreUsage / 100)
                        coreGraph += (' ' * (lenLine - len(coreGraph)))
                    else:
                        coreGraph = ' ' * lenLine

                    SysMgr.addPrint(\
                        '%s%s| %s\n' % (coreStat, coreGraph, coreFreq))
                except SystemExit:
                    sys.exit(0)
                except:
                    pass

        # print GPU STAT #
        if SysMgr.gpuEnable:
            gpuStats = {}

            if len(self.gpuData) > 0:
                SysMgr.addPrint('%s\n' % oneLine)

            for idx, value in self.gpuData.items():
                try:
                    if SysMgr.checkCutCond():
                        return

                    totalGpuUsage = value['CUR_LOAD']
                    coreStat = "{0:<23}({1:>5})|".format(\
                        idx[:23], '%s %%' % totalGpuUsage)

                    gpuStats[idx] = totalGpuUsage

                    # set frequency info #
                    try:
                        coreFreq = '%d Mhz' % value['CUR_FREQ']
                    except:
                        coreFreq = '? Mhz'
                    if 'MIN_FREQ' in value and 'MAX_FREQ' in value and \
                        value['MIN_FREQ'] > 0 and value['MAX_FREQ'] > 0:
                        coreFreq = '%s [%d-%d]' % \
                            (coreFreq, value['MIN_FREQ'], value['MAX_FREQ'])
                    coreFreq = '%20s|' % coreFreq

                    # set temperature info #
                    try:
                        coreFreq = '%3s C | %s' % (value['TEMP'], coreFreq)
                    except:
                        try:
                            coreFreq = '%3s C | %s' % \
                                (coreTempData['GPU'], coreFreq)
                        except:
                            coreFreq = '%3s C | %s' % ('?', coreFreq)

                    lenCore = len(coreStat)
                    lenFreq = len(coreFreq)
                    lenLine = SysMgr.lineLength - lenCore - lenFreq - 2

                    # print graph of per-core usage #
                    if totalGpuUsage > 0:
                        coreGraph = '#' * long(lenLine * totalGpuUsage / 100)
                        coreGraph += (' ' * (lenLine - len(coreGraph)))
                    else:
                        coreGraph = ' ' * lenLine

                    SysMgr.addPrint(\
                        '%s%s| %s\n' % (coreStat, coreGraph, coreFreq))
                except:
                    continue

        # save report data #
        if SysMgr.reportEnable or SysMgr.jsonOutputEnable:
            self.reportData = {}

            # timestamp #
            self.reportData['timestamp'] = SysMgr.uptime
            datetime = SysMgr.getPkg('datetime', False)
            if datetime:
                self.reportData['utctime'] = \
                    datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')

            # system #
            self.reportData['system'] = {
                'pid': SysMgr.pid,
                'uptime': SysMgr.uptime,
                'interval': interval,
                'nrIrq': nrIrq,
                'nrSoftIrq': nrSoftIrq,
                }

            # load #
            try:
                loads = list(map(float, SysMgr.loadavg.split()[:3]))
                self.reportData['system']['load1m'] = loads[0]
                self.reportData['system']['load5m'] = loads[1]
                self.reportData['system']['load15m'] = loads[2]
            except:
                pass

            # CPU #
            try:
                percoreStats
            except:
                percoreStats = None

            self.reportData['cpu'] = {
                'total': totalUsage,
                'idle': idleUsage,
                'user': userUsage,
                'kernel': kerUsage,
                'irq': irqUsage,
                'iowait': ioUsage,
                'nrCore': SysMgr.nrCore,
                'percore': percoreStats
                }

            # gpu #
            try:
                self.reportData['gpu'] = gpuStats
            except:
                pass

            # memory #
            self.reportData['mem'] = {
                'total': totalMem,
                'free': freeMem,
                'available': availMem,
                'anon': totalAnonMem,
                'file': totalFileMem,
                'slab': totalSlabMem,
                'cache': totalCacheMem,
                'kernel': totalKernelMem,
                'freeDiff': freeMemDiff,
                'availableDiff': availMemDiff,
                'anonDiff': anonMemDiff,
                'fileDiff': fileMemDiff,
                'slabDiff': slabMemDiff,
                'pgDirty': pgDirty,
                'pgRclmBg': pgRclmBg,
                'pgRclmFg': pgRclmFg,
                'nrMinFlt': nrMinFault,
                'pgMlock': pgMlock
                }

            # cma #
            try:
                self.reportData['mem']['cmaTotal'] = cmaTotalMem
                self.reportData['mem']['cmaFree'] = cmaFreeMem
                self.reportData['mem']['cmaDev'] = cmaDevMem
            except:
                pass

            # swap #
            self.reportData['swap'] = {
                'total': swapTotal,
                'usage': swapUsage,
                'usageDiff': swapUsageDiff,
                'swapin': swapInMem,
                'swapout': swapOutMem
                }

            # block #
            self.reportData['block'] = {
                'read': pgInMemDiff,
                'write': pgOutMemDiff,
                'ioWait': ioUsage,
                'nrMajFlt': nrMajFault,
                'nrTask': nrBlocked
                }

            # task #
            self.reportData['task'] = {
                'nrBlocked': nrBlocked,
                'nrProc': self.nrProcess,
                'nrThread': self.nrThread,
                'nrCtx': nrCtxSwc
                }

            # network #
            self.reportData['net'] = {
                'inbound': netIn,
                'outbound': netOut
                }

            if SysMgr.sysInstance.macAddr:
                macAddr = SysMgr.sysInstance.macAddr
                macStr = '%s_%s' % (macAddr[0], macAddr[1])
                self.reportData['net']['repmac'] = macStr

            if SysMgr.networkEnable:
                SysMgr.sysInstance.updateNetworkInfo()

                for dev, value in sorted(\
                    SysMgr.sysInstance.networkInfo.items()):
                    # check value #
                    if not 'rdiff' in value or \
                        not 'tdiff' in value:
                        continue

                    self.reportData['net'][dev] = dict()
                    reportData = self.reportData['net'][dev]

                    reportData['ipaddr'] = value['ipaddr']

                    rdiff = value['rdiff']
                    tdiff = value['tdiff']

                    reportData['trans'] = {
                        'bytes': rdiff[0],
                        'packets': rdiff[1],
                        'errs': rdiff[2],
                        'drop': rdiff[3],
                        'fifo': rdiff[4],
                        'frame': rdiff[5],
                        'compressed': rdiff[6],
                        'multicast': rdiff[7]
                        }

                    reportData['recv'] = {
                        'bytes': tdiff[0],
                        'packets': tdiff[1],
                        'errs': tdiff[2],
                        'drop': tdiff[3],
                        'fifo': tdiff[4],
                        'frame': tdiff[5],
                        'compressed': tdiff[6],
                        'multicast': tdiff[7]
                        }

            # storage #
            if SysMgr.diskEnable:
                SysMgr.sysInstance.updateStorageInfo()

                # copy storage data into report data structure #
                self.reportData['storage'] = \
                    deepcopy(SysMgr.sysInstance.storageData)

                prevStorageData = SysMgr.sysInstance.prevStorageData

                # calculate diff of read /write on each devices #
                for dev, value in sorted(self.reportData['storage'].items()):
                    # get read size on this interval #
                    try:
                        value['read'] -= prevStorageData[dev]['read']
                    except:
                        value['read'] = long(0)

                    # get write size on this interval #
                    try:
                        value['write'] -= prevStorageData[dev]['write']
                    except:
                        value['write'] = long(0)

                    # get readtime on this interval #
                    try:
                        value['readtime'] -= prevStorageData[dev]['readtime']
                    except:
                        value['readtime'] = long(0)

                    # get writetime on this interval #
                    try:
                        value['writetime'] -= prevStorageData[dev]['writetime']
                    except:
                        value['writetime'] = long(0)

                    # get iotime on this interval #
                    try:
                        value['iotime'] -= prevStorageData[dev]['iotime']
                    except:
                        value['iotime'] = long(0)

                    # get iowtime on this interval #
                    try:
                        value['iowtime'] -= prevStorageData[dev]['iowtime']
                    except:
                        value['iowtime'] = long(0)

                    # get avq on this interval #
                    try:
                        value['avq'] = value['iowtime'] / value['iotime']
                    except:
                        value['avq'] = long(0)
            else:
                self.reportData['storage'] = dict()

            if SysMgr.jsonOutputEnable:
                SysMgr.jsonData.update(self.reportData)



    def setProcUsage(self):
        interval = SysMgr.uptimeDiff

        for pid, value in self.procData.items():
            try:
                nowData = value['stat']
                prevData = self.prevProcData[pid]['stat']

                value['runtime'] = \
                    long(SysMgr.uptime - \
                    (float(nowData[self.starttimeIdx]) / 100))

                if value['io']:
                    value['read'] = value['io']['read_bytes'] - \
                            self.prevProcData[pid]['io']['read_bytes']
                    value['write'] = value['io']['write_bytes'] - \
                            self.prevProcData[pid]['io']['write_bytes']

                # check stat change #
                if not value['changed']:
                    value['utime'] = value['stime'] = long(0)
                    value['ttime'] = value['btime'] = value['cttime'] = long(0)
                    continue

                value['majflt'] = \
                    nowData[self.majfltIdx] - prevData[self.majfltIdx]

                utick = nowData[self.utimeIdx] - prevData[self.utimeIdx]
                value['utime'] = long(utick / interval)
                if value['utime'] >= 100 and \
                    value['stat'][self.nrthreadIdx] == '1':
                    value['utime'] = 100

                stick = nowData[self.stimeIdx] - prevData[self.stimeIdx]
                value['stime'] = long(stick / interval)
                if value['stime'] >= 100 and \
                    value['stat'][self.nrthreadIdx] == '1':
                    value['stime'] = 100

                # total time #
                value['ttime'] = utick + stick
                if SysMgr.floatEnable:
                    value['ttime'] = round(value['ttime'] / interval, 1)
                else:
                    value['ttime'] = long(value['ttime'] / interval)
                if value['ttime'] >= 100 and \
                    value['stat'][self.nrthreadIdx] == '1':
                    value['ttime'] = 100
                elif value['ttime'] == 0:
                    value['ttime'] = long(0)

                # child user time #
                cutick = nowData[self.cutimeIdx] - prevData[self.cutimeIdx]
                if SysMgr.floatEnable:
                    cutime = round(cutick / interval, 1)
                else:
                    cutime = long(cutick / interval)

                # child system time #
                cstick = nowData[self.cstimeIdx] - prevData[self.cstimeIdx]
                if SysMgr.floatEnable:
                    cstime = round(cstick / interval, 1)
                else:
                    cstime = long(cstick / interval)

                # child total time #
                value['cttime'] = cutime + cstime

                # block time #
                btick = nowData[self.btimeIdx] - prevData[self.btimeIdx]
                if SysMgr.floatEnable:
                    value['btime'] = round(btick / interval, 1)
                    if value['btime'] == 0:
                        value['btime'] = long(0)
                else:
                    value['btime'] = long(btick / interval)

                if value['ttime'] + value['btime'] > 100 and \
                    value['stat'][self.nrthreadIdx] == '1':
                    value['btime'] = 100 - value['ttime']
            except:
                value['new'] = True

                value['runtime'] = \
                    long(SysMgr.uptime - \
                    (float(nowData[self.starttimeIdx]) / 100))

                value['majflt'] = nowData[self.majfltIdx]

                # user time #
                value['utime'] = long(nowData[self.utimeIdx] / interval)
                if value['utime'] >= 100 and \
                    value['stat'][self.nrthreadIdx] == '1':
                    value['utime'] = 100
                if SysMgr.floatEnable:
                    utick = round(nowData[self.utimeIdx] / interval, 1)
                else:
                    utick = value['utime']

                # system time #
                value['stime'] = long(nowData[self.stimeIdx] / interval)
                if value['stime'] >= 100 and \
                    value['stat'][self.nrthreadIdx] == '1':
                    value['stime'] = 100
                if SysMgr.floatEnable:
                    stick = round(nowData[self.stimeIdx] / interval, 1)
                else:
                    stick = value['stime']

                # total time #
                value['ttime'] = utick + stick
                if value['ttime'] >= 100 and \
                    value['stat'][self.nrthreadIdx] == '1':
                    value['ttime'] = 100

                # child time #
                if SysMgr.floatEnable:
                    cutime = round(nowData[self.cutimeIdx] / interval, 1)
                    cstime = round(nowData[self.cstimeIdx] / interval, 1)
                else:
                    cutime = long(nowData[self.cutimeIdx] / interval)
                    cstime = long(nowData[self.cstimeIdx] / interval)
                value['cttime'] = cutime + cstime

                # block time #
                if SysMgr.floatEnable:
                    value['btime'] = \
                        round(nowData[self.btimeIdx] / interval, 1)
                else:
                    value['btime'] = long(nowData[self.btimeIdx] / interval)
                if value['ttime'] + value['btime'] > 100 and \
                    value['stat'][self.nrthreadIdx] == '1':
                    value['btime'] = 100 - value['ttime']

                if value['io']:
                    value['read'] = value['io']['read_bytes']
                    value['write'] = value['io']['write_bytes']

            # check delayacct_blkio_ticks error #
            if value['btime'] >= 100:
                value['btime'] = long(0)



    def getMemDetails(self, idx, maps):
        rss = long(0)
        sss = long(0)
        pss = long(0)
        memBuf = []

        if not maps:
            return [], 0, 0, 0

        convertFunc = UtilMgr.convSize2Unit

        for key, item in sorted(maps.items(), reverse=True):
            tmpstr = ''

            if len(item) == 0 or item['count'] == 0:
                continue

            try:
                prop = 'Size:'
                tmpstr = "%s%s%7s / " % \
                    (tmpstr, "VSS:", convertFunc(item[prop] << 10))
            except:
                tmpstr = "%s%s%7s / " % (tmpstr, prop.upper(), 0)

            try:
                prop = 'Rss:'
                tmpstr = "%s%s%7s / " % \
                    (tmpstr, prop.upper(), convertFunc(item[prop] << 10))
                rss += item[prop]
            except:
                tmpstr = "%s%s%7s / " % (tmpstr, prop.upper(), 0)

            try:
                prop = 'Pss:'
                tmpstr = "%s%s%7s / " % \
                    (tmpstr, prop.upper(), convertFunc(item[prop] << 10))
                pss += item[prop]
            except:
                tmpstr = "%s%s%7s / " % (tmpstr, prop.upper(), 0)

            try:
                prop = 'Swap:'
                tmpstr = "%s%s%7s / " % \
                    (tmpstr, prop.upper(), convertFunc(item[prop] << 10))
            except:
                tmpstr = "%s%s%7s / " % (tmpstr, prop.upper(), 0)

            try:
                prop = 'AnonHugePages:'
                tmpstr = "%s%s:%5s / " % \
                    (tmpstr, 'HUGE', convertFunc(item[prop] << 10, True))
            except:
                tmpstr = "%s%s:%5s / " % (tmpstr, 'HUGE', 0)

            try:
                prop = 'Locked:'
                tmpstr = "%s%s%6s / " % \
                    (tmpstr, 'LOCK:', convertFunc(item[prop] << 10, True))
            except:
                tmpstr = "%s%s%6s / " % (tmpstr, 'LOCK:', 0)

            try:
                prop = 'Shared_Clean:'
                sss += item[prop]
            except:
                pass

            try:
                prop = 'Shared_Dirty:'
                sss += item[prop]
                tmpstr = "%s%s:%7s / " % \
                    (tmpstr, 'SDRT', convertFunc(item[prop] << 10))
            except:
                tmpstr = "%s%s:%7s / " % (tmpstr, 'SDRT', 0)

            try:
                prop = 'Private_Dirty:'
                tmpstr = "%s%s:%7s" % \
                    (tmpstr, 'PDRT', convertFunc(item[prop] << 10))
            except:
                tmpstr = "%s%s:%7s" % (tmpstr, 'PDRT', 0)

            '''
            try:
                prop = 'NOPM'
                tmpstr = "%s%s:%5s" % \
                    (tmpstr, prop, convertFunc(item[prop] << 10, True))
            except:
                tmpstr = "%s%s:%5s" % (tmpstr, prop, 0)
            '''

            mtype = 'MEM(%s/%s)' % (key, item['count'])
            memBuf.append(\
                [key, "{0:>39} | {1:1}|\n".format(mtype, tmpstr)])

            if SysMgr.wssEnable:
                # get current WSS size #
                try:
                    wss =  convertFunc(item['Referenced:'] << 10, False)
                except:
                    wss =  0

                # get previous WSS history #
                try:
                    self.procData[idx]['wss'] = \
                        self.prevProcData[idx]['wss']
                except:
                    self.procData[idx].setdefault('wss', dict())

                    # clear reference bits #
                    try:
                        path = '%s/%s/clear_refs' % \
                            (SysMgr.procPath, idx)
                        with open(path, 'w') as fd:
                            fd.write('1')
                    except:
                        pass

                # update WSS history #
                try:
                    history = self.procData[idx]['wss'][key]
                    self.procData[idx]['wss'][key] = \
                        '%s -> %7s' % (history, wss)
                except:
                    self.procData[idx]['wss'][key] = '[%7s]' % wss

        # update pss #
        pss = pss >> 2

        # update uss #
        uss = (rss - sss) >> 2

        if not SysMgr.memEnable:
            memBuf = []

        return memBuf, rss, pss, uss



    def printDefaultUsage(self, title):
        nrNewThreads = \
            self.cpuData['processes']['processes'] - \
            self.prevCpuData['processes']['processes']

        try:
            loadlist = SysMgr.loadavg.split()[:3]
            for idx, load in enumerate(loadlist):
                loadlist[idx] = str('%.1f' % float(load))
            loadavg = '/'.join(loadlist)
        except:
            loadavg = '?'

        try:
            oom_kill = long(self.vmData['oom_kill'])
            oomstr = '[OOM: %d]'% oom_kill
        except:
            oomstr = ''

        try:
            nrCtxt = \
                self.cpuData['ctxt']['ctxt'] - self.prevCpuData['ctxt']['ctxt']
        except:
            nrCtxt = long(0)

        try:
            nrTermThreads = \
                abs(self.nrThread - nrNewThreads - self.nrPrevThread)
        except:
            nrTermThreads = long(0)

        try:
            nrIrq = \
                self.cpuData['intr']['intr'] - self.prevCpuData['intr']['intr']
        except:
            nrIrq = long(0)

        try:
            memTotal = UtilMgr.convSize2Unit(\
                self.memData['MemTotal'] << 10)
        except:
            memTotal = long(0)

        try:
            swapTotal = UtilMgr.convSize2Unit(\
                self.memData['SwapTotal'] << 10)
        except:
            swapTotal = long(0)

        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('system', dict())
            jsonData = SysMgr.jsonData['system']

            jsonData['uptime'] = SysMgr.uptime
            jsonData['interval'] = SysMgr.uptimeDiff
            jsonData['nrCtxt'] = nrCtxt
            jsonData['nrNewThreads'] = nrNewThreads
            jsonData['nrTermThreads'] = nrTermThreads
            jsonData['nrProcess'] = self.nrProcess
            jsonData['nrThreads'] = self.nrThread

            if len(oomstr) > 0:
                jsonData['oomKill'] = oom_kill

        SysMgr.addPrint(\
            ("%s [Time: %7.3f] [Interval: %.1f] [Ctxt: %d] "
            "[Life: +%d/-%d] %s [IRQ: %d] [Core: %d] [Task: %d/%d] "
            "[Load: %s] [RAM: %s] [Swap: %s]\n") % \
            (title, SysMgr.uptime, SysMgr.uptimeDiff, \
            nrCtxt, nrNewThreads, nrTermThreads, oomstr, nrIrq, \
            SysMgr.nrCore, self.nrProcess, self.nrThread, loadavg, \
            memTotal, swapTotal))



    def printZoneUsage(self, nrIndent):
        if len(self.zoneData) == 0:
            return

        nrZone = long(0)
        zoneData = '%s [Node %s > ' % (' ' * nrIndent, 0)
        lenZone = len(zoneData)

        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('zone', dict())

        for node, items in sorted(self.zoneData.items()):
            zoneData = '%s [%-10s > ' % (' ' * nrIndent, 'N%s' % node)
            lenZone = len(zoneData)
            nrZone += 1

            for info, val in sorted(items.items()):
                if SysMgr.jsonOutputEnable:
                    SysMgr.jsonData['zone'].setdefault(node, dict())

                if info == 'free':
                    if not node in self.prevZoneData or \
                        not info in self.prevZoneData[node]:
                        diff = val
                    else:
                        diff = val - self.prevZoneData[node][info]

                    diff = UtilMgr.convSize2Unit(diff << 12)
                    ninfo = 'diff'

                    if SysMgr.jsonOutputEnable:
                        SysMgr.jsonData['zone'][node][ninfo] = diff

                    zoneStat = '%s: %7s / ' % (ninfo, diff)
                    lenZoneStat = len(zoneStat)

                    if lenZone + lenZoneStat >= len(oneLine):
                        zoneData = '%s\n%s %s' % (zoneData, ' ' * 7, ' ' * nrIndent)
                        lenZone = nrIndent

                    zoneData = '%s%s' % (zoneData, zoneStat)
                    lenZone += lenZoneStat

                stat = UtilMgr.convSize2Unit(val << 12)

                if SysMgr.jsonOutputEnable:
                    SysMgr.jsonData['zone'][node][info] = stat
                    continue

                zoneStat = '%s: %6s / ' % (info, stat)
                lenZoneStat = len(zoneStat)

                if lenZone + lenZoneStat >= len(oneLine):
                    zoneData = '%s\n%s %s' % (zoneData, ' ' * 7, ' ' * nrIndent)
                    lenZone = nrIndent

                zoneData = '%s%s' % (zoneData, zoneStat)
                lenZone += lenZoneStat

            SysMgr.addPrint("{0:<1}]\n".format(zoneData[:-2]))



    def printIrqUsage(self, nrIndent):
        if len(self.irqData) == 0:
            return

        nrIrq = long(0)
        irqData = '%s [IRQ > ' % (' ' * nrIndent)
        lenIrq = len(irqData)

        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('irq', dict())

        for irq, cnt in sorted(self.irqData.items(), key=lambda e: \
            self.irqData[e[0]] if not e[0] in self.prevIrqData \
            else e[1] - self.prevIrqData[e[0]], reverse=True):

            if not irq in self.prevIrqData:
                irqDiff = cnt
            else:
                irqDiff = cnt - self.prevIrqData[irq]

            if irqDiff <= 0:
                break
            elif SysMgr.jsonOutputEnable:
                SysMgr.jsonData['irq'][irq] = irqDiff

            nrIrq += 1
            newIrq = '%s: %s / ' % \
                (irq, UtilMgr.convNum(irqDiff))
            lenNewIrq = len(newIrq)

            if lenIrq + lenNewIrq >= len(oneLine):
                irqData = '%s\n%s %s' % (irqData, ' ' * 7, ' ' * nrIndent)
                lenIrq = nrIndent

            irqData = '%s%s' % (irqData, newIrq)
            lenIrq += lenNewIrq

        if nrIrq > 0:
            SysMgr.addPrint("{0:<1}]\n".format(irqData[:-2]))



    def printPerfUsage(self, nrIndent):
        if len(SysMgr.perfEventData) == 0:
            return

        perfString = SysMgr.getPerfString(SysMgr.perfEventData)
        if len(perfString) > 0:
            SysMgr.addPrint("%s %s\n" % (' ' * nrIndent, perfString))

            # add JSON stats #
            if SysMgr.jsonOutputEnable:
                SysMgr.jsonData.setdefault('PMU', dict())
                jsonData = SysMgr.jsonData['PMU']

                plist = perfString[1:-1].split(' / ')
                for stat in plist:
                    metric, value = stat.split(':')
                    jsonData['PMU'][metric] = value.strip()



    def printNetworkUsage(self):
        if not SysMgr.networkEnable:
            return
        elif SysMgr.uptimeDiff == 0:
            return
        elif SysMgr.checkCutCond():
            return

        # update network usage #
        SysMgr.sysInstance.updateNetworkInfo()

        SysMgr.addPrint('%s\n' % twoLine)

        SysMgr.addPrint(\
            "{0:^40} | {1:^53} | {2:^53} |\n{3:1}\n".format(\
            "Network", "Receive", "Transfer", oneLine), newline=2)

        SysMgr.addPrint((\
            "{0:^16} | {1:^21} | "
            "{2:^8} | {3:^8} | {4:^8} | {5:^8} | {6:^9} | "
            "{2:^8} | {3:^8} | {4:^8} | {5:^8} | {6:^9} |\n").format(\
                "Dev", "IP", "Size", "Packet", "Error", "Drop", "Multicast"))

        SysMgr.addPrint('%s\n' % twoLine)

        convertFunc = UtilMgr.convSize2Unit

        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('net', dict())

        cnt = long(0)
        totalStat = {'rdiff': [0] * 5, 'tdiff': [0] * 5}

        for dev, val in sorted(\
            SysMgr.sysInstance.networkInfo.items(), key=lambda e:e[0]):
            '''
            [ network stat sequence ]
            bytes, packets, errs, drop, fifo, \
                frame, compressed, multicast
            '''

            try:
                rdiff = val['rdiff']
                tdiff = val['tdiff']

                # sum total stats #
                totalStat['rdiff'][0] += rdiff[0]
                totalStat['rdiff'][1] += rdiff[1]
                totalStat['rdiff'][2] += rdiff[2]
                totalStat['rdiff'][3] += rdiff[3]
                totalStat['rdiff'][4] += rdiff[-1]
                totalStat['tdiff'][0] += tdiff[0]
                totalStat['tdiff'][1] += tdiff[1]
                totalStat['tdiff'][2] += tdiff[2]
                totalStat['tdiff'][3] += tdiff[3]
                totalStat['tdiff'][4] += tdiff[-1]

                SysMgr.addPrint((\
                    "{0:>16} | {1:>21} | "
                    "{2:>8} | {3:>8} | {4:>8} | {5:>8} | {6:>9} | "
                    "{7:>8} | {8:>8} | {9:>8} | {10:>8} | {11:>9} |\n").format(\
                        dev, val['ipaddr'],\
                        convertFunc(rdiff[0]), convertFunc(rdiff[1]), \
                        convertFunc(rdiff[2]), convertFunc(rdiff[3]), \
                        convertFunc(rdiff[-1]), \
                        convertFunc(tdiff[0]), convertFunc(tdiff[1]), \
                        convertFunc(tdiff[2]), convertFunc(tdiff[3]), \
                        convertFunc(tdiff[-1])))
                cnt += 1
            except:
                pass

        if cnt == 0:
            SysMgr.addPrint('\tNone\n')
        else:
            rdiff = totalStat['rdiff']
            tdiff = totalStat['tdiff']
            SysMgr.addPrint((\
                "{0:>16} | {1:^21} | "
                "{2:>8} | {3:>8} | {4:>8} | {5:>8} | {6:>9} | "
                "{7:>8} | {8:>8} | {9:>8} | {10:>8} | {11:>9} |\n").format(\
                    '[ TOTAL ]', ' ',\
                    convertFunc(rdiff[0]), convertFunc(rdiff[1]), \
                    convertFunc(rdiff[2]), convertFunc(rdiff[3]), \
                    convertFunc(rdiff[-1]), \
                    convertFunc(tdiff[0]), convertFunc(tdiff[1]), \
                    convertFunc(tdiff[2]), convertFunc(tdiff[3]), \
                    convertFunc(tdiff[-1])))



    def printDiskUsage(self):
        if not SysMgr.diskEnable:
            return
        elif SysMgr.uptimeDiff == 0:
            return
        elif SysMgr.checkCutCond():
            return

        # update storage usage #
        SysMgr.sysInstance.updateStorageInfo()

        convSize2Unit = UtilMgr.convSize2Unit

        SysMgr.addPrint('%s\n' % twoLine)
        SysMgr.addPrint((\
            "{0:^24}|{1:4}|{2:^5}|{3:^7}|{4:^7}|{5:>7}({6:>7})|"
            "{7:^5}|{8:^7}|{9:^7}|{10:^8}|{11:^53}|\n").\
            format("DEV", "BUSY", "AVQ", "READ", "WRITE", "FREE", 'DIFF',\
            "USAGE", "TOTAL", "AVF", "FS", "MountPoint <Option>"))
        SysMgr.addPrint('%s\n' % oneLine)

        storageData = SysMgr.sysInstance.storageData
        prevStorageData = SysMgr.sysInstance.prevStorageData

        if SysMgr.jsonOutputEnable:
            SysMgr.jsonData.setdefault('storage', dict())

        printCnt = long(0)
        for dev, value in sorted(storageData.items(),\
            key=lambda e: e[1]['load'] if 'load' in e[1] else 0, reverse=True):

            # skip total usage #
            if dev == 'total':
                continue

            origDev = dev
            if 'mount' in value and \
                value['mount']['fs'] == 'tmpfs':
                dev = value['mount']['path']

            # get readtime #
            try:
                readtime = value['readtime'] - \
                    prevStorageData[origDev]['readtime']
            except:
                readtime = long(0)

            # get writetime #
            try:
                writetime = value['writetime'] - \
                    prevStorageData[origDev]['writetime']
            except:
                writetime = long(0)

            # get busytime #
            try:
                iotime = value['iotime'] - \
                    prevStorageData[origDev]['iotime']

                busytime = '%s%%' % \
                    long(iotime / 10 / SysMgr.uptimeDiff)

                iowtime = value['iowtime'] - \
                    prevStorageData[origDev]['iowtime']
            except:
                busytime = '0%'

            # get avq #
            try:
                iowtime = value['iowtime'] - \
                    prevStorageData[origDev]['iowtime']

                avq = '%.1f' % (iowtime / iotime)
            except:
                avq = '0'

            # get read size on this interval #
            try:
                readSize = value['read'] - \
                    prevStorageData[origDev]['read']

                readSize = convSize2Unit(readSize << 20)
            except:
                readSize = long(0)

            # get write size on this interval #
            try:
                writeSize = value['write'] - \
                    prevStorageData[origDev]['write']

                writeSize = convSize2Unit(writeSize << 20)
            except:
                writeSize = long(0)

            total = convSize2Unit(value['total'] << 20)

            free = convSize2Unit(value['free'] << 20)

            # get free space change on this interval #
            try:
                freeDiff = value['free'] - \
                    prevStorageData[origDev]['free']

                if freeDiff < 0:
                    op = '-'
                elif freeDiff == 0:
                    op = ''
                else:
                    op = '+'

                freeDiff = '%s%s' % \
                    (op, convSize2Unit(long(abs(freeDiff)) << 20))
            except:
                freeDiff = long(0)

            use = convSize2Unit(value['usageper'])
            avail = convSize2Unit(value['favail'])
            fs = value['mount']['fs']
            path = value['mount']['path']
            option = value['mount']['option']

            # make disk stat string #
            if len(option) > 0:
                mountInfo = '%s <%s>' % (path, option)
            else:
                mountInfo = path

            diskInfo = \
                ("{0:<24}|{1:>4}|{2:>5}|{3:>7}|{4:>7}|{5:>7}({6:>7})|"
                "{7:>5}|{8:>7}|{9:>7}|{10:^8}| {11:<52}|\n").\
                format(dev, busytime, avq, readSize, writeSize, free,\
                freeDiff, '%s%%' % use, total, avail, fs, mountInfo[:51])

            if SysMgr.checkCutCond():
                return

            SysMgr.addPrint(diskInfo)

            printCnt += 1

        if printCnt == 0:
            SysMgr.addPrint('\tNone\n')



    def getSortedProcData(self):
        # memory #
        if SysMgr.sort == 'm':
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: long(e[1]['stat'][self.rssIdx]), reverse=True)
        # block #
        elif SysMgr.sort == 'b':
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: e[1]['btime'], reverse=True)
        # WFC #
        elif SysMgr.sort == 'w':
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: e[1]['cttime'], reverse=True)
        # pid #
        elif SysMgr.sort == 'p':
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: long(e[0]))
        # new #
        elif SysMgr.sort == 'n':
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: e[1]['new'], reverse=True)
        # runtime #
        elif SysMgr.sort == 'r':
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: e[1]['runtime'], reverse=True)
        # oomscore #
        elif SysMgr.sort == 'o':
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: e[1]['oomScore'], reverse=True)
        # priority #
        elif SysMgr.sort == 'P':
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: long(e[1]['stat'][self.prioIdx]), reverse=False)
        # exectime #
        elif SysMgr.sort == 'e':
            try:
                for idx, value in self.procData.items():
                    self.saveProcSchedData(value['taskPath'], idx)

                sortedProcData = sorted(self.procData.items(), \
                    key=lambda e: e[1]['execTime'], reverse=True)
            except:
                sortedProcData = self.procData.items()
        # contextswitch #
        elif SysMgr.sort == 'C':
            try:
                for idx, value in self.procData.items():
                    self.saveProcStatusData(value['taskPath'], idx)

                now = self.procData
                prev = self.prevProcData
                yld = 'voluntary_ctxt_switches'
                prmpt = 'nonvoluntary_ctxt_switches'
                sortedProcData = \
                    sorted(now.items(), key=lambda k: \
                        (long(now[k[0]]['status'][yld]) - \
                            long(prev[k[0]]['status'][yld])) + \
                        (long(now[k[0]]['status'][prmpt]) - \
                            long(prev[k[0]]['status'][prmpt])) \
                                if k[0] in prev else 0, \
                        reverse=True)
            except:
                sortedProcData = self.procData.items()
        # dbus #
        elif SysMgr.sort == 'd':
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: \
                    long(e[1]['dbusCnt']) \
                        if 'dbusCnt' in e[1] else 0, reverse=True)
        # comm #
        elif SysMgr.sort == 'c':
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: e[1]['stat'][self.commIdx], reverse=False)
        # CPU #
        else:
            # set CPU usage as default #
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: e[1]['ttime'], reverse=True)

        return sortedProcData



    def printProcUsage(self):
        def isBreakCond(value):
            # get focus value #
            if not SysMgr.sort:
                focusVal = value['ttime']
            elif SysMgr.sort == 'm':
                focusVal = long(stat[self.rssIdx]) >> 8
            elif SysMgr.sort == 'b':
                focusVal = value['btime']
            elif SysMgr.sort == 'w':
                focusVal = value['cttime']
            elif SysMgr.sort == 'n':
                focusVal = value['new']
            elif SysMgr.sort == 'o':
                focusVal = value['oomScore']
            else:
                focusVal = 1

            if not SysMgr.filterGroup and \
                not SysMgr.showAll and \
                not focusVal:
                return True
            else:
                return False

        def isExceptTask(idx):
            exceptFlag = False

            for item in list(SysMgr.filterGroup):
                exceptFlag = False
                # group mode #
                if SysMgr.groupProcEnable:
                    # process mode #
                    if SysMgr.processEnable:
                        ppid = procData[idx]['stat'][self.ppidIdx]

                        # check current pid #
                        if idx == item:
                            break
                        # check current thread comm #
                        elif item in stat[self.commIdx]:
                            break
                        # check current's parent pid by comm #
                        elif ppid in plist:
                            break
                        # check current's parent comm #
                        elif ppid in procData and \
                            item in procData[ppid]['stat'][self.commIdx]:
                            break
                        # check current's parent pid #
                        elif item.isdigit() and \
                            item in procData and \
                            procData[item]['stat'][self.ppidIdx] == \
                            stat[self.ppidIdx]:
                            break
                        else:
                            exceptFlag = True
                    # thread mode #
                    else:
                        pid = procData[idx]['mainID']

                        # check current process comm #
                        if pid in procData and \
                            item in procData[pid]['stat'][self.commIdx]:
                            break
                        # check current pid by comm #
                        elif pid in plist:
                            break
                        # check current's pid #
                        elif item.isdigit() and \
                            item in procData and \
                            procData[item]['mainID'] == value['mainID']:
                            break
                        elif idx == item or \
                            value['mainID'] == item:
                            break
                        else:
                            exceptFlag = True
                # single mode #
                else:
                    if idx == item:
                        break
                    elif item in stat[self.commIdx]:
                        break
                    else:
                        exceptFlag = True

            return exceptFlag

        def getParentList():
            plist = {}
            if not SysMgr.groupProcEnable:
                return plist

            for idx, value in sortedProcData:
                for item in SysMgr.filterGroup:
                    if not item in value['stat'][self.commIdx]:
                        continue

                    if SysMgr.processEnable:
                        plist[self.procData[idx]['stat'][self.ppidIdx]] = long(0)
                    else:
                        plist[self.procData[idx]['mainID']] = long(0)
                    break

            return plist

        def getTypes():
            if SysMgr.processEnable:
                mode = 'Process'
                pidType = 'PID'
                ppidType = 'PPID'
                sidType = 'SID'
                pgrpType = 'USER'
            else:
                mode = 'Thread'
                pidType = 'TID'
                ppidType = 'PID'
                sidType = 'Yld'
                pgrpType = 'Prmt'

            if SysMgr.wfcEnable:
                dprop = 'WFC'
            else:
                dprop = 'Dly'

            # check last field #
            if SysMgr.wchanEnable:
                etc = 'WaitChannel'
            elif SysMgr.affinityEnable:
                etc = 'Affinity'
            elif SysMgr.oomEnable:
                etc = 'OOMScore'
            elif SysMgr.sigHandlerEnable:
                etc = 'SignalHandler'
            elif SysMgr.processEnable:
                etc = 'Parent'
            else:
                etc = 'Process'

            # set memory type #
            if SysMgr.pssEnable:
                mem = 'PSS'
            elif SysMgr.ussEnable:
                mem = 'USS'
            else:
                mem = 'RSS'

            return mode, pidType, ppidType, sidType, \
                pgrpType, dprop, etc, mem

        def printStackSamples(idx):
            # set indent size including arrow #
            initIndent = 42

            for stack, cnt in sorted(\
                self.stackTable[idx]['stack'].items(), \
                key=lambda e: e[1], reverse=True):

                line = ''
                newLine = 1
                fullstack = ''
                per = long((cnt / float(self.stackTable[idx]['total'])) * 100)
                self.stackTable[idx]['stack'][stack] = long(0)

                if per == 0:
                    continue

                indent = initIndent + 3

                for call in stack.split('\n'):
                    try:
                        if not call:
                            fullstack = 'N/A'

                        astack = call.split()[1]

                        if astack.startswith('0xffffffff'):
                            if fullstack == line == '':
                                line = 'N/A'
                            else:
                                line = line[:line.rfind('<-')]
                            break

                        lenLine = indent + len(line) + len(astack)
                        if lenLine >= SysMgr.lineLength:
                            indent = long(0)
                            fullstack = '%s%s\n' % (fullstack, line)
                            newLine += 1
                            line = ' ' * initIndent

                        line = '%s%s <- ' % (line, astack)
                    except:
                        pass

                fullstack = '%s%s' % (fullstack, line)

                if SysMgr.checkCutCond(newLine):
                    return -1

                SysMgr.addPrint(\
                    "{0:>39} | {1:1}\n".format(\
                        'KSTACK(%s%%)' % per, fullstack), newLine)

            return newLine

        # check return condition #
        if SysMgr.uptimeDiff == 0 or \
            SysMgr.checkCutCond():
            return
        elif len(self.procData) == 0:
            SysMgr.addPrint(twoLine)
            return

        # set comm and pid size #
        pd = SysMgr.pidDigit
        cl = 26-(SysMgr.pidDigit*2)

        # calculate resource usage of processes #
        self.setProcUsage()

        # get types #
        mode, pidType, ppidType, sidType, \
            pgrpType, dprop, etc, mem = getTypes()

        # add JSON stats #
        if SysMgr.jsonOutputEnable:
            jtype = mode.lower()
            SysMgr.jsonData.setdefault(jtype, dict())
            jsonData = SysMgr.jsonData[jtype]

        # print menu #
        SysMgr.addPrint((\
            "{24:1}\n{0:>{cl}} ({1:>{pd}}/{2:>{pd}}/{3:>4}/{4:>4})|"
            "{5:>4}({6:^3}/{7:^3}/{8:^3})|"
            "{9:>4}({10:>4}/{11:^3}/{12:^3}/{13:^3})|"
            "{14:>4}({15:>4}/{16:>4}/{17:>5})|"
            "{18:^5}|{19:^6}|{20:^4}|{21:>9}|{22:^21}|\n{23:1}\n").\
                format(mode, pidType, ppidType, "Nr", "Pri", \
                    "CPU", "Usr", "Ker", dprop, \
                    "VSS", mem, "Txt", "Shr", "Swp", \
                    "Blk", "RD", "WR", "NrFlt",\
                    sidType, pgrpType, "FD", "LifeTime", etc, \
                    oneLine, twoLine, cl=cl, pd=pd), newline = 3)

        # set sort value #
        sortedProcData = self.getSortedProcData()

        # make parent list #
        plist = getParentList()

        # define convert function #
        convertNum = UtilMgr.convNum
        convertFunc = UtilMgr.convSize2Unit
        convTime = UtilMgr.convTime

        totalStats = {\
            'read': long(0), 'write': long(0), \
            'yld': long(0), 'prtd': long(0), 'task': long(0)}

        # print resource usage of processes / threads #
        procCnt = long(0)
        procData = self.procData
        for idx, value in sortedProcData:
            stat = value['stat']

            # check exception flag #
            if isExceptTask(idx):
                continue

            # add task into stack trace list #
            if SysMgr.stackEnable:
                self.stackTable.setdefault(idx, dict())

                if not 'fd' in self.stackTable[idx]:
                    spath = '%s/%s/stack' % (SysMgr.procPath, idx)
                    try:
                        self.stackTable[idx]['fd'] = open(spath, 'r')
                        self.stackTable[idx]['stack'] = {}
                        self.stackTable[idx]['total'] = long(0)
                    except:
                        SysMgr.printOpenWarn(spath)

                        self.stackTable.pop(idx, None)

            # check limit #
            if isBreakCond(value):
                break

            if SysMgr.checkCutCond():
                return

            # get comm #
            if value['new']:
                comm = '*' + stat[self.commIdx][1:-1]
            else:
                comm = stat[self.commIdx][1:-1]

            # get parent id #
            if SysMgr.processEnable:
                pid = stat[self.ppidIdx]
            else:
                pid = value['mainID']

            # get task status #
            tstat = stat[self.statIdx]

            # get code size #
            codeSize = (long(stat[self.ecodeIdx]) - \
                long(stat[self.scodeIdx])) >> 20

            # get sched #
            SCHED_POLICY = ConfigMgr.SCHED_POLICY
            if SCHED_POLICY[int(stat[self.policyIdx])] == 'C':
                schedValue = "%3d" % (long(stat[self.prioIdx]) - 20)
            else:
                schedValue = "%3d" % (abs(long(stat[self.prioIdx]) + 1))

            # get lifetime #
            lifeTime = UtilMgr.convTime(value['runtime'])

            # save status info to get memory status #
            self.saveProcStatusData(value['taskPath'], idx)

            # save cmdline info #
            self.saveCmdlineData(value['taskPath'], idx)

            # save cgroup info #
            self.saveCgroupData(value['taskPath'], idx)

            # save sched info to get delayed time  #
            if not SysMgr.wfcEnable:
                self.saveProcSchedData(value['taskPath'], idx)

            # save wait channel info  #
            if SysMgr.isRoot() and SysMgr.wchanEnable:
                self.saveProcWchanData(value['taskPath'], idx)

            # save memory map info to get memory details #
            if SysMgr.memEnable or \
                SysMgr.pssEnable or \
                SysMgr.ussEnable:
                ThreadAnalyzer.saveProcSmapsData(value['taskPath'], idx)

            # swap #
            try:
                swapSize = long(value['status']['VmSwap'].split()[0]) >> 10
            except:
                swapSize = '-'

            # shared #
            try:
                shr = long(value['statm'][self.shrIdx]) >> 8
            except:
                shr = '-'

            if not SysMgr.processEnable:
                # yield #
                try:
                    value['yield'] = \
                        value['status']['voluntary_ctxt_switches']
                except:
                    value['yield'] = '-'

                # preempted #
                try:
                    value['preempted'] = \
                        value['status']['nonvoluntary_ctxt_switches']
                except:
                    value['preempted'] = '-'

            # user #
            try:
                userData = SysMgr.sysInstance.userData
                uid  = value['status']['Uid'].split()[0]
                value['user'] = userData[uid]['name']
            except:
                value['user'] = '-'

            # save size of file descriptor table #
            try:
                value['fdsize'] = value['status']['FDSize']
            except:
                value['fdsize'] = '-'

            # scheduling info #
            if SysMgr.processEnable:
                # sid #
                yld = stat[self.sidIdx]
                if yld == '0':
                    yld = '-'

                # user #
                try:
                    prtd = value['user'][:6]
                except:
                    prtd = '-'
            else:
                try:
                    prevStatus = self.prevProcData[idx]['status']
                    yld = long(value['yield']) - \
                        long(prevStatus['voluntary_ctxt_switches'])
                except:
                    yld = '-'

                try:
                    prevStatus = self.prevProcData[idx]['status']
                    prtd = long(value['preempted']) - \
                        long(prevStatus['nonvoluntary_ctxt_switches'])
                except:
                    prtd = '-'

            # calculate delayed time in runqueue #
            try:
                execTime = \
                    value['execTime'] - self.prevProcData[idx]['execTime']
                waitTime = \
                    value['waitTime'] - self.prevProcData[idx]['waitTime']
                execPer = (execTime / (execTime + waitTime)) * 100
                totalTime = value['ttime'] * (100 / execPer)
                dtime = long(totalTime - value['ttime'])
            except:
                dtime = '-'

            # get io size #
            try:
                readSize = value['read'] >> 20
                writeSize = value['write'] >> 20
            except:
                readSize = '-'
                writeSize = '-'

            # get blocked time of parent process waits for its children #
            if SysMgr.wfcEnable:
                dtime = long(value['cttime'])

            # set last field info #
            if SysMgr.wchanEnable:
                try:
                    etc = value['wchan']
                except:
                    etc = '-'
            elif SysMgr.affinityEnable:
                try:
                    etc = SysMgr.getAffinity(long(idx))
                except:
                    etc = '-'
            elif SysMgr.oomEnable:
                try:
                    etc = str(value['oomScore'])
                except:
                    etc = '-'
            elif SysMgr.sigHandlerEnable:
                try:
                    etc = value['status']['SigCgt'].lstrip('0')
                except:
                    etc = '-'
            elif not SysMgr.processEnable:
                # process name #
                try:
                    pgid = procData[idx]['mainID']
                    etc = '%s(%s)' % \
                        (procData[pgid]['stat'][self.commIdx][1:-1], pgid)
                except:
                    etc = '-'
            else:
                # parent name #
                try:
                    pgid = procData[idx]['stat'][self.ppidIdx]
                    etc = '%s(%s)' % \
                        (procData[pgid]['stat'][self.commIdx][1:-1], pgid)
                except:
                    etc = '-'

            try:
                mems = rss = long(stat[self.rssIdx])
            except:
                mems = rss = long(0)

            try:
                sched = \
                    SCHED_POLICY[int(stat[self.policyIdx])] + str(schedValue)
            except:
                sched = '?'

            try:
                vss = long(stat[self.vssIdx]) >> 20
            except:
                vss = long(0)

            # get memory details #
            memBuf, nrss, pss, uss = self.getMemDetails(idx, value['maps'])

            if SysMgr.pssEnable:
                mems = pss >> 8
            elif SysMgr.ussEnable:
                mems = uss >> 8
            else:
                mems = rss = rss >> 8

            # add JSON stats #
            if SysMgr.jsonOutputEnable:
                jsonData[idx] = {
                    'comm': comm,
                    'stat': tstat,
                    pidType: idx,
                    ppidType: pid,
                    'nrThreads': stat[self.nrthreadIdx],
                    'sched': sched.replace(' ', ''),
                    'ttime': value['ttime'],
                    'utime': value['utime'],
                    'stime': value['stime'],
                    'vss': vss,
                    'rss': rss,
                    'mem': mems,
                    'code': codeSize,
                    'shared': shr,
                    'btime': value['btime'],
                    'nrFlt': value['majflt'],
                    'fd': value['fdsize'],
                    'life': lifeTime.strip(),
                    'dtime': long(0),
                    'swap': long(0),
                    'bread': long(0),
                    'bwrite': long(0),
                }

                try:
                    jsonData[idx]['dtime'] = long(dtime)
                except:
                    pass

                try:
                    jsonData[idx]['swap'] = long(swapSize)
                except:
                    pass

                try:
                    jsonData[idx]['cgroup'] = value['cgroup']
                except:
                    pass

                try:
                    jsonData[idx]['cmdline'] = value['cmdline']
                except:
                    pass

                try:
                    jsonData[idx]['bread'] = long(readSize)
                    jsonData[idx]['bwrite'] = long(writeSize)
                except:
                    pass

                if SysMgr.memEnable:
                    jsonData[idx]['pss'] = pss
                    jsonData[idx]['uss'] = uss

            # remove unshown field in lifetime #
            if len(lifeTime.split(':')) > 3:
                lifeTime = lifeTime[:lifeTime.rfind(':')]

            if SysMgr.floatEnable:
                ttime = '%.1f' % value['ttime']
                btime = '%.1f' % value['btime']
            else:
                ttime = value['ttime']
                btime = value['btime']

            # print stats of a process #
            SysMgr.addPrint(\
                ("{0:>{cl}} ({1:>{pd}}/{2:>{pd}}/{3:>4}/{4:>4})|"
                "{5:>4}({6:>3}/{7:>3}/{8:>3})|"
                "{9:>4}({10:>4}/{11:>3}/{12:>3}/{13:>3})|"
                "{14:>4}({15:>4}/{16:>4}/{17:>5})|"
                "{18:>5}|{19:>6}|{20:>4}|{21:>9}|{22:>21}|\n").\
                format(comm[:cl], idx, pid, stat[self.nrthreadIdx], \
                sched, ttime, value['utime'], value['stime'], \
                dtime, vss, mems, codeSize, shr, swapSize, \
                btime, readSize, writeSize, value['majflt'], \
                yld, prtd, value['fdsize'], lifeTime[:9], etc[:21], \
                cl=cl, pd=pd))

            # sum stats #
            try:
                totalStats['ttime'] += value['ttime']
                totalStats['utime'] += value['utime']
                totalStats['stime'] += value['stime']
                totalStats['mem'] += mems
                if swapSize != '-':
                    totalStats['swap'] += swapSize
                totalStats['btime'] += value['btime']
                totalStats['majflt'] += value['majflt']
                totalStats['task'] += 1
            except:
                totalStats['ttime'] = value['ttime']
                totalStats['utime'] = value['utime']
                totalStats['stime'] = value['stime']
                totalStats['mem'] = mems
                totalStats['swap'] = swapSize
                totalStats['btime'] = value['btime']
                totalStats['majflt'] = value['majflt']
                totalStats['task'] = 1

            if not SysMgr.processEnable:
                try:
                    totalStats['yld'] += yld
                    totalStats['prtd'] += prtd
                except:
                    pass
            else:
                totalStats['yld'] = '-'
                totalStats['prtd'] = '-'

            if SysMgr.blockEnable:
                try:
                    totalStats['read'] += value['read']
                    totalStats['write'] += value['write']
                except:
                    try:
                        totalStats['read'] = value['read']
                        totalStats['write'] = value['write']
                    except:
                        totalStats['read'] = '-'
                        totalStats['write'] = '-'
            else:
                totalStats['read'] = '-'
                totalStats['write'] = '-'

            # print PMU stats #
            if SysMgr.perfGroupEnable:
                try:
                    perfData = \
                        SysMgr.collectProcPerfData(value['perfFds'])
                    perfString = SysMgr.getPerfString(perfData)
                    if len(perfString) > 0:
                        SysMgr.addPrint(\
                            "{0:>40}| {1:1}\n".format('PERF', perfString))
                except SystemExit:
                    sys.exit(0)
                except:
                    self.procData[idx]['perfFds'] = \
                        SysMgr.initProcPerfEvents(long(idx))

            # print memory details #
            for memData in memBuf:
                mprop = memData[0]
                mval = memData[1]

                SysMgr.addPrint(mval)

                if not SysMgr.wssEnable:
                    continue

                # split a long line #
                tstr = ''
                indent = 54
                indenta = 5
                lenItem = 7
                isFirstLined = True
                limit = SysMgr.lineLength - indent
                pstr = procData[idx]['wss'][mprop]

                while len(pstr) > limit:
                    slimit = len(pstr[:limit])
                    des = '%s' % pstr[:slimit]
                    tstr = '%s%s\n%s' % \
                        (tstr, des, ' ' * (indent + indenta))

                    if isFirstLined:
                        limit -= indenta + lenItem
                        isFirstLined = False

                    pstr = '%s' % pstr[slimit:]

                tstr = '%s%s' % (tstr, pstr)

                # count newlines #
                newline = tstr.count('\n')+1

                SysMgr.addPrint(\
                    "{0:>39} | WSS: {1:1}\n".format(' ', tstr), newline)

            # print cmdline #
            if SysMgr.cmdlineEnable and \
                len(value['cmdline']) > 0:
                SysMgr.addPrint(\
                    "{0:>39} | {1:1}\n".format('CMDLINE', value['cmdline']))

            # print cgroup #
            if 'cgroup' in value:
                SysMgr.addPrint(\
                    "{0:>39} | {1:1}\n".format('CGROUP', value['cgroup']))

            # print sched #
            if SysMgr.schedEnable and \
                'execTime' in value:
                execTime = float(long(value['execTime'] / 1000000000))
                if value['runtime'] > 0:
                    execPer = execTime / value['runtime'] * 100
                else:
                    execPer = 0
                waitTime = float(long(value['waitTime'] / 1000000000))
                if value['runtime'] > 0:
                    waitPer = waitTime / value['runtime'] * 100
                else:
                    waitPer = 0

                execStr = 'Exec: %s(%.1f%%)' % (convTime(execTime), execPer)
                waitStr = 'Wait: %s(%.1f%%)' % (convTime(waitTime), waitPer)
                sliceStr = 'NrTimeslice: %s' % convertNum(value['nrSlice'])

                schedStr = '%s / %s / %s' % (execStr, waitStr, sliceStr)

                SysMgr.addPrint(\
                    "{0:>39} | {1:1}\n".format('SCHED', schedStr))

                if SysMgr.jsonOutputEnable:
                    try:
                        jsonData[idx]['execTime'] = execTime
                        jsonData[idx]['waitTime'] = waitTime
                        jsonData[idx]['nrSchedSlice'] = value['nrSlice']
                    except:
                        pass

            if SysMgr.delayEnable:
                try:
                    while 1:
                        val = SysMgr.getTaskstats(idx)
                        if not val or str(val['ac_pid']) == idx:
                            break

                    cpuDelay = val['cpu_delay_total']
                    blkDelay = val['blkio_delay_total']
                    swapDelay = val['swapin_delay_total']
                    rclmDelay = val['freepages_delay_total']

                    value['delay'] = {
                        'CPU': cpuDelay,
                        'BLK': blkDelay,
                        'SWAP': swapDelay,
                        'RCLM': rclmDelay,
                    }

                    prevData = self.prevProcData[idx]

                    if 'delay' in prevData:
                        cpuDelayDiff = cpuDelay - prevData['delay']['CPU']
                        blkDelayDiff = blkDelay - prevData['delay']['BLK']
                        swapDelayDiff = swapDelay - prevData['delay']['SWAP']
                        rclmDelayDiff = rclmDelay - prevData['delay']['RCLM']

                        cpuDelayDiff /= 1000000000.0
                        blkDelayDiff /= 1000000000.0
                        swapDelayDiff /= 1000000000.0
                        rclmDelayDiff /= 1000000000.0

                        delayStr = \
                            'CPU: %.3f / BLK: %.3f / SWAP: %.3f / RCLM: %.3f' % \
                                (cpuDelayDiff, blkDelayDiff, swapDelayDiff, rclmDelayDiff)

                        SysMgr.addPrint(\
                            "{0:>39} | {1:1}\n".format('DELAY', delayStr))


                    cpuDelay /= 1000000000.0
                    blkDelay /= 1000000000.0
                    swapDelay /= 1000000000.0
                    rclmDelay /= 1000000000.0

                    delayTotalStr = \
                        'CPU: %.3f / BLK: %.3f / SWAP: %.3f / RCLM: %.3f' % \
                            (cpuDelay, blkDelay, swapDelay, rclmDelay)

                    SysMgr.addPrint(\
                        "{0:>39} | {1:1}\n".format('TOTAL_DELAY', delayTotalStr))

                    if SysMgr.jsonOutputEnable:
                        try:
                            jsonData[idx]['delayTotal'] = value['delay']
                        except:
                            pass

                        try:
                            jsonData[idx]['delay'] = {
                                'CPU': cpuDelayDiff,
                                'BLK': blkDelayDiff,
                                'SWAP': swapDelayDiff,
                                'RCLM': rclmDelayDiff,
                            }
                        except:
                            pass

                except SystemExit:
                    sys.exit(0)
                except:
                    pass

            # print D-Bus #
            if 'dbusList' in value and \
                len(value['dbusList']) > 0:
                for line in value['dbusList']:
                    SysMgr.addPrint(\
                        "{0:>39} | {1:1}\n".format('D-BUS', line))

            # print stacks of threads sampled #
            if SysMgr.stackEnable:
                try:
                    if printStackSamples(idx) == -1:
                        SysMgr.addPrint('---more---')
                        return
                except SystemExit:
                    sys.exit(0)
                except:
                    pass

                try:
                    self.stackTable[idx]['total'] = long(0)
                except:
                    pass

            procCnt += 1
            if SysMgr.memEnable:
                SysMgr.addPrint("%s\n" % oneLine)

        if procCnt > 0:
            totalTime = '%.1f' % totalStats['ttime']
            totalBtime = '%.1f' % totalStats['btime']

            if totalStats['read'] != '-':
                totalStats['read'] = totalStats['read'] >> 20
            if totalStats['write'] != '-':
                totalStats['write'] = totalStats['write'] >> 20

            # print total stats #
            SysMgr.addPrint(\
                ("{0:>{td}}|"
                "{1:>6}({2:>4}/{3:>4})|"
                "{4:>3}:{5:>5} / {6:>3}:{7:>5})|"
                "{8:>4}({9:>4}/{10:>4}/{11:>5})|"
                "{12:>12}|{13:>14}|{14:>21}|\n").\
                format('[ TOTAL ]', totalTime, \
                totalStats['utime'], totalStats['stime'], mem, \
                convertFunc(totalStats['mem'] << 20, True), \
                'Swp', convertFunc(totalStats['swap'], True), \
                totalBtime, totalStats['read'], \
                totalStats['write'], totalStats['majflt'], \
                'Yld: %s' % convertNum(totalStats['yld']), \
                'Prmt: %s' % convertNum(totalStats['prtd']), \
                'Task: %s' % convertNum(totalStats['task']), \
                td=cl+(pd*2)+14))

            SysMgr.addPrint("%s\n" % oneLine)
        else:
            text = "{0:^16}".format('None')
            frame = '%s%s|' % \
                (text, ' ' * (SysMgr.lineLength - len(text) - 1))
            SysMgr.addPrint("{0:1}\n{1:1}\n".format(frame, oneLine))

        # print special processes #
        if self.printSpecialTask('abnormal') == -1:
            return
        elif self.printSpecialTask('new') == -1:
            return
        elif self.printSpecialTask('die') == -1:
            return



    def printSpecialTask(self, taskType):
        # set comm and pid size #
        pd = SysMgr.pidDigit
        cl = 26-(SysMgr.pidDigit*2)

        # get task list #
        if taskType == 'abnormal':
            taskList = set(self.abnormalTaskList.keys())
        elif taskType == 'new':
            taskList = \
                set(self.procData.keys()) - set(self.prevProcData.keys())
        elif taskType == 'die':
            taskList = \
                set(self.prevProcData.keys()) - set(self.procData.keys())

        procCnt = long(0)
        for tid in sorted(list(map(long, taskList))):
            if SysMgr.checkCutCond():
                return -1

            idx = str(tid)

            # define stat variables #
            if taskType == 'die':
                value = self.prevProcData[idx]
                stat = value['stat']
            else:
                if not idx in self.procData:
                    value = dict(self.init_procData)
                    stat = ['?'] * 52
                else:
                    value = self.procData[idx]
                    stat = value['stat']

            # set comm #
            if taskType == 'new':
                comm = ('[+]%s' % stat[self.commIdx][1:-1])[:16]
            elif taskType == 'die':
                comm = ('[-]%s' % stat[self.commIdx][1:-1])[:16]
            elif taskType == 'abnormal':
                comm = ('[%s]%s' % \
                    (self.abnormalTaskList[idx], \
                        stat[self.commIdx][1:-1]))[:16]

            if SysMgr.processEnable:
                pid = stat[self.ppidIdx]
            else:
                pid = value['mainID']

            try:
                codeSize = (long(stat[self.ecodeIdx]) - \
                    long(stat[self.scodeIdx])) >> 20
            except:
                codeSize = 0

            try:
                if ConfigMgr.SCHED_POLICY[int(stat[self.policyIdx])] == 'C':
                    schedValue = "%3d" % (long(stat[self.prioIdx]) - 20)
                else:
                    schedValue = "%3d" % (abs(long(stat[self.prioIdx]) + 1))
                schedPolicy = \
                    ConfigMgr.SCHED_POLICY[int(stat[self.policyIdx])] + \
                    str(schedValue)
            except:
                schedPolicy = '?'

            try:
                runtime = value['runtime'] + SysMgr.uptimeDiff
                lifeTime = UtilMgr.convTime(runtime)
                if len(lifeTime.split(':')) > 3:
                    lifeTime = lifeTime[:lifeTime.rfind(':')]
            except:
                lifeTime = '?'

            try:
                swapSize = \
                    long(value['status']['VmSwap'].split()[0]) >> 10
            except:
                swapSize = '-'
            try:
                shr = long(value['statm'][self.shrIdx]) >> 8
            except:
                shr = '-'

            if SysMgr.blockEnable:
                try:
                    readSize = value['read'] >> 20
                    writeSize = value['write'] >> 20
                except:
                    readSize = writeSize = long(0)
            else:
                readSize = '-'
                writeSize = '-'

            # get common dataset for tasks #
            if idx in self.prevProcData:
                dataset = self.prevProcData
            elif idx in self.procData:
                dataset = self.procData
            else:
                dataset = None

            if not SysMgr.processEnable:
                # process name #
                try:
                    pgid = dataset[idx]['mainID']
                    etc = '%s(%s)' % \
                        (dataset[pgid]['stat'][self.commIdx][1:-1], pgid)
                except:
                    etc = '-'
            else:
                # parent name #
                try:
                    pgid = dataset[idx]['stat'][self.ppidIdx]
                    etc = '%s(%s)' % \
                        (dataset[pgid]['stat'][self.commIdx][1:-1], pgid)
                except:
                    etc = '-'

            if SysMgr.floatEnable:
                ttime = '%.1f' % value['ttime']
                btime = '%.1f' % value['btime']
            else:
                ttime = value['ttime']
                btime = value['btime']

            try:
                vss = long(stat[self.vssIdx]) >> 20
            except:
                vss = 0

            try:
                rss = long(stat[self.rssIdx]) >> 8
            except:
                rss = 0

            # print thread information #
            SysMgr.addPrint(\
                ("{0:>{cl}} ({1:>{pd}}/{2:>{pd}}/{3:>4}/{4:>4})|"
                "{5:>4}({6:>3}/{7:>3}/{8:>3})|"
                "{9:>4}({10:>4}/{11:>3}/{12:>3}/{13:>3})|"
                "{14:>4}({15:>4}/{16:>4}/{17:>5})|"
                "{18:>5}|{19:>6}|{20:>4}|{21:>9}|{22:>21}|\n").\
                format(comm[:cl], idx, pid, stat[self.nrthreadIdx], \
                schedPolicy, ttime, value['utime'], value['stime'], '-', \
                vss, rss, codeSize, shr, swapSize, \
                btime, readSize, writeSize, value['majflt'],\
                '-', '-', '-', lifeTime[:9], etc[:21], cl=cl, pd=pd))
            procCnt += 1

        if procCnt > 0:
            SysMgr.addPrint("%s\n" % oneLine)



    def printReportStat(self, reportStat):
        if not reportStat:
            return
        elif type(reportStat) is dict:
            reportStat = UtilMgr.convDict2Str(reportStat)

        SysMgr.printPipe(reportStat, newline=False, flush=True)

        return

        printBuf = "%s\n" % twoLine

        if 'event' in reportStat:
            for event, proc in reportStat['event'].items():
                printBuf += '[event] (%s)\n' % (event)

                for rank, stat in sorted(\
                    proc.items(), key=lambda e: long(e[0]), reverse=False):

                    printBuf += '[%s] ' % (rank)

                    for item, val in stat.items():
                        printBuf += '(%s: %s) ' % (item, val)

                    printBuf += '\n'

                printBuf += "%s\n" % oneLine

            del reportStat['event']

        for idx, stat in reportStat.items():
            printBuf += '[%s] ' % idx

            if type(stat) is dict:
                for item, val in sorted(stat.items(), reverse=False):
                    printBuf += '(%s: %s) ' % (item, val)
            else:
                printBuf += '(%s) ' % stat

            printBuf += '\n'

        printBuf += "%s\n" % twoLine

        SysMgr.printPipe(printBuf)



    def replyService(self, ip, port):
        if not SysMgr.remoteServObj:
            SysMgr.printErr(\
                "Fail to use server because it is not initialized")
            return

        # send reply message to server #
        message = 'ACK'
        SysMgr.localServObj.sendto(message, ip, port)



    def handleServerResponse(self, packet):
        # return by interrupt from recv #
        if not packet:
            sys.exit(0)

        if type(packet) is tuple:
            data = packet[0]
            addr = packet[1]
        else:
            return

        if type(data) is bytes:
            try:
                data = data.decode()
            except:
                pass

        if not UtilMgr.isString(data):
            SysMgr.printErr("Fail to recognize data from server")
            return

        # get address info from server #
        try:
            ip = addr[0]
            port = long(addr[1])
        except:
            SysMgr.printErr("Fail to recognize address from server")

        # wrong request from client #
        if SysMgr.remoteServObj == 'NONE' and \
            data in ThreadAnalyzer.requestType:
            SysMgr.printErr(\
                "Fail to handle %s request from client" % data)
            return

        # reply ACK to server #
        try:
            self.replyService(ip, port)
        except:
            SysMgr.printErr("Fail to send ACK to server")

        # REPORT service #
        if data[0] == '{' and \
            data.strip()[-1] == '}':
            # convert report data to dictionary type #
            reportStat = UtilMgr.convStr2Dict(data)

            # check converting result #
            if not reportStat:
                reportStat = data

            # print report data #
            self.printReportStat(reportStat)

        # REFUSE response #
        elif data == 'REFUSE':
            SysMgr.printErr(\
                "Fail to request service because of no support from server")
            sys.exit(0)

        # DUPLICATED response #
        elif data == 'PRINT' or data.startswith('REPORT'):
            SysMgr.printErr(\
                "Fail to request service "
                "because of same port used between client and sever")
            sys.exit(0)

        # PRINT service #
        else:
            # realtime mode #
            if not SysMgr.printFile:
                SysMgr.printPipe(data, newline=False, flush=True)
            # buffered mode #
            else:
                SysMgr.addProcBuffer(data)

                # flush buffer #
                SysMgr.clearPrint()



    def requestService(self):
        if not SysMgr.remoteServObj or \
            not SysMgr.localServObj:

            SysMgr.remoteServObj = None
            return

        try:
            # set block socket #
            SysMgr.localServObj.socket.setblocking(1)

            if SysMgr.remoteServObj != 'NONE':
                # send request to server #
                SysMgr.localServObj.sendto(\
                    SysMgr.remoteServObj.request, \
                    SysMgr.remoteServObj.ip, \
                    SysMgr.remoteServObj.port)

                # check event #
                if SysMgr.remoteServObj.request.startswith('EVENT_'):
                    SysMgr.printStat(\
                        "requested %s to server" % \
                        SysMgr.remoteServObj.request)
                    sys.exit(0)

                SysMgr.printStat(\
                    "wait for response of %s registration from server" % \
                    SysMgr.remoteServObj.request)
            else:
                SysMgr.printStat("wait for input from server")
        except SystemExit:
            sys.exit(0)
        except:
            SysMgr.printErr(\
                "Fail to send request '%s'" % \
                SysMgr.remoteServObj.request)



    def checkServer(self):
        if not SysMgr.localServObj:
            return

        while 1:
            # get message from clients #
            ret = SysMgr.localServObj.recvfrom(verbose=False)

            # verify request type #
            if ret is False:
                SysMgr.localServObj = None
                return
            elif not ret:
                return

            # check type #
            if type(ret) is not tuple:
                continue

            try:
                message = ret[0].decode()
            except:
                message = ret[0]

            # check message type #
            if not UtilMgr.isString(message):
                return

            try:
                ip = ret[1][0]
                port = ret[1][1]
            except:
                SysMgr.printWarn(\
                    "Fail to get address of client from message")
                continue

            networkObject = NetworkMgr('client', ip, port)
            if not networkObject.ip:
                continue

            # save current time in new object #
            networkObject.time = time.time()

            if message.startswith('EVENT_'):
                event = message[message.find('_')+1:]

                pos = event.rfind('@')
                if pos >= 0:
                    rtime = event[pos+1:]
                    event = event[:pos]
                else:
                    rtime = SysMgr.uptime

                # append event to list #
                ThreadAnalyzer.procEventData.append(\
                    [SysMgr.uptime, event, rtime])

                SysMgr.printInfo(\
                    "added event '%s' from %s:%d" % (event, ip, port))

                networkObject.send(message)
                del networkObject
                continue

            elif message == 'LOG':
                pass

            elif message == 'PRINT':
                index = ip + ':' + str(port)
                if not index in SysMgr.addrListForPrint:
                    SysMgr.addrListForPrint[index] = networkObject
                    SysMgr.printInfo(\
                        "registered %s:%d as remote address for PRINT" % \
                        (ip, port))
                else:
                    SysMgr.printWarn(\
                        "Duplicated %s:%d as remote address" % (ip, port))

            elif message == 'REPORT_ALWAYS' or message == 'REPORT_BOUND':
                if not SysMgr.reportEnable:
                    SysMgr.printWarn(\
                        "Ignored %s request from %s:%d because no service" % \
                        (message, ip, port))
                    networkObject.send("REFUSE")
                    del networkObject
                    continue

                networkObject.request = message

                index = ip + ':' + str(port)
                if not index in SysMgr.addrListForReport:
                    SysMgr.addrListForReport[index] = networkObject
                    SysMgr.printInfo(\
                        "registered %s:%d as remote address for REPORT" % \
                        (ip, port))
                else:
                    SysMgr.addrListForReport[index] = networkObject
                    SysMgr.printInfo(\
                        "updated %s:%d as remote address for REPORT" % \
                        (ip, port))

            elif message == 'ACK':
                index = ip + ':' + str(port)
                if index in SysMgr.addrListForPrint:
                    SysMgr.addrListForPrint[index].ignore -= 1
                    SysMgr.addrListForPrint[index].status = 'READY'
                elif index in SysMgr.addrListForReport:
                    SysMgr.addrListForReport[index].ignore -= 1
                    SysMgr.addrListForReport[index].status = 'READY'
                else:
                    SysMgr.printWarn(\
                        "Fail to find %s:%d as remote address" % (ip, port))

            # wrong request or just data from server #
            else:
                SysMgr.printErr(\
                    "Fail to recognize the request from client")



    def reportSystemStat(self):
        if not SysMgr.reportEnable:
            return

        # initialize report event list #
        '''
        CPU_INTENSIVE
        MEM_PRESSURE
        SWAP_PRESSURE
        IO_INTENSIVE
        STORAGE_FULL
        '''

        self.reportData['event'] = {}

        # check image created #
        if SysMgr.imagePath:
            self.reportData['event']['IMAGE_CREATED'] = SysMgr.imagePath
            SysMgr.imagePath = None

        rb = ThreadAnalyzer.reportBoundary

        # add CPU status #
        if 'cpu' in self.reportData:
            rank = 1
            self.reportData['cpu']['procs'] = {}
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: e[1]['ttime'], reverse=True)

            for pid, data in sortedProcData:
                if not (SysMgr.showAll or data['ttime'] > 0):
                    break

                evtdata = self.reportData['cpu']['procs']

                pid = long(pid)
                evtdata[rank] = {}
                evtdata[rank]['pid'] = pid
                evtdata[rank]['rank'] = rank
                evtdata[rank]['comm'] = data['stat'][self.commIdx][1:-1]
                evtdata[rank]['total'] = data['ttime']
                evtdata[rank]['user'] = data['utime']
                evtdata[rank]['kernel'] = data['stime']
                evtdata[rank]['runtime'] = \
                    UtilMgr.convTime(data['runtime'])

                rank += 1

            # check event boundary #
            if rb['cpu']['total'] <= self.reportData['cpu']['total']:
                self.reportData['event']['CPU_INTENSIVE'] = \
                    self.reportData['cpu']['procs']

        # add memory & swap status #
        if 'mem' in self.reportData:
            rank = 1
            self.reportData['mem']['procs'] = {}
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: long(e[1]['stat'][self.rssIdx]), reverse=True)

            for pid, data in sortedProcData:
                rss = long(data['stat'][self.rssIdx]) >> 8

                if not (SysMgr.showAll or rank <= 10):
                    break

                text = (long(data['stat'][self.ecodeIdx]) - \
                    long(data['stat'][self.scodeIdx])) >> 20

                evtdata = self.reportData['mem']['procs']

                pid = long(pid)
                evtdata[rank] = {}
                evtdata[rank]['pid'] = pid
                evtdata[rank]['rank'] = rank
                evtdata[rank]['comm'] = data['stat'][self.commIdx][1:-1]
                evtdata[rank]['rss'] = rss
                evtdata[rank]['text'] = text
                evtdata[rank]['runtime'] = \
                    UtilMgr.convTime(data['runtime'])

                # swap #
                try:
                    self.reportData['mem']['procs'][pid]['swap'] = \
                        long(data['status']['VmSwap'].split()[0]) >> 10
                except:
                    pass

                # shared #
                try:
                    self.reportData['mem']['procs'][pid]['shared'] = \
                        long(data['statm'][self.shrIdx]) >> 8
                except:
                    pass

                rank += 1

            # check event boundary #
            if rb['mem']['free'] >= self.reportData['mem']['free']:
                self.reportData['event']['MEM_PRESSURE'] = \
                    self.reportData['mem']['procs']

            # check event boundary #
            if 'swap' in self.reportData and \
                self.reportData['swap']['total'] > 0:

                # get swap usage #
                swapUsagePer = \
                    long(self.reportData['swap']['usage'] / \
                    float(self.reportData['swap']['total']) * 100)

                if rb['swap']['usage'] <= swapUsagePer:
                    self.reportData['event']['SWAP_PRESSURE'] = \
                        self.reportData['mem']['procs']

        # add block status #
        if 'block' in self.reportData:
            rank = 1
            self.reportData['block']['procs'] = {}
            sortedProcData = sorted(self.procData.items(), \
                key=lambda e: e[1]['btime'], reverse=True)

            for pid, data in sortedProcData:
                if data['btime'] == 0:
                    break

                evtdata = self.reportData['block']['procs']

                pid = long(pid)
                evtdata[rank] = {}
                evtdata[rank]['pid'] = long(pid)
                evtdata[rank]['rank'] = rank
                evtdata[rank]['comm'] = data['stat'][self.commIdx][1:-1]
                evtdata[rank]['iowait'] = data['btime']
                evtdata[rank]['runtime'] = \
                    UtilMgr.convTime(data['runtime'])

                rank += 1

            if rb['block']['ioWait'] <= self.reportData['block']['ioWait']:
                self.reportData['event']['IO_INTENSIVE'] = \
                    self.reportData['block']['procs']

        # add storage status #
        if 'storage' in self.reportData:
            try:
                if rb['storage']['total'] <= \
                    self.reportData['storage']['total']['usageper']:
                    self.reportData['event']['STORAGE_FULL'] = \
                        self.reportData['storage']
            except:
                pass

        # add system status #
        if 'system' in self.reportData:
            pass

        # add task status #
        if 'task' in self.reportData:
            pass

        # get event number #
        nrReason = len(self.reportData['event'])

        # print system status to file if condition is met #
        if nrReason > 0 and \
            SysMgr.reportFileEnable and \
            SysMgr.printFile:

            # submit summarized report and details #
            ThreadAnalyzer.printIntervalUsage()

            # sync and close output file #
            if SysMgr.fileForPrint:
                try:
                    SysMgr.fileForPrint.close()
                except:
                    pass
                finally:
                    SysMgr.fileForPrint = None

            # make output path #
            filePath = os.path.dirname(SysMgr.inputFile) + '/guider'
            for event in list(self.reportData['event'].keys()):
                filePath = '%s_%s' % (filePath, event)
            filePath = '%s_%s.out' % \
                (filePath, str(long(SysMgr.uptime)))

            try:
                # rename output file #
                os.rename(SysMgr.inputFile, filePath)

                try:
                    fsize = UtilMgr.convSize2Unit(\
                        long(os.path.getsize(filePath)))
                except:
                    fsize = '?'

                SysMgr.printStat((\
                    "save results based monitoring into "
                    "%s [%s] successfully") % \
                    (filePath, fsize))
            except SystemExit:
                sys.exit(0)
            except:
                SysMgr.printWarn(\
                    "Fail to rename %s to %s" % \
                    SysMgr.inputFile, filePath)

        # convert dict data to JSON-type string #
        jsonObj = UtilMgr.convDict2Str(self.reportData)
        if not jsonObj:
            SysMgr.printWarn(\
                "Fail to convert report data to JSON type")
            return

        # transfer data to file or socket #
        self.tranData(jsonObj)



    def reportSystemStatElastic(self):
        '''
        make data fields as the below list
        - metricset fields
        - beat fields (metricbeat, filebeat, guider, etc...)
        - system fields (cpu, process, memory, diskio, etc...)
        '''

        reportElasticData = ""

        metricsetFields = {
            'metricset':
                {
                    'module': 'system',
                    'name'  : ''
                }
        }

        # set beatstart flag for syncing timestamp
        if hasattr(self, 'beatStart'):
            self.beatStart = False
        else:
            self.beatStart = True

        beatFields = {
            'beat':
                {
                    'name'      : 'guider',
                    'hostname'  : SysMgr.localServObj.ip,
                    'version'   : __version__,
                    'beatstart' : self.beatStart
                }
        }


        # generate CPU status data #
        metricsetFields['metricset']['name'] = 'cpu'

        cpuData = self.reportData['cpu']

        systemCpuFields = {
            'system': {
                'cpu':
                    {
                        'total' : { 'pct': cpuData['total'] },
                        'idle'  : { 'pct': cpuData['idle'] },
                        'user'  : { 'pct': cpuData['user'] },
                        'kernel': { 'pct': cpuData['kernel'] },
                        'irq'   : { 'pct': cpuData['irq'] },
                        'iowait': { 'pct': cpuData['iowait'] },
                        'cores' : cpuData['nrCore']
                    }
                }
        }

        # merge CPU data dictionary #
        reportCpuData = metricsetFields.copy()
        reportCpuData.update(beatFields)
        reportCpuData.update(systemCpuFields)

        jstr = UtilMgr.convDict2Str(reportCpuData)
        if jstr:
            reportElasticData += jstr

        # generate memory status data #
        metricsetFields['metricset']['name'] = 'memory'

        memData = self.reportData['mem']
        swapData = self.reportData['swap']

        systemMemoryFields = {
            'system':
                {
                    'memory':{
                        'total'     : memData['total'],
                        'free'      : memData['free'],
                        'available' : memData['available'],
                        'anon'      : memData['anon'],
                        'file'      : memData['file'],
                        'slab'      : memData['slab'],
                        'swap': {
                            'total' : swapData['total'],
                            'used'  : swapData['usage']
                        }
                    }
                }
        }

        # merge momory data dictionary #
        reportMemoryData = metricsetFields.copy()
        reportMemoryData.update(beatFields)
        reportMemoryData.update(systemMemoryFields)

        jstr = UtilMgr.convDict2Str(reportMemoryData)
        if jstr:
            reportElasticData += jstr

        # generate network status data #
        metricsetFields['metricset']['name'] = 'network'

        networkData = self.reportData['net']

        systemNetworkFields = {
            'system':
                {
                    'network': {
                        'in' : { 'byte': networkData['inbound'] },
                        'out': { 'byte': networkData['outbound'] }
                    }
                }
        }

        # merge network data dictionary #
        reportNetworkData = metricsetFields.copy()
        reportNetworkData.update(beatFields)
        reportNetworkData.update(systemNetworkFields)

        jstr = UtilMgr.convDict2Str(reportNetworkData)
        if jstr:
            reportElasticData += jstr

        # generate network status data #
        metricsetFields['metricset']['name'] = 'diskio'

        systemDiskioFields = {
            'system':
                {
                    'diskio': {
                        'name'  : '',
                        'read'  : { 'bytes': long(0) },
                        'write' : { 'bytes': long(0) },
                        'used'  : { 'pct': long(0) },
                    }
                }
        }

        diskioData = systemDiskioFields['system']['diskio']

        # get read/write bytes on each devices #
        for dev, value in sorted(self.reportData['storage'].items()):
            diskioData['name'] = dev
            diskioData['read']['bytes'] = value['read']
            diskioData['write']['bytes'] = value['read']
            diskioData['used']['pct'] = value['usageper']

            # merge diskio data dictionary #
            reportDiskioData = metricsetFields.copy()
            reportDiskioData.update(beatFields)
            reportDiskioData.update(systemDiskioFields)

            jstr = UtilMgr.convDict2Str(reportDiskioData)
            if jstr:
                reportElasticData += jstr

        # generate process status data #
        metricsetFields['metricset']['name'] = 'process'

        strProcessData = ""
        systemProcessFields = {
            'system':
                {
                    'process':{
                        'name'  : '',
                        'state' : '',
                        'pid'   : 0,
                        'cpu'   : {
                            'user'      : { 'pct': long(0) },
                            'kernel'    : { 'pct': long(0) },
                            'total'     : { 'pct': long(0) },
                            'runtime'   : ''
                        },
                        'memory': {
                            'rss'   : { 'bytes': long(0) },
                            'text'  : long(0)
                        }
                    },

                }
            }

        sortedProcData = sorted(self.procData.items(), \
            key=lambda e: e[1]['ttime'], reverse=True)

        processData = systemProcessFields['system']['process']

        for pid, data in sortedProcData:
            if not (SysMgr.showAll or data['ttime'] > 0):
                break

            processData['pid'] = long(pid)
            processData['name'] = data['stat'][self.commIdx][1:-1]
            processData['cpu']['user']['pct'] = data['utime']
            processData['cpu']['kernel']['pct'] = data['stime']
            processData['cpu']['total']['pct'] = data['ttime']
            processData['cpu']['runtime'] = \
                UtilMgr.convTime(data['runtime'])

            rss = long(data['stat'][self.rssIdx]) >> 8

            text = (long(data['stat'][self.ecodeIdx]) - \
                    long(data['stat'][self.scodeIdx])) >> 20

            processData['memory']['rss']['bytes'] = rss
            processData['memory']['text'] = text

            # merge process data dictionary #
            reportProcessData = metricsetFields.copy()
            reportProcessData.update(beatFields)
            reportProcessData.update(systemProcessFields)

            jstr = UtilMgr.convDict2Str(reportProcessData)
            if jstr:
                reportElasticData += jstr

        # transfer data to file or socket #
        self.tranData(reportElasticData)



    def tranData(self, data):
        # report system status to file #
        if SysMgr.reportObject:
            UtilMgr.writeJsonObject(\
                data, fd=SysMgr.reportObject, \
                trunc=SysMgr.truncEnable)

        # report system status to socket #
        addrlist = dict(SysMgr.addrListForReport)
        for addr, cli in addrlist.items():
            if cli.request != 'REPORT_ALWAYS':
                continue

            if cli.status == 'SENT' and cli.ignore > 1:
                SysMgr.printInfo(\
                    "unregistered %s:%d for REPORT" % (cli.ip, cli.port))
                del SysMgr.addrListForReport[addr]
            else:
                ret = cli.send(data)
                if not ret:
                    del SysMgr.addrListForReport[addr]
                else:
                    cli.ignore += 1



    def printSimpleStat(self):
        pass



    def printSystemStat(self):
        title = '[Top Info]'
        nrIndent = len(title)

        # print default stats #
        self.printDefaultUsage(title)

        # print zone stats #
        self.printZoneUsage(nrIndent)

        # print irq stats #
        self.printIrqUsage(nrIndent)

        # print PMU stat #
        self.printPerfUsage(nrIndent)

        # print system stat #
        self.printSystemUsage()

        # print disk stat #
        self.printDiskUsage()

        # print network stat #
        self.printNetworkUsage()

        # print process stat #
        self.printProcUsage()

        # update session #
        SysMgr.updateSession()

        # flush stats #
        SysMgr.printTopStats()





def main(args=None):
    # update arguments #
    if UtilMgr.isString(args):
        sys.argv = ['guider'] + args.split()

    # initialize envirnoment #
    SysMgr.initEnvironment()

    # check commands #
    if not SysMgr.isRecordMode():
        SysMgr.checkCmdMode()

    # save system info first #
    SysMgr()

    #==================== RECORD PART ====================#

    if SysMgr.isRecordMode():
        SysMgr.setRecordAttr()

        # wait for signal #
        if SysMgr.waitEnable:
            SysMgr.printStat(\
                "wait for user input... [ START(Ctrl+c) ]")

            SysMgr.waitEvent()

        # set normal signal #
        SysMgr.setNormalSignal()

        # SYSTEM MODE #
        if SysMgr.isSystemMode():
            SysMgr.execSystemView()
            sys.exit(0)
        # FILE MODE #
        elif SysMgr.isFileMode():
            SysMgr.execFileAnalysis()
            sys.exit(0)

        # register exit handler #
        atexit.register(SysMgr.stopRecording)

        # start recording #
        SysMgr.sysInstance.startRecording()

        # THREAD & FUNCTION MODE #
        SysMgr.execRecordLoop()

    #==================== ANALYSIS PART ====================#

    # register exit handler #
    atexit.register(SysMgr.doExit)

    # REPORT MODE #
    if SysMgr.isReportMode():
        SysMgr.setReportAttr()
    # VISUAL MODE #
    elif SysMgr.isDrawMode():
        SysMgr.setVisualAttr()

    # parse analysis option #
    SysMgr.parseAnalOption()

    # REALTIME MODE #
    if SysMgr.isTopMode():
        SysMgr.execTopCmd()
        sys.exit(0)
    # THREAD & FUNCTION MODE #
    elif SysMgr.isRecordMode() and \
        SysMgr.isFunctionMode() and \
        SysMgr.graphEnable:
        ThreadAnalyzer(SysMgr.inputFile)

    # set handler for exit #
    signal.signal(signal.SIGINT, SysMgr.exitHandler)

    # check log file is recoginizable #
    ThreadAnalyzer.getInitTime(SysMgr.inputFile)

    # apply launch option from data file #
    if not SysMgr.isRecordMode():
        SysMgr.applyLaunchOption()

    # get mount info from file #
    SysMgr.getMountInfo()

    # print analysis option #
    SysMgr.printAnalOption()

    # FUNCTION MODE #
    if SysMgr.isFunctionMode():
        FunctionAnalyzer(SysMgr.inputFile).printUsage()
    # THREAD MODE #
    else:
        ThreadAnalyzer(SysMgr.inputFile).printUsage()

    # print event info #
    EventAnalyzer.printEventInfo()



# define line variables #
oneLine = "-" * SysMgr.lineLength
twoLine = "=" * SysMgr.lineLength

# define print method for debugging #
def dbgp(msg):
    SysMgr.printWarn(msg, True)

# main #
if __name__ == '__main__':
    # set main environment #
    os.environ["ISMAIN"] = "True"

    main(args=None)
