#!/usr/bin/env python

#-----------------------------------------------------------------------------
#                 Copyright(c) 2016-2019 Innogrit Corporation
#                             All Rights reserved.
#
# The confidential and proprietary information contained in this file may
# only be used by a person authorized under and to the extent permitted
# by a subsisting licensing agreement from Innogrit Corporation.
#
#-----------------------------------------------------------------------------

import os
import re
import sys
import time
import struct
import serial
import string
import telnetlib
import threading
from datetime import datetime
import unicodedata
import binascii
import platform

global fw_fmts
global ftl_fmts
global rtos_fmts
global print_fmts
global sec_addr
global rodata

rodata = []
fw_fmts = []
ftl_fmts = []
rtos_fmts = []
print_fmts = [rtos_fmts, ftl_fmts, fw_fmts] #the index of the three

def get_fmts_ptr(modname):
    if 'RTOS' in modname:
        return rtos_fmts
    elif 'FTL' in modname:
        return ftl_fmts
    elif 'FW' in modname:
        return fw_fmts
    else:
        print('[Error][get_fmts_ptr()] modname error')
        sys.exit(0)

def get_trace_fmts(elf_fmt_path):
    module_name = ""
    fmt_found = False
    try:
        fp = open(elf_fmt_path + 'trace-fmtstr.h')
    except Exception as ex:
        print('[Error][get_trace_fmts]',ex)
        sys.exit(0)
    for line in fp.readlines():
        res = re.search('[A-Z_]+_EVID_STR_FMT', line)
        if None != res:
           module_name = res.group()
           fmt_found = True
           fmts_ptr = get_fmts_ptr(module_name)
           continue
        if '};' in line:
            fmt_found = False
            continue
        if True == fmt_found:
            line = line[line.index('{') + 1 : line.index('}') - 1]
            fmts_ptr.append(line)
    fp.close()

def get_section_addr(elf_fmt_path, elf_name, core_num):
    platform = sys.platform.lower()
    win_gcc_cmd_path = r'C:\Program Files (x86)\GNU Tools ARM Embedded\5.4 2016q3\bin'
    rosec = 'rostrsec'

    extname = ''
    try :
        fp = open(elf_fmt_path + '%s%d'%(elf_name, 1) + extname, 'r')
        fp.close()
    except :
        extname = '.elf'

    for inx in range(core_num):
        if ('win' in platform) and (elf_fmt_path == '.\\') :
            elf_fmt_path = os.getcwd() + '\\'
        elf = elf_fmt_path + '%s%d'%(elf_name, inx + 1) + extname
        rosecfp = elf_fmt_path + '%s%d'%(rosec, inx + 1)
        elfinfo = elf_fmt_path + 'elfinfo'

        if 'win' in platform:
            exit_status = os.system('cd %s & arm-none-eabi-objdump.exe -h %s > %s' %(win_gcc_cmd_path, elf, elfinfo))
            exit_status += os.system('cd %s & arm-none-eabi-objcopy.exe -O binary -j .rostr_data %s %s' %(win_gcc_cmd_path, elf, rosecfp))
        elif 'linux' in platform:
            exit_status = os.system( 'objdump -h %s > %s' %(elf, elfinfo))
            exit_status += os.system( 'arm-none-eabi-objcopy -O binary -j .rostr_data %s %s' %(elf, rosecfp))
        if exit_status != 0:
            print('[Error][get_section_addr()] Parse ELF file error.')
            print('[Tip] Try changing the optional directory to an absolute path.\n\n')
            return False

        rodata.append(rosecfp)
        fp = open(elfinfo, 'r')
        for line in fp.readlines():
            if '.rostr_data' in line:
                line = line.split(' ')
                #remove all null member
                for i in range(line.count('')):
                    line.remove('')
                #sec_addr.append(int(line[3], 16))
                sec_addr[inx] = int(line[3], 16) # avoid some ELF files without '.rostr_data' section
        fp.close()
    return True

def fmt_str_to_list(fmt_str):
    fmt_list = []
    for i in range(3):
        space_index = fmt_str.index(" ")
        sub_str = fmt_str[0 : space_index - 1]
        fmt_str = fmt_str[space_index + 1 : len(fmt_str)]
        fmt_list.append(sub_str)
    fmt_list.append(fmt_str)
    for i in range(len(fmt_list)):
        fmt_list[i] = fmt_list[i].replace('\"', '')
    return fmt_list

def fmt_get_char(char_addr, trace_cpuid):
    fp = open(rodata[trace_cpuid - 1], 'rb')
    fsize = os.path.getsize(rodata[trace_cpuid - 1])
    #check if str addr valid
    if (char_addr >= sec_addr[trace_cpuid - 1]) and (char_addr < (sec_addr[trace_cpuid - 1] + fsize)):
        off = char_addr - sec_addr[trace_cpuid - 1]
    else:
        print('[Error][fmt_get_char()] invalid char addr:0x%x' %(char_addr))
        fp.close()
        return 'E'

    fp.seek(off, 0)
    data = struct.unpack('B', fp.read(1))
    char = chr(data[0])
    fp.close()
    return char

def fmt_get_str(str_addr, trace_cpuid):
    fp = open(rodata[trace_cpuid - 1], 'rb')
    fsize = os.path.getsize(rodata[trace_cpuid - 1])
    #check if str addr valid
    if (str_addr >= sec_addr[trace_cpuid - 1]) and (str_addr < (sec_addr[trace_cpuid - 1] + fsize)):
        off = str_addr - sec_addr[trace_cpuid - 1]
    else:
        print('[Error][fmt_get_str()] invalid str addr:0x%x' %(str_addr))
        line = 'error str_addr: 0x%x' %(str_addr)
        fp.close()
        return line

    fp.seek(off, 0)
    line = ''
    while True:
        data = struct.unpack('B', fp.read(1))
        char = chr(data[0])
        if '\0' != char:
           line += char
        else:
            break
    fp.close()
    return line

def fmt_print_arg(fmt, argv, trace_cpuid):
    #as %p and %x is the same, so replace %p to %x
    fmt = fmt.replace('%p', '%x')
    line = ''
    arg_idx = 0
    fmt_idx = 0
    #go over each char and translate
    while fmt_idx < len(fmt):
        c = fmt[fmt_idx]
        fmt_idx += 1
        if '%' != c:
            line += c
            continue
        else:
            c = fmt[fmt_idx]
            fmt_idx += 1
            if 'x' == c:
                line += '%x' %((int(argv[arg_idx]) & 0xFFFFFFFF))
                arg_idx += 1
            elif 'd' == c:
                line += '%d' %(int(argv[arg_idx]))
                arg_idx += 1
            elif 'u' == c:
                line += '%u' %(int(argv[arg_idx]))
                arg_idx += 1
            elif 'c' == c:
                line += fmt_get_char(int(argv[arg_idx]), trace_cpuid)
                arg_idx += 1
            elif 's' == c:
                line += fmt_get_str(int(argv[arg_idx]), trace_cpuid)
                arg_idx += 1
            else:
                line += c
    return line

def translate_trace_data(trace_line, trace_cpuid):
    trace_log = ''
    str_level = 'DIWEA'
    trace_data = trace_line.split(' ')
    timestamp  = trace_data[0]
    try:
        if '0x' in trace_data[1]:
            eventid = int(trace_data[1], 16)
        else:
            eventid = int(trace_data[1], 10)
    except Exception as ex:
        print('[Error][translate_trace_data()] ',ex)
        return "error trace## " + trace_line
    trace_level = (eventid >> 16)# & 0xff
    trace_modul = (eventid >> 12) & 0xF
    trace_evtid = eventid & 0xFFF
    #check if module id is valid
    if trace_modul > 2:
        trace_log += 'cpuid(%d) modid(%d) exceeds, error eventid(%d)' %(trace_cpuid,trace_modul, eventid)
        return trace_log
    #check if eventid is valid
    max_evtid = len(print_fmts[trace_modul]) - 1
    if trace_evtid > max_evtid:
        trace_log += 'cpuid(%d) evtid(%d) out of %d in module %d, error eventid(%d)' %(trace_cpuid,trace_evtid, max_evtid, trace_modul, eventid)
        return trace_log
    #split fmt string into list for translate
    fmt_list  = fmt_str_to_list(print_fmts[trace_modul][trace_evtid])
    file_name = fmt_list[0]
    func_name = fmt_list[1]
    file_line = fmt_list[2]
    fmt_str   = fmt_list[3]
    """
    if 0 == trace_level:#debug
	trace_log += '\033[0m'
    elif 1 == trace_level:#info
	trace_log += '\033[1;37;40m'
    elif 2 == trace_level:#warning
	trace_log += '\033[1;33;40m'
    elif 3 == trace_level:#error
	trace_log += '\033[1;35;40m'
    elif 4 == trace_level:#panic
	trace_log += '\033[1;31;40m'
    """
    trace_log += '%s %s %s +%s %s() - ' %(timestamp, str_level[trace_level], file_name, file_line, func_name)
    trace_log += fmt_print_arg(fmt_str, trace_data[2: ], trace_cpuid)
    return trace_log

def is_legal_trace(line):
    if '0x' not in line:
        return False
    if 1 != line.count('0x'):
        return False
    if 8 != len(line.split(' ')):
        return False
    sub_line = line[line.index(' ') : ].lower()
    res = re.search('[a-z_]', sub_line)
    if None != res:
        return False
    return True

def err_trace_handle(line, logfile, rawfile):
    line = line.strip()
    if 'Signature' in line and 'FW' in line:
        sig_line = line[0 : line.index('to')]
        sig_line = sig_line + 'to execute'
        sig_line = datetime.now().strftime('[%Y%m%d_%H:%M:%S.%f] ') + sig_line
        print(sig_line)
        logfile.write(sig_line + '\n')
        rawfile.write(sig_line + '\n')
        fw_line  = line[line.index('FW') : ]
        fw_line  = '\033[1;31;40mShastaPlus(InnoGrit) ' + fw_line
        fw_line  = datetime.now().strftime('[%Y%m%d_%H:%M:%S.%f] ') + fw_line
        print(fw_line)
        logfile.write(fw_line + '\n')
        rawfile.write(fw_line + '\n')
    else:
        line = datetime.now().strftime('[%Y%m%d_%H:%M:%S.%f] ') + repr(line)
        print(line)
        logfile.write(line + '\n')
        rawfile.write(line + '\n')

class ItermThread:
    def __init__(self, port_type, port, log_path):
        #init serial para
        if '-p' == port_type:
            self.type = 'serial'
            self.term = serial.Serial()
            self.term.port = port
            self.term.baudrate = 115200
            self.term.bytesize = 8
            self.term.parity = 'N'
            self.term.stopbits = 1
            self.term.timeout = None
            self.term.xonxoff = 0
            self.term.rtscts = 0
        elif '-t' == port_type:
            self.type = 'telnet'
            self.term = telnetlib.Telnet()
            self.term.host = port.split(":")[0]
            self.term.port = port.split(":")[1]
        #init dev status
        self.alive = False
        self.waitEnd = None
        #save org port
        self.raw_port = port
        fname = time.strftime('%Y%m%d__%H_%M_%S')#file name base on current time
        port = port.replace('/', '_')
        port = port.replace(':', '_')
        # isExists = os.path.exists(log_path)
        # if not isExists:
            # os.makedirs(log_path)
        self.log_path = log_path
        self.logfname = self.log_path + 'log__' + port + '__' + fname + '.txt'
        self.rawfname = self.log_path + 'raw__' + port + '__' + fname + '.txt'
        self.thread_read = None
        self.thread_send = None

    def waiting(self):
        # wait for event stop flag
        if not self.waitEnd is None:
            self.waitEnd.wait()

    def start(self):
        #open port and log file
        self.logfile = open(self.logfname,'w')
        self.rawfile = open(self.rawfname,'w')
        try:
            if 'serial' == self.type:
                self.term.open()
            else:
                self.term.open(self.term.host, self.term.port)
        except Exception as ex:
            print ('[Error][ItermThread.start()] ',ex)
            return False
        #query fw_version and save to log file
        self.term.write('fw_version\r'.encode('utf-8'))
        self.waitEnd = threading.Event()
        self.alive = True

        if sys.version_info.major == 3:
            self.thread_read = threading.Thread(target=self.Reader_3x)#for python 3.x version
        else:
            self.thread_read = threading.Thread(target=self.Reader_2x)#for python 2.x version

        self.mutex = threading.Lock()
        self.thread_read.setDaemon(True)
        self.thread_send=threading.Thread(target=self.Sender)
        self.thread_send.setDaemon(True)
        self.thread_read.start()
        self.thread_send.start()
        return True

    def chk_log_size(self):
        #limit log file max size to 100MB
        if os.path.getsize(self.logfname) >= 0x6400000:
            #close current file first
            self.logfile.close()
            self.rawfile.close()
            #gen new log file name
            fname = time.strftime('%Y%m%d__%H_%M_%S')
            port = self.raw_port
            port = port.replace('/', '_').replace(':', '_')
            self.logfname = self.log_path + 'log__' + port + '__' + fname + '.txt'
            self.rawfname = self.log_path + 'raw__' + port + '__' + fname + '.txt'
            #open new log file
            self.logfile = open(self.logfname, 'w')
            self.rawfile = open(self.rawfname, 'w')
        return True

    def Reader_3x(self):
        line = ['' for x in range(10)]
        line_raw = ''
        last_id = 0
        while self.alive:
            try:
                if 'serial' == self.type:
                    new_line = new_line_raw = self.term.readline()
                else:
                    new_line = new_line_raw = self.term.read_until(b'\r')
                line_raw = new_line
                new_line_lst = [b'' for x in range(10)]

                if b'\xf9' in new_line:
                    frame_lst = new_line.split(b'\xf9')   # strip off Start/End flags: 0xf9
                    #print frame_lst
                    if frame_lst[0] is not b'':
                        new_line_lst[last_id] += frame_lst[0]
                    if frame_lst[-1] is not b'':
                        last_id = int(str(frame_lst[-1])[4 : 6])
                    else:
                        last_id = 0
                    for frame in frame_lst[1:] :
                        if frame is not b'':
                            #length check
                            if frame != frame_lst[-1] and int(str(frame)[8 : 10]) != len(frame[2 : ]):
                                print("\033[91mError: length not match (%d, %d)\033[0m" % (int(binascii.hexlify(frame[1])), len(frame[2:])))
                            new_line_lst[int(str(frame)[4 : 6])] += frame[2 : ]
                else:
                    #id = 0
                    new_line_lst[last_id] += new_line

                for id in range(10):
                    line[id] += str(new_line_lst[id])[2 : ]
                    if r'\n' not in line[id]:
                        continue
                    line[id] = line[id][2 : -3]
                    line[id] = line[id].strip()
                    if '' == line[id]:
                        continue
                    line[id] = line[id].replace('\'','')
                    if 'win' in sys.platform.lower():
                        line[id] = line[id].replace(r'\x1b[91m','\x1b[91m').replace(r'\x1b[0m','\x1b[0m').replace(r'\r','')

                    log_line = line[id]
                    if is_legal_trace(log_line) and (print_fmts != [[], [], []]):
                        log_line = translate_trace_data(log_line, id)

                    if id is 0:
                        prt_fmt = ''
                    else:
                        prt_fmt = '[cpu '+ str(id)+'] '

                    if r'serial@ShastaPlus:#' in line[id]:
                        line[id] = 'serial@ShastaPlus:# '
                        sys.stdout.write(prt_fmt + line[id])
                        self.logfile.write(prt_fmt + datetime.now().strftime('[%Y%m%d_%H:%M:%S.%f] ') + line[id] + '\n')
                    else:
                        sys.stdout.write(prt_fmt + datetime.now().strftime('[%Y%m%d_%H:%M:%S.%f] ') + log_line + '\n')
                        self.logfile.write(prt_fmt + datetime.now().strftime('[%Y%m%d_%H:%M:%S.%f] ') + log_line + '\n')

                    sys.stdout.flush()
                    self.logfile.flush()
                    line[id] = ''
                    self.mutex.acquire()
                    ItermThread.chk_log_size(self)
                    self.mutex.release()

                self.rawfile.write(datetime.now().strftime('[%Y%m%d_%H:%M:%S.%f] ') + repr(line_raw) + '\n')
                self.rawfile.flush()
            except IOError as ex:
                self.alive = False
            except Exception as ex:
                print('[Error][ItermThread.Reader_3x()] ',ex)
                try:
                    self.mutex.release()
                except Exception as ex:
                    print('[Normal Tip] No need to release the mutex.')

                if type(new_line) == type('xyz'):
                    err_trace_handle(new_line, self.logfile, self.rawfile)
                line = ['' for x in range(10)]
                line_raw = ''
        self.waitEnd.set()
        self.alive = False

    def Reader_2x(self):
        line = ['' for x in xrange(10)]
        line_raw = ''
        last_id = 0
        while self.alive:
            try:
                if 'serial' == self.type:
                    new_line = new_line_raw = self.term.readline()
                else:
                    new_line = new_line_raw = self.term.read_until(b'\r')
                line_raw = new_line
                new_line_lst = ['' for x in xrange(10)]
                if '\xf9' in new_line:
                    frame_lst = new_line.split('\xf9')   # strip off Start/End flags: 0xf9
                    #print frame_lst
                    if frame_lst[0] is not '':
                        new_line_lst[last_id] += frame_lst[0]
                    if frame_lst[-1] is not '':
                        last_id = int(binascii.hexlify(frame_lst[-1][0]))
                    else:
                        last_id = 0
                    for frame in frame_lst[1:]:
                        if frame is not '':
                            #length check
                            if frame != frame_lst[-1] and int(binascii.hexlify(frame[1])) != len(frame[2:]):
                                print("[Error][ItermThread().Reader_2x] \033[91mError: length not match (%d, %d)\033[0m" % (int(binascii.hexlify(frame[1])), len(frame[2:])))
                            new_line_lst[int(binascii.hexlify(frame[0]))] += frame[2:]
                else:
                    new_line_lst[last_id] += new_line

                for id in range(10):
                    line[id] += new_line_lst[id].decode('utf-8', 'ignore')
                    if '\n' not in line[id]:
                        continue
                    line[id] = line[id].strip()
                    if '' == line[id]:
                        continue
                    log_line = line[id].encode('utf-8')#unicode to str
                    if is_legal_trace(log_line) and (print_fmts != [[], [], []]):
                        log_line = translate_trace_data(log_line, id)

                    # if 'win' in sys.platform.lower():
                        # log_line = log_line.replace('\x1b[91m','').replace('\x1b[0m','').replace('\r','')

                    if id is 0:
                        prt_fmt = ''
                    else:
                        prt_fmt = '[cpu '+ str(id)+'] '

                    if 'serial@ShastaPlus:#' in line[id]:
                        line[id] = 'serial@ShastaPlus:# '
                        sys.stdout.write(prt_fmt + line[id])
                        self.logfile.write(prt_fmt + datetime.now().strftime('[%Y%m%d_%H:%M:%S.%f] ') + line[id] + '\n')
                    else:
                        sys.stdout.write(prt_fmt + datetime.now().strftime('[%Y%m%d_%H:%M:%S.%f] ') + log_line + '\n')
                        self.logfile.write(prt_fmt + datetime.now().strftime('[%Y%m%d_%H:%M:%S.%f] ') + log_line + '\n')

                    sys.stdout.flush()
                    self.logfile.flush()
                    line[id] = ''
                    self.mutex.acquire()
                    ItermThread.chk_log_size(self)
                    self.mutex.release()

                self.rawfile.write(datetime.now().strftime('[%Y%m%d_%H:%M:%S.%f] ') + repr(line_raw) + '\n')
                self.rawfile.flush()
            except IOError as ex:
                self.alive = False
            except Exception as ex:
                print('[Error][ItermThread.Reader_2x()] ',ex)
                try:
                    self.mutex.release()
                except Exception as ex:
                    print('[Normal Tip] No need to release the mutex.')

                if type(new_line) == type('xyz'):
                    err_trace_handle(new_line, self.logfile, self.rawfile)
                line = ['' for x in xrange(10)]
                line_raw = ''
        self.waitEnd.set()
        self.alive = False

    def Sender(self):
        while self.alive:
            try:
                if sys.version_info.major < 3:
                    snddata = raw_input()
                else:
                    snddata = input()
                snddata = snddata.strip()
                #received "q" then exit
                if 'q' == snddata:
                    break
                # save command to file
                self.mutex.acquire()
                self.logfile.write(snddata + '\n')
                self.mutex.release()
                snddata = snddata + '\r'
                snddata = snddata.encode('utf-8')

                if sys.version_info.major == 3:
                    self.term.write(snddata)
                else:
                    for chr in snddata[0 : ]:
                        self.term.write(chr)
                        time.sleep(.005)

            except Exception as ex:
                print('[Error][ItermThread.Sender()] ',ex)
                try:
                    self.mutex.release()
                except Exception as ex:
                    print('[Normal Tip] No need to release the mutex.')

        self.waitEnd.set()
        self.alive = False

    def stop(self):
        self.alive = False
        self.term.close()
        self.logfile.close()
        self.rawfile.close()

if __name__ == '__main__':

    list = sys.argv
    #input para check
    if '--version' in sys.argv:
        print('muxterm version 3.0.0.0')
        sys.exit(0)
    if ('--usage' in sys.argv) or ('--help' in sys.argv) or (1 == len(sys.argv)):
        print('/----------------------------------------------------------------------------------------------------------------\\\n')
        print(' [Serial usage(Linux)]\n  \___ sudo ./muxterm.py [-n xx] [-e xxx] [-s xxx/xxx] <-p /dev/ttyUSB0>\t(Replace with local serial port)\n')
        print(' [Serial usage(Linux subsystem in windows)]\n  \___ ./muxterm.py [-n xx] [-e xxx] [-s xxx/xxx] <-p /dev/ttyS4>\t\t(Replace with local serial port)\n')
        print(' [Serial usage(Windows)]\n  \___ python muxterm.py [-n xx] [-e xxx] [-s xxx/xxx] <-p COM4> \t\t(Replace with local serial port)\n')
        print(' [Telnet usage]\n  \___ ./muxterm.py [-n xx] [-e xxx] [-s xxx/xxx] <-t hostip:port>\n')
        print(' [Options]')
        print('    [-n NUM]                 Specify the number of CPU cores.')
        print('    [(-e or -elf) elf-name]  Specify ELF file name.')
        print('    [-s elf-trace-path]      Specify the source path of the ELF and trace_fmtstr.h template files.')
        print('    [-d log-path]            Specify the log storage path.')
        print('    <-p port> or <-t host-ip:port>\n\t\t\t      Specify the serial port or Telnet connection port.\n')
        print(' [Tip] When you don\'t need to match the template file, just specify the <-p or -t> option.')
        print(' [Tip] The order of the options is not mandatory.')
        print(' [Tip] Windows needs to run at the administrator level.')
        print('\n\\----------------------------------------------------------------------------------------------------------------/')
        sys.exit(0)

    try:
        port_type = list[ list.index('-p') ]
        port = list[ list.index('-p') + 1 ]
    except Exception as ex:
        try:
            port_type = list[ list.index('-t') ]
            port = list[ list.index('-t') + 1 ]
        except Exception as ex:
            print('[Error][__main__] The < -p > or < -t > port type option was not found.')
            sys.exit(0)

    try:
        elf = list[ list.index('-elf') + 1 ]
    except Exception as ex:
        try:
            elf = list[ list.index('-e') + 1 ]
        except Exception as ex:
            elf = 'NULL'
            dir = 'NULL'
            core_num = 0

    if elf != 'NULL':
        try:
            core_num = int(list[ list.index('-n') + 1 ])
        except Exception as ex:
            print('[Error][__main__] The < -n > option was not found.')
            sys.exit(0)
        try:
            dir = list[ list.index('-s') + 1 ]
            if 'win' in sys.platform.lower() and dir[-1] != '\\':
                dir += '\\'
            elif 'linux' in sys.platform.lower() and dir[-1] != '/':
                dir += '/'
        except Exception as ex:
            if 'win' in sys.platform.lower():
                dir = '.\\'
            elif 'linux' in sys.platform.lower():
                dir = './'

    try:
        log_path = list[ list.index('-d') + 1 ]
        if 'win' in sys.platform.lower() and log_path[-1] != '\\':
            log_path += '\\'
        elif 'linux' in sys.platform.lower() and log_path[-1] != '/':
            log_path += '/'
    except Exception as ex:
        if 'win' in sys.platform.lower():
            log_path = '.\\log\\'
        elif 'linux' in sys.platform.lower():
            log_path = './log/'

    isExists = os.path.exists(log_path)
    if not isExists:
        os.makedirs(log_path)

    print('elf-trace-path: %s,\telf-name: %s,\tcpu-core-num: %s' % (dir, elf, core_num))
    print('port-type: %s,\tport: %s,\tlog-path: %s' % (port_type, port, log_path))

    #configure default encoding
    if sys.version_info.major < 3:
        reload(sys)
        sys.setdefaultencoding('utf-8')

    if 'NULL' != elf:
        sec_addr = [ -1 for inx in range(core_num)]
        #get trace fmts
        get_trace_fmts(dir)
        #get ro section base addr
        get_section_addr(dir, elf, core_num)

    iterm = ItermThread(port_type, port, log_path)
    try:
        if iterm.start():
            iterm.waiting()
            iterm.stop()
        else:
            pass
    except Exception as ex:
        print (ex)

    if iterm.alive:
        iterm.stop()

    print ('End OK .')
    del iterm
