Full Code of yangyss/lldb-trace for AI

script1.0.1 1a66059419c7 cached
7 files
84.5 KB
21.7k tokens
152 symbols
1 requests
Download .txt
Repository: yangyss/lldb-trace
Branch: script1.0.1
Commit: 1a66059419c7
Files: 7
Total size: 84.5 KB

Directory structure:
gitextract_o893_d24/

├── .gitignore
├── README.md
├── lldbTrace.py
├── main.mm
└── tools/
    └── verifyAlgorithm/
        ├── checkDemo
        ├── test.py
        └── wtpytracer.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/


================================================
FILE: README.md
================================================
# lldbTrace

##### How to use it?

> 1.*Break at an address where you want to begin tracing.*
>
> ![](https://github.com/yangyss/lldb-trace/blob/script/source/1111.png)
>
> 2, *Import lldb python script.*
>
> ![](https://github.com/yangyss/lldb-trace/blob/script/source/2222.png)
>
> 3,*Use 'trace' command,and set end tracing addresses.Multi-address split by ";".*
>
> ![](https://github.com/yangyss/lldb-trace/blob/script/source/3333.png)
>
> 4,*Result  like  ...*
>
> ![](https://github.com/yangyss/lldb-trace/blob/script/source/4444.png)



> *参考:https://github.com/gm281/lldb-trace*



================================================
FILE: lldbTrace.py
================================================
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
#@File    :   lldb-trace.py
#@Time    :   2021/06/25 22:16:01
#@Author  :   wt 

import re
import lldb
import shlex
import optparse
import threading
import ctypes
import os
 


log_default_path = '~/Desktop/' # 默认路径 , 

options = None
d_log_file = None   # fileName : Redirect debug log in d_log_file
d_log_file_name = None
t_log_file = None   # fileName : Redirect trace log in t_log_file
t_log_file_name = None
t_only_self_module = None 
t_parser_msgsend_parameters = None
ASLR = None
num_for_print_progress = 500 # 进度条

def log_d(msg): # debug log
    global d_log_file,options
    if options.log_type == 'debug':
        d_log_file.write(msg)
        d_log_file.write('\n')

def log_t(msg): # trace log
    global t_log_file
    t_log_file.write(msg)
    t_log_file.write('\n')

def log_c(msg): # console log
    global options
    if options.print_tracing_progress:
        print(msg)
    
def log_flush():
    global d_log_file,t_log_file
    if d_log_file is not None:
        d_log_file.flush()
    if t_log_file is not None:
        t_log_file.flush()

def dlog(msg):
    print("xxxxxxxxx-> {}".format(msg))

# 调试类型
TRACE_TYPE_Instrument = 0,
TRACE_TYPE_Function = 1,
# 设备架构 
DEVICE_BSD32 = 'BSD32'
DEVICE_BSD64 = 'BSD64'
DEVICE_Arm64 = 'Arm64'
DEVICE_x8664 = 'x86-64'
DEVICE_x8632 = 'x86-32'
# 调试中需要处理的 汇编指令信息
CONST_INS_call = 'call',
CONST_INS_jmp = 'jmp',
CONST_INS_condition_jmp = 'condition_jmp',
CONST_INS_syscall = 'syscall',
CONST_INS_end = 'func_end_mnemonic'
CONST_FUNC_NAME_ignore_list = 'ignore_func_name_list'
CONST_FUNC_NAME_protect_list = 'protect_func_name_list'
CONST_PRINT_obj = 'obj'
CONST_PRINT_char_star = 'char_star'
CONST_REGISTER_re = 're'
CONST_REGISTER_default_return_register = 'default_return_register'


# 断点列表里的 key 
CONST_BREAKPOINT_BREAKPOINE = 'breakpoint',
CONST_BREAKPOINT_INDEX = 'index',  # 引用计数

# deal_with 的 返回值
CONST_DEAL_WITH_error = 0,
CONST_DEAL_WITH_continue = 1,
CONST_DEAL_WITH_wait_breakpoint = 2,
CONST_DEAL_WITH_break = 3,
# check ins end type
CONST_CHECK_ins_default = 0
CONST_CHECK_ins_ret = 1
CONST_CHECK_ins_end_address =2


#########################################################
CONST_DEVICE_info_list = {
    DEVICE_BSD64 : {
        CONST_FUNC_NAME_ignore_list : ['printf','objc_unsafeClaimAutoreleasedReturnValue','objc_storeStrong'],
        CONST_FUNC_NAME_protect_list : {
            'objc_msgSend' : {
                # if trace function,need to analyse parameters. if parser_msgsend_parameters was true, need to analyse parameters too.
                CONST_PRINT_obj:['po [$x0 class]'],
                CONST_PRINT_char_star:['x1']
            }
        },
        CONST_REGISTER_re : [r'\b[xwd][0-9]{1,2}',r'\b[xwd][0-9]{1,2},',r'sp'], # r'\b[xw][0-9]{1,2}[,]{0,1}'
        CONST_REGISTER_default_return_register:'x0',

        CONST_INS_call : ['bl'],#,'bl',
        CONST_INS_jmp  : ['cb','b','tb'],#'b',
        CONST_INS_condition_jmp : ['b'],
        CONST_INS_syscall : ['svc'],#'svc'
        CONST_INS_end : ['ret']
    },
    DEVICE_Arm64 : {},
    DEVICE_x8664 : {},
    DEVICE_x8632 : {}
}
#########################################################
# 当前设备类型
DEVICE = DEVICE_BSD64
#########################################################


class WTListeningThread(threading.Thread):
    def __init__(self, wait_event, notify_event,listener,process):
        super(WTListeningThread, self).__init__()
        self.wait_event = wait_event
        self.notify_event = notify_event
        self.listener = listener
        self.process = process
        self.exiting = False
        self.wait_timeout = False

    def wait_timed_out(self):
        return self.wait_timeout

    def exit(self):
        self.exiting = True

    def run(self):
        steam :lldb.SBStream = lldb.SBStream()
        while True:
            self.wait_event.wait()
            self.wait_event.clear()
            if self.exiting:
                log_d('=>>>Listener thread was asked to exit, complying')
                self.notify_event.set()
                return
            while True:
                event = lldb.SBEvent()
                steam.Clear()
                log_d('=>>>Listener waiting for events')
                wait_result = self.listener.WaitForEvent(10, event)
                event.GetDescription(steam)
                log_d('=>>>Listener wait exited: {}, {}'.format(str(wait_result), steam.GetData()))

                if not wait_result:
                    log_d('=>>>Listener thread timed out waiting for notification')
                    self.wait_timeout = True
                    self.notify_event.set()
                    break
                processState = self.process.GetState()
                if processState == lldb.eStateStopped:
                    log_d('=>>>Listener detected process state change, but it is not stopped: {}'.format(str(processState)))
                    break
                log_d('=>>>Process not stopped, listening for the next event')
            log_d('=>>>Listener thread got event, notifying')
            self.notify_event.set()

def get_c_char_star(address):
    retstr = ''
    curr_addr = address
    while True:
        p = ctypes.cast(curr_addr,ctypes.POINTER(ctypes.c_char))
        value = p.contents.value
        if not (value[0] == 0) :
            retstr = retstr + chr(value[0])
            curr_addr = curr_addr + 1
        else:
            break
    return retstr

def handle_command(command,debugger:lldb.SBDebugger):
    log_d('handle_command -> command : {}'.format(command))
    interpreter:lldb.SBCommandInterpreter = debugger.GetCommandInterpreter()
    re_obj:lldb.SBCommandReturnObject = lldb.SBCommandReturnObject()
    interpreter.HandleCommand(command,re_obj)
    result = ''
    log_d('handle_command -> re_obj status : {}'.format(re_obj.GetStatus()))
    if re_obj.GetStatus() == lldb.eReturnStatusSuccessFinishResult:
        result = re_obj.GetOutput()
    # print('|{}|'.format(result.replace('\n','')))
    return result.replace('\n','')

def continue_and_wait_for_breakpoint(process, thread, listening_thread, wait_event, notify_event):
    wait_event.set()
    log_d("Process in state: {}".format(str(process.GetState())))
    process.Continue()
    log_d('Process continued, waiting for notification')
    notify_event.wait()
    notify_event.clear()
    log_d('Got notification, process in state: {}, sanity checks follow'.format(str(process.GetState())))
    if listening_thread.wait_timed_out():
        log_d('Listener thread exited unexpectedly')
        return False
    if thread.GetStopReason() != lldb.eStopReasonBreakpoint:
        log_d("Thread {} didn't stop due to a breakpoint".format(str(thread)))
        return False
    return True

def suspend_threads_escape_select_thread(process:lldb.SBProcess,flag:bool):
    select_thread :lldb.SBThread = process.GetSelectedThread()
    if flag :
        for item in process:
            if select_thread.GetThreadID() == item.GetThreadID():
                log_d('current run thread : {}'.format(item))
            else:
                log_d('Suspend thread : {}'.format(item))
                item.Suspend()
    else:
        log_d('Resume all threads.')
        for item in process:
            item.Resume()
    
            

def match_registers(text):
    now_list = []
    fileters = CONST_DEVICE_info_list[DEVICE][CONST_REGISTER_re]
    for item in fileters:
        find_result = re.finditer(item,text)
        match : str = ''
        for match in find_result:
            tmpStr = '{}'.format(match.group())
            if tmpStr.find(',') >= 0 :
                if not(tmpStr[:-1] in now_list) :
                    now_list.append(tmpStr[:-1])
            else:
                if not(tmpStr in now_list):
                    now_list.append(tmpStr)
    return now_list

class WTInstruction():
    def __init__(self, target, thread, frame,debugger,traceType=TRACE_TYPE_Instrument,traceMsgSend=False,endAddress=None):
        self.target:lldb.SBTarget = target
        self.thread:lldb.SBThread = thread
        self.frame:lldb.SBFrame = frame
        self.debugger:lldb.SBDebugger = debugger

        self.trace_type = traceType      # Trace 类型

        self.next_instruction:lldb.SBInstruction = None   # 下一条 instruction
        self.current_instruction:lldb.SBInstruction = None # 当前 instruction
        self.last_instruction:lldb.SBInstruction = None # 上一条 instruction

        self.begin_trace_address = None  # 开始 Trace 地址
        self.end_trace_address = []

        for item in re.split(';',endAddress):
            self.end_trace_address.append(int(item,16)) # 结束 Trace 地址

        # 包含 breakpoint : 以及 引用计数 used_num :
        self.breakpoint_list = {}   # 所有断点 的 list
        self.current_instruction_list = {} # 当前 symbol 下的 所有的 instruction 列表
        self.current_instruction_end_address_list = [] # 当前 symbol 下的 所有的  end_address 列表
        self.call_return_instruction_list = {} # tracing 中,所有函数返回的地址 列表

        self.current_module_name:str = None # 当前模块

        self.append_msg = '' # 附加消息

        self.print_index = 0
        self.print_text = '    '

    def increase_print_index(self):
        log_d('@@@@ increase print index. {} : {}'.format(self.print_index,self.print_index + 1))
        self.print_index = self.print_index + 1
        
    
    def check_in_call_return_instruction_list(self):
        pc = self.get_current_pc()
        if pc in self.call_return_instruction_list:
            log_d('@@@@ {} in call_return_instruction_list'.format(hex(pc)))
            return True
        log_d('@@@@ {} not in call_return_instruction_list'.format(hex(pc)))
        return False

    def decrease_print_index(self):
        log_d('@@@@ decrease print index. {} : {}'.format(self.print_index,self.print_index - 1))
        self.print_index = self.print_index - 1

    def check_str_in_arr(self,cur_str:str,cur_arr):
        for item in cur_arr:
            if cur_str.startswith(item):
                return True
        return False

    def init_env(self):

        frame :lldb.SBFrame = self.thread.GetSelectedFrame()
        symbol:lldb.SBSymbol = frame.GetSymbol()

        if self.current_module_name is None:
            self.current_module_name:str = '{}'.format(self.frame.GetModule())
            log_d('current module name : {}'.format(self.current_module_name))

        
        instructionlist : lldb.SBInstructionList = symbol.GetInstructions(self.target)
        # 清空 current_instruction_list  和 current_instruction_end_address_list
        if self.current_instruction_list:
            self.current_instruction_list = {}
            self.current_instruction_end_address_list = []
            
        # endaddress 加入到 end tracing 地址列表中
        cur_end_address = symbol.GetEndAddress().GetLoadAddress(self.target) - 4
        self.end_trace_address.append(cur_end_address)   
        
        # 把 返回指令的 地址 加入到 end tracing 地址列表中
        instruction :lldb.SBInstruction = None
        for instruction in instructionlist:
            address :lldb.SBAddress = instruction.GetAddress()
            cur_mnemonic:str = instruction.GetMnemonic(self.target)
            load_address = address.GetLoadAddress(self.target)
            if self.check_str_in_arr(cur_mnemonic,CONST_DEVICE_info_list[DEVICE][CONST_INS_end]):
                if not load_address in self.end_trace_address:
                    self.end_trace_address.append(load_address)


    # 获得当前 pc
    def get_current_pc(self):
        now_frame :lldb.SBFrame = self.thread.GetSelectedFrame()
        if now_frame:
            return now_frame.GetPC()
        return None

    # 判断当前 pc 是否在 list 中
    # 不在的话,更新所有 list
    def checkPCInList_transferCurrentSymbolInstrucionsToList(self,address):
        # current_instruction_list 为空,或者  cur_pc(有效) 不在 current_instruction_list 里
        if not self.current_instruction_list or (address and (not (address in self.current_instruction_list))) :
            frame :lldb.SBFrame = self.thread.GetSelectedFrame()
            symbol:lldb.SBSymbol = frame.GetSymbol()
            ################## 给 current_instruction_end_address_list 赋值
            # 获得 当前 symbol 下的 endAddress
            cur_end_address = symbol.GetEndAddress().GetLoadAddress(self.target) - 4
            log_d('cur symbol end addr : {}'.format(hex(cur_end_address)))
            self.current_instruction_end_address_list = []
            # 把 结束地址,加入到 current_instruction_end_address_list 中
            self.current_instruction_end_address_list.append(cur_end_address)

            # 给 current_instruction_list 赋值
            # 获得 当前 symbol 下的 instructionlist
            instructionlist : lldb.SBInstructionList = symbol.GetInstructions(self.target)

            # 清空 current_instruction_list
            if self.current_instruction_list:
                self.current_instruction_list = {}
                self.current_instruction_end_address_list = {}

            instruction :lldb.SBInstruction = None            
            # 处理 所有的 instruction,
            for instruction in instructionlist:
                address :lldb.SBAddress = instruction.GetAddress()
                cur_mnemonic:str = instruction.GetMnemonic(self.target)
                load_address = address.GetLoadAddress(self.target)
                self.current_instruction_list[load_address] = instruction  

            return False
        return True

    def updata_instruction_instructionList(self):
        cur_pc = self.get_current_pc()     
        self.checkPCInList_transferCurrentSymbolInstrucionsToList(cur_pc)

        if cur_pc in self.current_instruction_list:
            self.current_instruction = self.current_instruction_list[cur_pc]
        else:
            self.current_instruction = None


    def clean_env(self):
        for item in self.breakpoint_list.values():
            breakpoint :lldb.SBBreakpoint = item[CONST_BREAKPOINT_BREAKPOINE]
            self.target.BreakpointDelete(breakpoint.GetID())     
        self.breakpoint_list = {}


    def deal_with(self):
        return self.deal_with_ins()

    def updata_last_instruction(self):
        self.last_instruction = self.current_instruction

    def get_current_symbol_name(self):
        frame:lldb.SBFrame = self.thread.GetSelectedFrame()
        sym:lldb.SBSymbol = frame.GetSymbol()
        return sym.GetName()

    def get_next_instruction(self):
        pc = self.get_current_pc()
        size = self.current_instruction.GetByteSize()
        next_pc = pc + size
        self.checkPCInList_transferCurrentSymbolInstrucionsToList(next_pc)
        if next_pc in self.current_instruction_list:
            self.next_instruction = self.current_instruction_list[next_pc]
        else:
            self.next_instruction = None

    def print_tracing_progress(self,count):
        # 当前trace的总行数 内存地址:文件地址: <函数名>
        global ASLR
        mem_addr = 0
        file_addr = 0
        if self.current_instruction:
            mem_addr = self.current_instruction.GetAddress().GetLoadAddress(self.target)
        if not (mem_addr == 0) :
            file_addr = mem_addr - ASLR   
        out_str = '{: <10}  {} : {} <{}>'.format(count,hex(mem_addr),hex(file_addr),self.get_current_symbol_name())
        log_c(out_str)

    def log_current_instruction(self,cur_pc):
        cur_mnemonic:str = self.current_instruction.GetMnemonic(self.target)
        cur_operands:str = self.current_instruction.GetOperands(self.target)
        aligns = self.print_text * self.print_index
        if self.last_instruction:
            last_mnemonic:str = self.last_instruction.GetMnemonic(self.target)      
            if self.check_str_in_arr(last_mnemonic,CONST_DEVICE_info_list[DEVICE][CONST_INS_call]) :
                frame:lldb.SBFrame = self.thread.GetSelectedFrame()
                return_register = CONST_DEVICE_info_list[DEVICE][CONST_REGISTER_default_return_register]
                value:lldb.SBValue = frame.FindRegister(return_register)
                data_str = '{: <3} : {} '.format(return_register,value.GetValue())
                log_t('{}{: <15}{: <6}{: <30}// {} {}'.format(aligns,hex(cur_pc),cur_mnemonic,cur_operands,data_str,self.append_msg))
                self.append_msg = ''
                return  
            last_operands:str = self.last_instruction.GetOperands(self.target)      
            register_arr = match_registers(last_operands)
            data_str = ''
            for now_reg in register_arr:
                frame:lldb.SBFrame = self.thread.GetSelectedFrame()
                value:lldb.SBValue = frame.FindRegister(now_reg)
                data_str = '{}{: <3} : {} '.format(data_str,now_reg,value.GetValue())
            
            log_t('{}{: <15}{: <6}{: <30}// {} {}'.format(aligns,hex(cur_pc),cur_mnemonic,cur_operands,data_str,self.append_msg))
            self.append_msg = ''
            return
        log_t('{}{: <15}{: <6}{: <30} {}'.format(aligns,hex(cur_pc),cur_mnemonic,cur_operands,self.append_msg))
        self.append_msg = ''

    def parser_ins_symbol_name(self,last_symbole_name:str,cur_symbol_name : str):

        if not cur_symbol_name  or not last_symbole_name:
            log_d('err : cur_symbol_name or last_symbole_name is None')
            return True

        if cur_symbol_name in CONST_DEVICE_info_list[DEVICE][CONST_FUNC_NAME_ignore_list]:
            # 忽略的 符号名
            log_d('cur_symbol_name in ignore_function_names')
            return True

        if cur_symbol_name in CONST_DEVICE_info_list[DEVICE][CONST_FUNC_NAME_protect_list]:
            # # 设置 附加信息 
            
            # # log_t('{}<< current frame name >> :  {}'.format(aligens,cur_symbol_name))
            # frame :lldb.SBFrame = self.thread.GetSelectedFrame()
            
            # for pro_key,pro_value in CONST_DEVICE_info_list[DEVICE][CONST_FUNC_NAME_protect_list].items():
                
            #     if pro_key == cur_symbol_name:

            #         objs = pro_value[CONST_PRINT_obj]
            #         char_stars = pro_value[CONST_PRINT_char_star]
                    
            #         for char_star_item in char_stars: 
            #             func_name_register:lldb.SBValue = frame.FindRegister(char_star_item)
            #             addr = int(func_name_register.GetValue(),16)
                        # self.append_msg = ' : {}{: <3} ==> {} '.format(self.append_msg,char_star_item,get_c_char_star(addr))
                    
            #         for obj_item in objs:
            #             item_value =  handle_command(obj_item,self.debugger)
            #             self.append_msg = '{}{: <3} ==> {} '.format(self.append_msg,obj_item,item_value)

            #         break

            # log_d('cur_symbol_name in protect_function_names')
            # return True
            pass

        return False

    def add_next_breakpoint(self):
        if self.next_instruction:
            next_pc = self.next_instruction.GetAddress().GetLoadAddress(self.target)
            if next_pc in self.breakpoint_list:
                breakpoint = self.breakpoint_list[next_pc][CONST_BREAKPOINT_BREAKPOINE]
                log_d('->>> increase index on breakpoint : {}'.format(str(breakpoint)))
                self.breakpoint_list[next_pc][CONST_BREAKPOINT_INDEX] = self.breakpoint_list[next_pc][CONST_BREAKPOINT_INDEX] + 1
            else:
                breakpoint :lldb.SBBreakpoint = self.target.BreakpointCreateByAddress(next_pc)
                breakpoint.SetThreadID(self.thread.GetThreadID())
                item = {}
                item[CONST_BREAKPOINT_BREAKPOINE] = breakpoint
                item[CONST_BREAKPOINT_INDEX] = 1
                self.breakpoint_list[next_pc] = item
                log_d('->>> add address : {}  breakpoint : {}'.format(hex(next_pc),str(breakpoint)))
    
    def add_call_return_addr(self):
        if self.next_instruction:
            next_pc = self.next_instruction.GetAddress().GetLoadAddress(self.target)
            log_d('add {} index in call_return_instruction_list.'.format(hex(next_pc)))
            if next_pc in self.call_return_instruction_list:
                self.call_return_instruction_list[next_pc] = self.call_return_instruction_list[next_pc] + 1
            else:
                self.call_return_instruction_list[next_pc] = 1

    def sub_call_return_addr(self):
        pc = self.get_current_pc()
        if pc in self.call_return_instruction_list:
            log_d('@@@@ delete call return addr : {} out of call_return_instruction_list.'.format(hex(pc)))
            if self.call_return_instruction_list[pc] > 1:
                tmp = self.call_return_instruction_list[pc]
                self.call_return_instruction_list[pc] = tmp - 1
            else:
                self.call_return_instruction_list.pop(pc)


    def check_need_delete_breakpoint_in_current_call_return_list_and_decrease_index(self,cur_pc):
        if cur_pc in self.call_return_instruction_list:
            index = self.call_return_instruction_list[cur_pc]
            if index > 0 :
                self.call_return_instruction_list[cur_pc] = index - 1
                return True
            else:
                self.call_return_instruction_list.pop(cur_pc)
        return False 

    def delete_current_breakpoint(self):
        if self.current_instruction:
            curr_pc = self.current_instruction.GetAddress().GetLoadAddress(self.target)
            if not curr_pc in self.breakpoint_list:
                log_d('->>> {} not in breakpoint_list'.format(hex(curr_pc)))
                return
            item = self.breakpoint_list[curr_pc]
            if not item :
                log_d('->>> curr address : {} not in breakpoint_list'.format(hex(curr_pc)))
                return
            index = item[CONST_BREAKPOINT_INDEX]
            if index > 1 :
                log_d('->>> increase index on breakpoint : {}'.format(str(item[CONST_BREAKPOINT_BREAKPOINE])))
                self.breakpoint_list[curr_pc][CONST_BREAKPOINT_INDEX] = index - 1
            elif index == 1:
                delete_breakpoint :lldb.SBBreakpoint = item[CONST_BREAKPOINT_BREAKPOINE]
                if not self.check_need_delete_breakpoint_in_current_call_return_list_and_decrease_index(curr_pc):
                    self.target.BreakpointDelete(delete_breakpoint.GetID())
                    log_d('**** delet breakpoint at : {}'.format(hex(self.get_current_pc())))
                self.breakpoint_list.pop(curr_pc)
            else:
                log_c('->>> {} : breakpoint delete error'.format(hex(curr_pc)))
                log_d('->>> {} : breakpoint delete error'.format(hex(curr_pc)))

    def check_currentIns_is_endIns(self):
        if self.current_instruction:
            size = self.current_instruction.GetByteSize()
            pc = self.get_current_pc()
            nextpc = pc + size
            if nextpc in self.current_instruction_end_address_list:
                log_d('addr : {} in current_instruction_end_address_list'.format(hex(nextpc)))
                return True,CONST_CHECK_ins_end_address

            mnemonic:str = self.current_instruction.GetMnemonic(self.target)
            for ins_end_item in CONST_DEVICE_info_list[DEVICE][CONST_INS_end]:
                if mnemonic.startswith(ins_end_item):
                    log_d('addr : {} is CONST_INS_end'.format(hex(pc)))
                    return True,CONST_CHECK_ins_ret
            log_d('addr : {} is default ins.'.format(hex(pc)))
            return False,CONST_CHECK_ins_default
        else:
            log_d('warning : current ins is None.')
            log_c('warning : current ins is None.')
        return False,CONST_CHECK_ins_default

    def check_ins_call(self,mnemonic:str,cur_symbol:lldb.SBSymbol):
        for call_item  in CONST_DEVICE_info_list[DEVICE][CONST_INS_call]:
            if not mnemonic.startswith(call_item):
                continue
            pc = self.get_current_pc()
            self.get_next_instruction() # 获得下一条指令
            if not self.next_instruction is None:       
                self.add_next_breakpoint()
                self.add_call_return_addr()

            last_symbol_name = self.get_current_symbol_name()
            self.delete_current_breakpoint()# 删除当前断点
            self.thread.StepInstruction(False) # 单步进入
            sym_name = self.get_current_symbol_name()

            if self.parser_ins_symbol_name(last_symbol_name,sym_name) :  # 解析 symbol_name
                self.append_msg = sym_name + self.append_msg
                self.log_current_instruction(pc)
                self.increase_print_index()
                log_d('####### return : check_ins_call. ignore fun or protect fun. value : CONST_DEAL_WITH_wait_breakpoint')
                return True,CONST_DEAL_WITH_wait_breakpoint
                
            self.log_current_instruction(pc) # 打印信息
            if not(sym_name == last_symbol_name) :
                if sym_name and (not (sym_name == '')):
                    log_t('{}{} : '.format(self.print_text * self.print_index,sym_name))

            # 忽略的,保护的,需要  CONST_DEAL_WITH_wait_breakpoint
            self.increase_print_index()

            log_d('####### return : check_ins_call. value : CONST_DEAL_WITH_continue')
            return True,CONST_DEAL_WITH_continue
        
        return False,None

    def check_ins_jmp(self,mnemonic:str,cur_symbol:lldb.SBSymbol):
        for jmp_item  in CONST_DEVICE_info_list[DEVICE][CONST_INS_jmp]:
            if not mnemonic.startswith(jmp_item):
                continue
            
            pc = self.get_current_pc()
            self.get_next_instruction() # 获得下一条指令
            if not self.next_instruction is None:       
                self.add_next_breakpoint()

            last_symbol_name = self.get_current_symbol_name()
            self.delete_current_breakpoint()
            self.thread.StepInstruction(False)

            sym_name = self.get_current_symbol_name()

            if sym_name and self.parser_ins_symbol_name(last_symbol_name,sym_name):
                print('type : {} symName : {}'.format(type(sym_name),sym_name))
                if self.append_msg == None:
                    self.append_msg = ''
                self.append_msg = sym_name + self.append_msg
                self.log_current_instruction(pc)
                log_d('####### return : check_ins_jmp. ignore fun or protect fun. value : CONST_DEAL_WITH_wait_breakpoint')
                return True,CONST_DEAL_WITH_wait_breakpoint

            self.log_current_instruction(pc) # 打印信息

            log_d('####### return : check_ins_jmp. same module. value : CONST_DEAL_WITH_continue')
            return True,CONST_DEAL_WITH_continue
        
        return False,None

    def check_ins_syscall(self,mnemonic:str,cur_symbol:lldb.SBSymbol):
        for syscall_item in CONST_DEVICE_info_list[DEVICE][CONST_INS_syscall]:
            if not mnemonic.startswith(syscall_item):
                continue


            self.get_next_instruction() # 获得下一条指令
            if not self.next_instruction is None:       
                self.add_next_breakpoint()

            self.delete_current_breakpoint()
            
            self.log_current_instruction(self.get_current_pc()) # 打印信息
            log_d('####### return : check_ins_syscall. value : CONST_DEAL_WITH_wait_breakpoint')
            return True,CONST_DEAL_WITH_wait_breakpoint

        return False,None

    def check_ins_other(self,cur_symbol:lldb.SBSymbol):
        self.get_next_instruction() # 获得下一条指令
        if not self.next_instruction is None:       
            self.add_next_breakpoint()

        self.delete_current_breakpoint()
        self.log_current_instruction(self.get_current_pc())        # 打印信息

    def check_out_tracing(self):
        # 递归函数的处理 。。。。。。。
            
        pc = self.get_current_pc()
        if pc in self.end_trace_address:
            self.delete_current_breakpoint()
            self.log_current_instruction(pc)
            log_d('end trace addr list : {}'.format(self.end_trace_address))
            log_d('cur pc : {}'.format(pc))
            return True
        return False

    def check_end_fun(self):
        # 当前在结束地址       
        flag,ret = self.check_currentIns_is_endIns()
        if flag :
            if ret == CONST_CHECK_ins_ret:
                pc = self.get_current_pc()
                self.delete_current_breakpoint()
                self.log_current_instruction(pc)
                log_d('@@@@ check_end_fun : address : {} is ret ins.'.format(hex(pc)))
                return  True,CONST_DEAL_WITH_wait_breakpoint
            elif ret == CONST_CHECK_ins_end_address:
                last_pc = self.get_current_pc()
                self.thread.StepInstruction(False)
                self.delete_current_breakpoint()
                # 判断当前pc 是否在 instructionList中
                pc = self.get_current_pc()
                if pc in self.current_instruction_list:
                    self.log_current_instruction(last_pc)
                    log_d('@@@@ check_end_fun : address : {} is call end address,and in current_instruction_list.'.format(hex(last_pc)))
                    return True,CONST_DEAL_WITH_continue
                else:
                    # 可以 decrease print index
                    self.log_current_instruction(last_pc)
                    log_d('@@@@ check_end_fun : address : {} is call end address,and not in current_instruction_list.'.format(hex(last_pc)))
                    return True,CONST_DEAL_WITH_wait_breakpoint
            else:
                pass
        log_d('@@@@ check_end_fun : address : {} is not call end address or ret ins.'.format(hex(self.get_current_pc())))
        return False,None

    def check_symbol_valid(self):
        now_frame :lldb.SBFrame =  self.thread.GetSelectedFrame()
        if now_frame:
            sym:lldb.SBSymbol = now_frame.GetSymbol()
            if not sym.IsValid():
                log_d('####### return : check_symbol_valid not valid. value : CONST_DEAL_WITH_wait_breakpoint')
                return False,CONST_DEAL_WITH_wait_breakpoint
        log_d('@@@@ check_symbol_valid : valid.')
        return True,None

    def check_in_module(self):
        frame :lldb.SBFrame = self.thread.GetSelectedFrame()
        now_module_name = '{}'.format(frame.GetModule())
        log_d('@@@@ current module name : {}'.format(now_module_name))
        if now_module_name == self.current_module_name :
            return True,None
        log_d('####### return : check_in_module. is not current module. value : CONST_DEAL_WITH_wait_breakpoint')
        return False,CONST_DEAL_WITH_wait_breakpoint


    def deal_with_ins(self):

        if self.check_in_call_return_instruction_list():
            self.decrease_print_index()
            self.sub_call_return_addr()

        # 结束tracing
        if self.check_out_tracing():
            log_d('####### return : check_out_tracing value : CONST_DEAL_WITH_break')
            return CONST_DEAL_WITH_break

        # 函数结束的判断
        flag,ret = self.check_end_fun()
        if flag:
            log_d('####### return : check_end_fun')
            return ret
        
        # frame.GetFunction 和 frame.GetSymbol 是否有效
        flag,ret = self.check_symbol_valid()
        if not flag :
            return ret

        global t_only_self_module
        if t_only_self_module :
            flag,ret = self.check_in_module()
            if not flag:
                return ret
        
        instruction:lldb.SBInstruction = self.current_instruction
        mnemonic = None
        if instruction :
            mnemonic:str = instruction.GetMnemonic(self.target)
        else:
            log_d('warning : instruction is None')
            log_c('warning : instruction is None')

        cur_frame:lldb.SBFrame = self.thread.GetFrameAtIndex(0)
        cur_symbol:lldb.SBSymbol = cur_frame.GetSymbol()  
        flag,value = self.check_ins_call(mnemonic,cur_symbol) # call 指令 操作
        if flag:
            log_d('check_ins_call')
            return value
            
        flag,value = self.check_ins_jmp(mnemonic,cur_symbol) # jmp 指令 操作
        if flag:
            log_d('check_ins_jmp')
            return value

        flag,value = self.check_ins_syscall(mnemonic,cur_symbol)  # syscall 指令 操作
        if flag :
            log_d('check_ins_syscall')
            return value

        self.check_ins_other(cur_symbol)  # 其他指令的操作
        log_d('####### return : check_ins_other. value : CONST_DEAL_WITH_wait_breakpoint')
        return CONST_DEAL_WITH_wait_breakpoint
        
    

       


class WTFunction():
    def __init__(self, *args):
        pass
    def deal_with_fun(self):
        pass
        

class TraceOptionParser(optparse.OptionParser):
    def __init__(self, result):
        optparse.OptionParser.__init__(self)
        self.result = result
        self.exited = False

    def get_prog_name(self):
        return "trace"

    def exit(self, status=0, msg=None):
        if msg is not None:
            # print >>self.result, msg
            print(msg,file=self.result)
        self.exited = True

def parse_options(command, result):
    global options
    command_tokens = shlex.split(command)
    parser = TraceOptionParser(result)
    parser.add_option("-e","--end-address",action="store",metavar="END_ADDRESS",dest="end_address",help="End addresses of trace,using to stop trace thread.More address,use ';' to split.")
    parser.add_option("-o","--only-tracing-self-module",action="store_true",dest="only_tracing_self_module",default=True,help="Only tracing in current module.Default is True")
    parser.add_option("-m","--mode-type",action="store",metavar="<instruction/function>",dest="mode_type",default="instruction",help='Tracing mode,contains function and instruction.Default is instruction mode.')
    parser.add_option("-l","--log-type",action="store",metavar="<trace/debug>",dest="log_type",default='trace',help="Set log type for this tracing. With trace type redirect trace output file. With debug type redirect trace and debug output files.Default is trace type.")
    parser.add_option("-P","--parser-msgsend-parameters",action="store_true",dest="parser_msgsend_parameters",default=False,help="Parser objc_msgsend function's parameters.Default is False")
    parser.add_option("-p","--print-tracing-progress",action="store_true",dest="print_tracing_progress",default=True,help="Print tracing progress in console.Default is True")
    parser.add_option("-s","--suspend-threads-except-current-thread",action="store_true",dest="suspend_threads",default=True,help="Suspend threads except current thread,to clean env.Default is True")
    (options, _) = parser.parse_args(command_tokens)

    return parser.exited

def check_parser_command():
    global options
    global t_only_self_module,t_parser_msgsend_parameters
    global t_log_file,t_log_file_name,d_log_file,d_log_file_name

    if options.end_address is None :
        print('err : plz input an address where you want to end tracing.')
        return False

    log_type_arr = ['trace','debug']
    if not options.log_type in log_type_arr :
        print('err : plz input -l --log-type value, use "trace" or "debug".')
        return False

    mode_type_arr = ['function','instruction']
    if not options.mode_type in mode_type_arr:
        print('err : plz input -m --mode-type value, use "function" or "instruction".')
        return False

    if options.log_type == 'trace':
        print(type(t_log_file_name))
        print(t_log_file_name)
        t_log_file = open(t_log_file_name,'w')

    if options.log_type == 'debug':
        t_log_file = open(t_log_file_name,'w')
        d_log_file = open(d_log_file_name,'w')

    t_only_self_module = options.only_tracing_self_module
    t_parser_msgsend_parameters = options.parser_msgsend_parameters
    return True

def ini_log_file(mode_name:str):
    import time
    global log_default_path,t_log_file_name,d_log_file_name
    timeName = int(time.time())
    if mode_name == 'instruction':
        if log_default_path.endswith('/'):
            t_log_file_name = "{}{}{}".format(log_default_path,timeName,'instrace.log')
            d_log_file_name = "{}{}{}".format(log_default_path,timeName,'insdebug.log')
            log_c('trace log file : {}'.format(t_log_file_name))
            log_c('debug log file : {}'.format(d_log_file_name))
        else:
            t_log_file_name = "{}/{}{}".format(log_default_path,timeName,'instrace.log')
            d_log_file_name = "{}/{}{}".format(log_default_path,timeName,'insdebug.log')
            log_c('trace log file : {}'.format(t_log_file_name))
            log_c('debug log file : {}'.format(d_log_file_name))
        
    elif mode_name == 'function':

        if log_default_path.endswith('/'):
            t_log_file_name = "{}{}{}".format(log_default_path,timeName,'funtrace.log')
            d_log_file_name = "{}{}{}".format(log_default_path,timeName,'fundebug.log')
            log_c('trace log file : {}'.format(t_log_file_name))
            log_c('debug log file : {}'.format(d_log_file_name))
        else:
            t_log_file_name = "{}/{}{}".format(log_default_path,timeName,'funtrace.log')
            d_log_file_name = "{}/{}{}".format(log_default_path,timeName,'fundebug.log')
            log_c('trace log file : {}'.format(t_log_file_name))
            log_c('debug log file : {}'.format(d_log_file_name))
    else:
        print('err : trace mode err.')    


def test(debugger:lldb.SBDebugger):
    return False
    # import sys
    # import os
    # print(sys.argv[0])
    # print(__file__)
    # current_path = os.path.abspath(__file__)
    # print(current_path)
    # father_path = os.path.abspath(os.path.dirname(current_path) + os.path.sep + ".")
    # print(father_path)
    # global options
    # endAddress = options.end_address
    # a = re.split(';',endAddress)
    # for item in a:
    #     print(type(int(item,16)))
    #     print(int(item,16))
    #     print(item)
    # print(a)
    # target: lldb.SBTarget = debugger.GetSelectedTarget()
    # process: lldb.SBProcess = target.GetProcess()
    # thread: lldb.SBThread = process.GetSelectedThread()
    # frame: lldb.SBFrame = thread.GetSelectedFrame()
    # symbol :lldb.SBSymbol = frame.GetSymbol()
    
    # print(frame.GetModule())
    # print('frame : {}'.format(frame))
    # print('symbol.Instructions : ')
    # print(symbol.GetInstructions(target))
    # print('symbol : {}'.format(symbol))
    # print('symbol.Name : "{}"'.format(symbol.GetName()))
    # print('thread : {}'.format(thread))
    # print('thread name : {}'.format(thread.GetName()))
    # ins:lldb.SBInstruction = None
    # stream:lldb.SBStream = lldb.SBStream()
    # for ins in symbol.GetInstructions(target):
    #     # print(ins.GetData(target))
    #     ins.GetDescription(stream)
    #     addr :lldb.SBAddress = ins.GetAddress()
    #     module : lldb.SBModule = addr.GetModule()
    #     print('module : {}'.format(module))
    #     sym : lldb.SBSymbol = None
    #     for sym in module:
    #         print('sym name : {}'.format(sym.GetName()))

    #     break
    # print('symbol valid : {}'.format(symbol.IsValid()))
    # print('symbol DisplayName : {}'.format(symbol.GetDisplayName()))
    # print('symbol MangledName : {}'.format(symbol.GetMangledName()))


    return True

def trace(debugger: lldb.SBDebugger, command: str, result: lldb.SBCommandReturnObject, internal_dict):
    '''
    Traces execution of the symbol in the currently selected frame.
    trace -h/--help, for full help
    '''
    global options
    if parse_options(command, result):
        return
    
    ####################################################
    ########################测 试########################
    ####################################################
    if test(debugger):
            return
    ####################################################

    ini_log_file(options.mode_type)

    if not check_parser_command():
        return
    

    wait_event = threading.Event()
    wait_event.clear()
    notify_event = threading.Event()
    notify_event.clear()
    
    target: lldb.SBTarget = debugger.GetSelectedTarget()
    broadcaster: lldb.SBBroadcaster = target.GetBroadcaster()
    log_d("Target: {}".format(str(target)))
    process: lldb.SBProcess = target.GetProcess()
    log_d("Process: {}".format(str(process)))
    log_d("Broadcaster: {}".format(str(broadcaster)))
    if options.suspend_threads :
        suspend_threads_escape_select_thread(process,True)

    listener = lldb.SBListener("trace breakpoint listener")
    rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
    my_thread = WTListeningThread(wait_event, notify_event,listener, process)
    my_thread.start()

    thread: lldb.SBThread = process.GetSelectedThread()
    log_d("Thread: {}".format(str(thread)))
    
    frame: lldb.SBFrame = thread.GetSelectedFrame()
    
    module: lldb.SBModule = frame.GetModule()
    if frame.GetFrameID() == 0xFFFFFFFF:
        log_d("Invalid frame, has your process started?")
        return

    insObj = WTInstruction(target,thread,frame,debugger,TRACE_TYPE_Instrument,endAddress=options.end_address)
    ## 初始化 环境 
    insObj.init_env()
    global num_for_print_progress
    insCount = 0
    test_index = 0
    while True:
        log_d('index : {}'.format(test_index))
        # 打印进度
        if options.print_tracing_progress :
            if insCount % num_for_print_progress == 0 and insCount > 0:
                insObj.print_tracing_progress(insCount)
            insCount = insCount + 1

        # 更新当前 instruction / instructionList
        log_d("////////////////////////////////loop begin////////////////////////////////")
        insObj.updata_instruction_instructionList() # 更新所有的 指令 ,更新当前 指令 

        # ins : 设置断点,进行有必要的 单步 调试
        # fun : 设置断点
        ret = insObj.deal_with() # 处理 指令

        # 保存指令
        insObj.updata_last_instruction()

        log_d("=================== Stopped at: ====================")
        log_d("Frame: {}, symbol: {}, pc: {pc:#x}".format(str(frame), str(frame.GetSymbol()), pc=frame.GetPC()))
        # 判断结果
        if ret == CONST_DEAL_WITH_error:
            log_c('err : deal with error.')
            log_d('err : deal with error.')
            insObj.clean_env()
            break

        if ret == CONST_DEAL_WITH_continue:
            continue

        if ret == CONST_DEAL_WITH_break :
            break
        continue_and_wait_for_breakpoint(process,thread,my_thread,wait_event,notify_event)



    if options.suspend_threads :
        suspend_threads_escape_select_thread(process,False)
    my_thread.exit()
    wait_event.set()
    my_thread.join()
    broadcaster.RemoveListener(listener)
    log_d('Listener thread exited completing')
    log_flush()


############################################################################################################################################################
#######################################################################traceblock###########################################################################
############################################################################################################################################################

class WTBlock():
    def __init__(self, target, thread, frame,debugger,endAddress=None):
        self.target:lldb.SBTarget = target
        self.thread:lldb.SBThread = thread
        self.frame:lldb.SBFrame = frame
        self.debugger:lldb.SBDebugger = debugger

        self.current_instruction_list = {}
        self.end_trace_address = []
        self.block_list = {} # 存贮所有的 block

        # 
        # {
        #     addr : {  # 这里是断点地址
        #         'index' : 0 # 这里是断点信息
        #         'breakpoint' : None # 这里是 lldb.SBBreakpoint
        #     }
        # }
        self.breakpoint_list = {} # 断点列表
        
        self.loop_flag = False
        self.append_msg = ''  

        # log
        self.last_block_msg = '' 
        self.last_isnts_msg = ''
        self.last_reg_msg = ''

        ## 
        self.test_test_index = 0

        for item in re.split(';',endAddress):
            self.end_trace_address.append(int(item,16)) # 结束 Trace 地址

    def initEnv(self):
        cur_pc = self.get_current_pc()
        self.block_add_block_to_block_list(cur_pc)
        for item in self.end_trace_address :
            self.block_add_breakpoint(item)  # 给结束地址下断点

    def block_set_loop_flag(self,flag_value):
        self.loop_flag = flag_value

    def block_add_append_msg(self,msg):
        self.append_msg = '{}[{}]'.format(self.append_msg,msg)            
        

    def block_clear_append_msg(self):
        self.append_msg = ''

    def block_delete_breakpoint(self,inst_addr):
        if inst_addr in self.breakpoint_list :
            index_value = self.breakpoint_list[inst_addr]['index']
            delete_breakpoint:lldb.SBBreakpoint = self.breakpoint_list[inst_addr]['breakpoint']
            if index_value > 1 :
                self.breakpoint_list[inst_addr]['index'] = index_value -1
            elif index_value == 1:
                log_d('delete breakpoint at : {}'.format(hex(inst_addr)))
                self.target.BreakpointDelete(delete_breakpoint.GetID())
                self.breakpoint_list[inst_addr]['index'] = 0
                self.breakpoint_list.pop(inst_addr)
            else:
                log_d('err : delete breakpoint with wrong index . < index : {} >'.format(index_value))

    def block_add_breakpoint(self,inst_addr):
        if inst_addr in self.breakpoint_list:
            # index_value = self.breakpoint_list[inst_addr]['index']
            # if index_value > 0 :
            #     print('increase breakpoint index at : {}'.format(hex(inst_addr)))
            #     self.breakpoint_list[inst_addr]['index'] = index_value + 1
            # else:
            #     print('err : add breakpoint with wrong index. < index : {} >'.format(index_value))
            log_d('breakpoint at {} had been exist.'.format(hex(inst_addr)))
        else:
            item = {}
            breakpoint :lldb.SBBreakpoint = self.target.BreakpointCreateByAddress(inst_addr)
            breakpoint.SetThreadID(self.thread.GetThreadID())
            item['index'] = 1
            item['breakpoint'] = breakpoint
            self.breakpoint_list[inst_addr] = item
            log_d('add breakpoint at : {}'.format(hex(inst_addr)))
    def block_add_block_to_block_list(self,block_id):
        if  not (block_id in self.block_list) :
            log_d('>>>>>> add block : {}  >>> value : None.'.format(hex(block_id)))
            self.block_list[block_id] = None

    # 获得当前 pc
    def get_current_pc(self):
        now_frame :lldb.SBFrame = self.thread.GetSelectedFrame()
        if now_frame:
            return now_frame.GetPC()
        return None
    # 
    def block_update_current_ins(self):
        frame : lldb.SBFrame = self.thread.GetSelectedFrame()
        # symbol:lldb.SBSymbol = frame.GetSymbol()
        # # 给 current_instruction_list 赋值
        # # 获得 当前 symbol 下的 instructionlist
        # insts : lldb.SBInstructionList = symbol.GetInstructions(self.target)

        cur_pc = self.get_current_pc()
        
        if not (cur_pc in self.current_instruction_list)  :
            # 清空一哈
            self.current_instruction_list = {}
            # 更新 self.current_instruction_list

            target: lldb.SBTarget = self.debugger.GetSelectedTarget()
            process: lldb.SBProcess = target.GetProcess()
            thread: lldb.SBThread = process.GetSelectedThread()
            frame: lldb.SBFrame = thread.GetSelectedFrame()
            symbol :lldb.SBSymbol = frame.GetSymbol()
            insts :lldb.SBInstructionList = symbol.GetInstructions(target)
            # func : lldb.SBFunction = frame.GetFunction()
            # insts : lldb.SBInstructionList = func.GetInstructions(self.target)     
            for inst in insts :
                instAddr :lldb.SBAddress = inst.GetAddress()
                addr = instAddr.GetLoadAddress(self.target)
                if not (addr in self.current_instruction_list) :
                    self.current_instruction_list[addr] = inst
        
        return cur_pc


    # 判断当前 ins 是否在 trace 的结束列表中
    def block_check_current_ins_in_end_tracing_address_list(self,curIns):
        if curIns in self.end_trace_address :
            return True
        return False
    
    def block_update_block_data(self,block_id,block_dic):
        if block_id in self.block_list:
            block_data = self.block_list[block_id]
            if not block_data :
                self.block_list[block_id] = block_dic
            else :
                log_d('>> block : {} had been update'.format(hex(block_id)))
        else:
            log_d('err : block id dont input to block list.')

    def block_update_current_block(self):        
        # 需要在 bl 以及 jmp 目标地址,和条件jmp的下一条指令处下断点,以及 增加对应的 block 到 blockList 中
        cur_pc = self.get_current_pc()
        # print(self.current_instruction_list)
        inst :lldb.SBInstruction = self.current_instruction_list[cur_pc]

        if (cur_pc in self.block_list) and ( self.block_list[cur_pc]) :  
            self.block_set_loop_flag(True)
            self.block_delete_breakpoint(cur_pc)
            return self.block_list[cur_pc]

        use_inst = inst
        block_ins_list = {}
        need_break = False
        log_d('update block : {} insts :'.format(hex(cur_pc)))
        while True :
            mnemonic: str = use_inst.GetMnemonic(self.target)
            inst_addr = use_inst.GetAddress().GetLoadAddress(self.target)
            next_addr = inst_addr + use_inst.GetByteSize()
            operands = use_inst.GetOperands(self.target)

            flag = False
            for item in CONST_DEVICE_info_list[DEVICE][CONST_INS_call] :
                if mnemonic.startswith(item) :
                    flag = True
                    break
            
            if flag :
                self.block_add_breakpoint(inst_addr)
                block_ins_list[inst_addr] = use_inst # 代码加入到 block_ins_list 
                if next_addr in self.current_instruction_list :
                    use_inst = self.current_instruction_list[next_addr] # 更新 use_inst
                else :
                    break
                continue

            flag = False
            for item in CONST_DEVICE_info_list[DEVICE][CONST_INS_jmp]:
                if item == mnemonic :
                    flag = True
                    need_break = True
                    break
            
            if flag :  
                self.block_add_block_to_block_list(int(operands,16))    # 添加block 到 block_list 中 
                self.block_add_breakpoint(int(operands,16))# 在 int(operands,16) 处下断点

            if not need_break :        
                flag = False
                for item in CONST_DEVICE_info_list[DEVICE][CONST_INS_condition_jmp] :
                    if  mnemonic.startswith(item):
                        flag = True
                        need_break = True
                        break
                if flag :
                    if int(operands,16) > inst_addr :    
                        self.block_add_block_to_block_list(int(operands,16)) 
                        self.block_add_breakpoint(int(operands,16)) # 在 operands 下断点

                    self.block_add_block_to_block_list(next_addr)
                    self.block_add_breakpoint(next_addr) # 在 next_addr 下断点

            
            block_ins_list[inst_addr] = use_inst # 代码加入到 block_ins_list 
            if need_break :
                break

            if next_addr in self.current_instruction_list :
                use_inst = self.current_instruction_list[next_addr] # 更新 use_inst
            else :
                break
        # self.block_list[cur_pc] = block_ins_list
        # print('block : {} \n{}:'.format(hex(cur_pc),self.block_list[cur_pc]))
        return block_ins_list


    def block_at_bl(self,curIns):
        ins:lldb.SBInstruction = self.current_instruction_list[curIns]
        mnem:str = ins.GetMnemonic(self.target)
        for item in CONST_DEVICE_info_list[DEVICE][CONST_INS_call]:
            if mnem.startswith(item) :
                return True
        return False

    def block_at_header(self,curIns):
        if curIns in self.block_list :
            return True
        return False

    ##############################
    def block_step_into(self):
        self.thread.StepInstruction(False)

    def block_get_data_about_function_and_symbol(self,curIns):
        target: lldb.SBTarget = self.debugger.GetSelectedTarget()
        process: lldb.SBProcess = target.GetProcess()
        thread: lldb.SBThread = process.GetSelectedThread()
        frame: lldb.SBFrame = thread.GetSelectedFrame()
        symbol :lldb.SBSymbol = frame.GetSymbol()
        func : lldb.SBFunction = frame.GetFunction()
        # insts:lldb.SBInstructionList = func.GetInstructions(target)
        # inst:lldb.SBInstruction = None
        # block_delete_breakpoint
        self.block_delete_breakpoint(curIns)

        if func.IsValid():
            return True,symbol.GetName()

        return False,symbol.GetName()


    def block_get_reg_msg(self):
        reg_msg = ''
        target: lldb.SBTarget = self.debugger.GetSelectedTarget()
        process: lldb.SBProcess = target.GetProcess()
        thread: lldb.SBThread = process.GetSelectedThread()
        frame: lldb.SBFrame = thread.GetSelectedFrame()

        registerSet :lldb.SBValueList = frame.GetRegisters()
        regs:lldb.SBValue = registerSet.GetValueAtIndex(0)
        for reg in regs :     
            if reg_msg == "" :
                reg_msg = '{}:{}'.format(reg.name,reg.value)
            else:
                reg_msg = '{}|{}:{}'.format(reg_msg,reg.name,reg.value)

            if reg.name == 'pc' :
                break

        return reg_msg

    def block_get_current_insts_msg(self,block_id):
        global ASLR
        target: lldb.SBTarget = self.debugger.GetSelectedTarget()
        isnts_msg = ''
        if  not self.loop_flag :
            # isnts_msg = '0x12345 mov x0,1'
            if block_id in self.block_list:
                cur_block = self.block_list[block_id]
                inst:lldb.SBInstruction = None
                if cur_block :
                    for key,inst in cur_block.items():
                        inst_msg = '{: <5} {}'.format(inst.GetMnemonic(target),inst.GetOperands(target))
                        if isnts_msg == "" :
                            isnts_msg = '{: <10}  {}'.format(hex(key - ASLR),inst_msg)
                        else:
                            isnts_msg = '{}\n\t{: <10}  {}'.format(isnts_msg,hex(key - ASLR),inst_msg)

        return isnts_msg

    ################################
    # log 输出 格式
    # block_id :
	# {
	#     addr : inst
	# 	...
	# }<函数名|函数名|..>[x0:value|x1:value|....]
    # block_id :
	#     {}<函数名|函数名|..>[x0:value|x1:value|....]
    #
    # out_msg = "%s\n{\n\t%s\n}<%s>[%s]" % ('block id : 0x1233333','0x12345 mov x0,1','malloc|strlen','x0:0x1234|x1:0x222222')
    def block_log_msg(self,block_id):
        global ASLR
        self.test_test_index = self.test_test_index + 1
        
        block_msg = "{} =>> block id : {}".format(self.test_test_index,hex(block_id-ASLR))
        isnts_msg = self.block_get_current_insts_msg(block_id)   
        reg_msg = self.block_get_reg_msg()

        if not (self.last_block_msg == '' and self.last_isnts_msg == '' and self.last_reg_msg == '') :
            out_msg = "%s\n{\n\t%s\n}<%s>[%s]" % (self.last_block_msg,self.last_isnts_msg,self.append_msg,self.last_reg_msg)
            log_t(out_msg)

        self.last_block_msg = block_msg
        self.last_isnts_msg = isnts_msg
        self.last_reg_msg = reg_msg

        # 清空 append_msg
        self.append_msg = ''

    def block_log_end_msg(self):
        if not (self.last_block_msg == '' and self.last_isnts_msg == '' and self.last_reg_msg == '') :
            out_msg = "%s\n{\n\t%s\n}<%s>[%s]" % (self.last_block_msg,self.last_isnts_msg,self.append_msg,self.last_reg_msg)
            log_t(out_msg)

        self.last_block_msg = ''
        self.last_isnts_msg = ''
        self.last_reg_msg = ''
        
        self.append_msg = ''
        

    def block_get_symbol_name(self):
        target: lldb.SBTarget = self.debugger.GetSelectedTarget()
        process: lldb.SBProcess = target.GetProcess()
        thread: lldb.SBThread = process.GetSelectedThread()
        frame: lldb.SBFrame = thread.GetSelectedFrame()
        symbol :lldb.SBSymbol = frame.GetSymbol()
        return symbol.GetName()


    def block_print_tracing_progress(self,count):
        # 当前trace的总行数 内存地址:文件地址: <函数名>
        global ASLR
        file_addr = 0
        cur_pc = self.get_current_pc()
        if  cur_pc == 0 :
            log_c('{: <10}  err .'.format(count))
        else:
            file_addr = cur_pc - ASLR
            if cur_pc in self.current_instruction_list:   
                out_str = '{: <10}  {} : {} <{}>'.format(count,hex(cur_pc),hex(file_addr),self.block_get_symbol_name())
                log_c(out_str)
            else:
                out_str = '{: <10} {}'.format(count,hex(cur_pc))
                log_c(out_str)

    def block_get_block_id(self,block):
        retaddr = 0
        for addr in block.keys():
            if retaddr == 0 :
                retaddr = addr
            else:
                if retaddr > addr :
                    retaddr = addr
        
        return retaddr


    def block_print(self):
        print('---> block_list <---')
        for item in self.block_list:
            print(hex(item))

        print('---> breakpoint_list <---')
        for item in self.breakpoint_list :
            print(hex(item))

        print('--------------------------')




def block_parser_options(command, result):
    global options
    command_tokens = shlex.split(command)
    parser = TraceOptionParser(result)
    parser.add_option("-e","--end-address",action="store",metavar="END_ADDRESS",dest="end_address",help="End addresses of trace,using to stop trace thread.More address,use ';' to split.")
    parser.add_option("-l","--log-type",action="store",metavar="<trace/debug>",dest="log_type",default='trace',help="Set log type for this tracing. With trace type redirect trace output file. With debug type redirect trace and debug output files.Default is trace type.")
    parser.add_option("-p","--print-tracing-progress",action="store_true",dest="print_tracing_progress",default=True,help="Print tracing progress in console.Default is True")
    parser.add_option("-s","--suspend-threads-except-current-thread",action="store_true",dest="suspend_threads",default=True,help="Suspend threads except current thread,to clean env.Default is True")
    
    (options, _) = parser.parse_args(command_tokens)

    return parser.exited


def block_ini_log_file():
    import time
    global log_default_path,t_log_file_name,d_log_file_name
    timeName = int(time.time())

    if log_default_path.endswith('/'):
        t_log_file_name = "{}{}{}".format(log_default_path,timeName,'blocktrace.log')
        d_log_file_name = "{}{}{}".format(log_default_path,timeName,'blockdebug.log')
        log_c('trace log file : {}'.format(t_log_file_name))
        log_c('debug log file : {}'.format(d_log_file_name))
    else:
        t_log_file_name = "{}/{}{}".format(log_default_path,timeName,'blocktrace.log')
        d_log_file_name = "{}/{}{}".format(log_default_path,timeName,'blockdebug.log')
        log_c('trace log file : {}'.format(t_log_file_name))
        log_c('debug log file : {}'.format(d_log_file_name))
 


def block_check_parser_command():
    global options
    global t_log_file,t_log_file_name,d_log_file,d_log_file_name

    if options.end_address is None :
        print('err : plz input an address where you want to end tracing.')
        return False

    log_type_arr = ['trace','debug']
    if not options.log_type in log_type_arr :
        print('err : plz input -l --log-type value, use "trace" or "debug".')
        return False

    if options.log_type == 'trace':
        print(type(t_log_file_name))
        print(t_log_file_name)
        t_log_file = open(t_log_file_name,'w')

    if options.log_type == 'debug':
        t_log_file = open(t_log_file_name,'w')
        d_log_file = open(d_log_file_name,'w')

    return True


def test_block(debugger:lldb.SBDebugger):
    
    return False

    target: lldb.SBTarget = debugger.GetSelectedTarget()
    process: lldb.SBProcess = target.GetProcess()
    thread: lldb.SBThread = process.GetSelectedThread()
    frame: lldb.SBFrame = thread.GetSelectedFrame()
    symbol :lldb.SBSymbol = frame.GetSymbol()
    func : lldb.SBFunction = frame.GetFunction()

    # out_msg = "%s\n{\n\t%s\n}<%s>[%s]" % ('block id : 0x1233333','0x12345 mov x0,1','malloc|strlen','x0:0x1234|x1:0x222222')

    # print(out_msg)
    # registerSet :lldb.SBValueList = frame.GetRegisters()
    # regs:lldb.SBValue = registerSet.GetValueAtIndex(0)
    # print('num is : {}'.format(regs.GetNumChildren()))
    # for reg in regs :     
    #     print('{} : {}'.format(reg.name,reg.value))
    #     if reg.name == 'pc' :
    #         break
    # print(symbol.GetInstructions(target))

    # # symbol 可执行文件里有,链接库里有
    # # func 可执行文件里有,但是 链接库里 没有
    # if func.IsValid() :
    #     # insts:lldb.SBInstructionList = func.GetInstructions(target)
    #     # inst:lldb.SBInstruction = None
    #     # print('isnts : ')
    #     # print(insts)
    #     print('func : {}'.format(func))
    #     print('func name : {}'.format(func.GetName()))  
    # # print('symbol : {}'.format(symbol))
    # # print('symbol DisplayName : {}'.format(symbol.GetDisplayName()))
    # # print('symbol MangledName : {}'.format(symbol.GetMangledName()))
    # print('symbol name : {}'.format(symbol.GetName()))


    # for inst in insts :  
    #     print('|{}|-----|{}|'.format(inst.GetMnemonic(target),inst.GetOperands(target)))
    #     pass
    cur_block_ins_list = None # 直接更新
    blockObj = WTBlock(target,thread,frame,debugger)
    blockObj.initEnv()
    cur_ins = blockObj.block_update_current_ins()
    print('cur ins : {}'.format(hex(cur_ins)))
    if not cur_block_ins_list :
        cur_block_ins_list = blockObj.block_update_current_block()

    # if not (cur_ins in cur_block_ins_list) :
    #     cur_block_ins_list = blockObj.block_update_current_block()

    print('--> block_ins_list <---')
    item : lldb.SBInstruction = None  
    for _,item in cur_block_ins_list.items() :
        print('{}      {}  {}'.format(hex(item.GetAddress().GetLoadAddress(target)),item.GetMnemonic(target),item.GetOperands(target)))


    blockObj.block_print()

def trace_block(debugger: lldb.SBDebugger, command: str, result: lldb.SBCommandReturnObject, internal_dict):
    global options
    if block_parser_options(command, result):
        return
    
    ####################################################
    ########################测 试########################
    ####################################################
    if test_block(debugger):
            return
    ####################################################

    block_ini_log_file()


    if not block_check_parser_command():
        return
    
    wait_event = threading.Event()
    wait_event.clear()
    notify_event = threading.Event()
    notify_event.clear()
    
    target: lldb.SBTarget = debugger.GetSelectedTarget()
    broadcaster: lldb.SBBroadcaster = target.GetBroadcaster()
    print("Target: {}".format(str(target)))
    process: lldb.SBProcess = target.GetProcess()
    print("Process: {}".format(str(process)))
    print("Broadcaster: {}".format(str(broadcaster)))
    if options.suspend_threads :
        suspend_threads_escape_select_thread(process,True)

    listener = lldb.SBListener("trace breakpoint listener")
    rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
    my_thread = WTListeningThread(wait_event, notify_event,listener, process)
    my_thread.start()

    thread: lldb.SBThread = process.GetSelectedThread()
    print("Thread: {}".format(str(thread)))
    
    frame: lldb.SBFrame = thread.GetSelectedFrame()
    
    module: lldb.SBModule = frame.GetModule()
    if frame.GetFrameID() == 0xFFFFFFFF:
        print("Invalid frame, has your process started?")
        return
    
    blockObj = WTBlock(target,thread,frame,debugger,endAddress=options.end_address)
    blockObj.initEnv()
    
    cur_block = None # 直接更新
    blockCount = 0
    while True :
        # 打印进度
        if options.print_tracing_progress :
            if blockCount % num_for_print_progress == 0 and blockCount > 0:
                blockObj.block_print_tracing_progress(blockCount)
            blockCount = blockCount + 1
        log_d("=================== Stopped at: ====================")
        log_d("Frame: {}, symbol: {}, pc: {pc:#x}".format(str(frame), str(frame.GetSymbol()), pc=frame.GetPC()))
        cur_ins = blockObj.block_update_current_ins()

        if blockObj.block_check_current_ins_in_end_tracing_address_list(cur_ins):
            print('end tracing....... at : {}'.format(hex(cur_ins)))
            blockObj.block_log_end_msg()
            log_d('end tracing....... at : {}'.format(hex(cur_ins)))
            # blockObj.block_print()
            break
        
        if (not cur_block ) or not (cur_ins in cur_block): 
            cur_block = blockObj.block_update_current_block() # 需要在 bl 以及 jmp 目标地址,和条件jmp的下一条指令处下断点,以及 增加对应的 block 到 blockList 中
            blockObj.block_update_block_data(cur_ins,cur_block)


        at_bl_flag = blockObj.block_at_bl(cur_ins)
        at_header_flag = blockObj.block_at_header(cur_ins)

        if at_bl_flag and at_header_flag :
            # 当前指令 是 bl 而且是 block 头
            # 输出 信息
            blockObj.block_log_msg(cur_ins)
            blockObj.block_set_loop_flag(False)
            # 单步进入,然后获得 symble name 和 function name
            blockObj.block_step_into()
            _,symbol_name = blockObj.block_get_data_about_function_and_symbol(cur_ins) 
            blockObj.block_add_append_msg('') # blockObj.block_add_append_msg(msg) # 把信息 加入 到 

        elif at_bl_flag and (not at_header_flag):
            # 当前指令 仅仅是 bl
            # 单步进入,然后获得 symble name 和 function name
            blockObj.block_step_into()
            _,symbol_name = blockObj.block_get_data_about_function_and_symbol(cur_ins)
            blockObj.block_add_append_msg(symbol_name) # blockObj.block_add_append_msg(msg) # 把信息 加入 到 
            
        elif at_header_flag and (not at_bl_flag):
            # 当前指令 仅仅是 block 头,在进来的时候,已经搞定
            # 输出 信息
            blockObj.block_log_msg(cur_ins)
            blockObj.block_set_loop_flag(False)
        else:
            log_d('err : ins out of control.')
            print('err : ins out of control.')
            break
        
        # 10分钟 刷新一次缓存,把缓存 写入到 block list 文件中  xxxxx_block_list.txt
        # 清空 blockObj.block_list

        continue_and_wait_for_breakpoint(process,thread,my_thread,wait_event,notify_event)      

    if options.suspend_threads :
        suspend_threads_escape_select_thread(process,False)
    my_thread.exit()
    wait_event.set()
    my_thread.join()
    broadcaster.RemoveListener(listener)
    print('Listener thread exited completing')
    log_flush()



def init_ASLR(debugger:lldb.SBDebugger):   
    global ASLR
    interpreter:lldb.SBCommandInterpreter = debugger.GetCommandInterpreter()
    returnObject = lldb.SBCommandReturnObject()
    interpreter.HandleCommand('image list -o', returnObject)
    output = returnObject.GetOutput()
    match = re.match(r'.+(0x[0-9a-fA-F]+)', output)
    if match:
        ASLRHexStr:str = match.group(1)
        ASLR = int(ASLRHexStr,16)
        print('ALSR : {}'.format(ASLRHexStr))
        return ASLRHexStr
    else:
        ASLR = ''
        print('err : ALSR is None')
        return None

def setDefaultPath(debugger: lldb.SBDebugger, command: str, result: lldb.SBCommandReturnObject, internal_dict):
    global log_default_path
    log_default_path = command
    # 还需要判断这个 路径存在否
    print(command)
    
def defaultPath(debugger: lldb.SBDebugger, command: str, result: lldb.SBCommandReturnObject, internal_dict):
    global log_default_path
    print(log_default_path)

def __lldb_init_module(debugger:lldb.SBDebugger, internal_dict):
    global log_default_path
    init_ASLR(debugger)
    log_default_path = os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + os.path.sep + ".")
    debugger.HandleCommand('command script add -f lldbTrace.trace trace')
    debugger.HandleCommand('command script add -f lldbTrace.setDefaultPath setlogpath')
    debugger.HandleCommand('command script add -f lldbTrace.defaultPath logpath')
    print('WT::The "trace" python command has been installed and is ready for use.')



    print('WT::Default path =>>>> {}'.format(log_default_path))
    print('    use : logpath command to look up logfile default path.')
    print('    use : setlogpath <PATH> command to reset logfile default path.')

    debugger.HandleCommand('command script add -f lldbTrace.trace_block trace_b')
    print('WT::The "trace_b" python command has been installed and is ready for use.')




================================================
FILE: main.mm
================================================
//
//  main.m
//  checkDemo
//
//  Created by wt on 2021/4/21.
//

#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCrypto.h>
#import <CommonCrypto/CommonCryptor.h>
#import <CoreLocation/CoreLocation.h>
#include <sys/stat.h>
#import <objc/runtime.h>
#import <Foundation/NSObject.h>
#import "WTAes.hpp"

int test(int a,int b,int c){
    int  tmp = 2 * c;
    return  a + b + tmp;
}

int test_fun(){
    NSString * a = @"{\"b1\":\"\",\"b2\":1,\"b3\":\"AAAAAAAAAAAAAMnu601KCPF0Mj3cObiE77iT8YWCbhK1vSgWHJ3uNlYTdmODBjMGMyZGMn-JGVHeeVP_WmIdd2TFi6Si0TpSJ8_Q\",\"b4\":\"\",\"b5\":1,\"b6\":{\"c1\":\"com.meituan.imeituan\",\"c2\":\"56226DD0E7DEB85C417DD793041E5CC9\",\"c3\":\"11.7.202\",\"c4\":117202,\"c5\":-2}}";
    NSLog(@"%ld",[a length]);
    unsigned char arr[] = {
        0xc2,0x55,0xe9,0x74,0xb0,0xd6,0x39,0xb2,
        0xf3,0x0e,0x85,0x98,0x6b,0xd0,0xb8,0xc9,
        0x35,0x50,0x56,0xe0,0xef,0xe7,0x1d,0x2c,
        0x5a,0x0e,0x76,0x76,0xd8,0x6f,0xda,0xee,
        0xf5,0xfe,0x78,0x0f,0x08,0x3d,0x47,0xe2,
        0x51,0xf3,0xc1,0x75,0xf5,0xf1,0x40,0x10,
        0x74,0xd6,0x62,0x5e,0xe7,0x51,0xce,0xd7,
        0x8b,0x4d,0x66,0x95,0x34,0x33,0xda,0x3b,
        0x0f,0xe7,0x55,0x27,0x5b,0xe8,0x11,0x2c,
        0xcd,0xc5,0xfa,0x76,0x97,0x8c,0x4c,0xcc,
        0x33,0x1e,0xe5,0xf2,0x5e,0xba,0xca,0xae,
        0x6c,0x32,0x21,0x18,0x1e,0x5e,0x32,0x69,
        0x00,0x3c,0xfa,0x14,0xea,0x62,0xed,0x81,
        0x59,0xad,0x70,0x7b,0x56,0xa7,0x1d,0x40,
        0x44,0x23,0x69,0x3e,0xda,0x14,0xb8,0x42,
        0x67,0x9f,0xc7,0x07,0xe4,0x92,0xd3,0xff,
        0x5b,0x6d,0x0d,0xd6,0x3c,0x0d,0xcb,0x33,
        0x95,0x4f,0x8c,0xbe,0xd1,0xbf,0x87,0x8e,
        0x24,0x03,0x8b,0xc4,0xfa,0xfd,0x25,0x7d,
        0xe9,0x40,0xda,0xe8,0xc0,0xf4,0xd5,0x12,
        0x6f,0xf0,0x3d,0x3e,0xca,0x96,0x63,0x72,
        0x9d,0x2c,0x72,0xbb,0xef,0x73,0xac,0xaa,
        0xfd,0xd1,0x4c,0x2d,0x38,0x9c,0xd2,0x19,
        0x54,0x43,0x1b,0xd5,0x9d,0xa5,0x15,0x7d,
        0xf2,0x27,0x7a,0x1d,0xee,0x91,0xfc,0xf2,
        0xca,0x9b,0xee,0x14,0x5c,0xe5,0x6d,0x5c,
        0x31,0xe6,0x47,0x45,0xf2,0x68,0xb8,0x32,
        0x85,0x08,0x68,0x4e,0x57,0x80,0x82,0xc9,
        0x8f,0xe2,0x7c,0xff,0x79,0xd6,0xc7,0xba,
        0x68,0xf7,0x9a,0x13,0xbf,0x99,0x01,0xe8,
        0x98,0x7a,0xd6,0xab,0xb8,0xae,0x0c,0x3f,
        0xe7,0xb0};
    
    NSData * data = [[NSData alloc] initWithBytes:arr length:0xfd];
    NSData *base64Data = [data base64EncodedDataWithOptions:0];
    
    NSString *base64 = [[NSString alloc] initWithData:base64Data encoding:NSUTF8StringEncoding];
    NSLog(@"%@",base64);
    
    int value = test(2, 3, 5);
    NSString * str = [NSString stringWithFormat:@"%d",value];
    [str stringByAppendingString:@"abc"];
    
//    @"wlXpdLDWObLzDoWYa9C4yTVQVuDv5x0sWg52dthv2u71/ngPCD1H4lHzwXX18UAQdNZiXudRzteLTWaVNDPaOw/nVSdb6BEszcX6dpeMTMwzHuXyXrrKrmwyIRgeXjJpADz6FOpi7YFZrXB7VqcdQEQjaT7aFLhCZ5/HB+SS0/9bbQ3WPA3LM5VPjL7Rv4eOJAOLxPr9JX3pQNrowPTVEm/wPT7KlmNynSxyu+9zrKr90UwtOJzSGVRDG9WdpRV98id6He6R/PLKm+4UXOVtXDHmR0XyaLgyhQhoTleAgsmP4nz/edbHumj3mhO/mQHomHrWq7iuDD/nsA==";
//    @"wlXpdLDWObLzDoWYa9C4yTVQVuDv5x0sWg52dthv2u71/ngPCD1H4lHzwXX18UAQdNZiXudRzteLTWaVNDPaOw/nVSdb6BEszcX6dpeMTMwzHuXyXrrKrmwyIRgeXjJpADz6FOpi7YFZrXB7VqcdQEQjaT7aFLhCZ5/HB+SS0/9bbQ3WPA3LM5VPjL7Rv4eOJAOLxPr9JX3pQNrowPTVEm/wPT7KlmNynSxyu+9zrKr90UwtOJzSGVRDG9WdpRV98id6He6R/PLKm+4UXOVtXDHmR0XyaLgyhQhoTleAgsmP4nz/edbHumj3mhO/mQHomHrWq7iuDD/nsCgAMA==";
    
//    wlXpdLDWObLzDoWYa9C4yTVQVuDv5x0sWg52dthv2u71/ngPCD1H4lHzwXX18UAQdNZiXudRzteLTWaVNDPaOw/nVSdb6BEszcX6dpeMTMwzHuXyXrrKrmwyIRgeXjJpADz6FOpi7YFZrXB7VqcdQEQjaT7aFLhCZ5/HB+SS0/9bbQ3WPA3LM5VPjL7Rv4eOJAOLxPr9JX3pQNrowPTVEm/wPT7KlmNynSxyu+9zrKr90UwtOJzSGVRDG9WdpRV98id6He6R/PLKm+4UXOVtXDHmR0XyaLgyhQhoTleAgsmP4nz/edbHumj3mhO/mQHomHrWq7iuDD/nsA==
    
//    struct stat a;
//    const char * path = '/Users/wt/pro';
//    stat(path, &a);
//    int abc = sizeof(a);
//
//    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
//    NSLog(@"%f",[[NSDate date]timeIntervalSince1970]);
//
//
//    [NSKeyedUnarchiver unarchiveObjectWithData:nil];
//
//    CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding|kCCOptionECBMode,)
    return  0;
}

void test_aes(){
    AES aes;
    byte enc[16];
    byte buf[16]="this is a test";
    byte ret[16];
    aes.encrypt(buf,enc);
    aes.decrypt(enc,ret);
    printf("%s",ret);
}


void test_folly()
{
    
}

void b(void)
{
    usleep(200 * 1000);
}

void a(void)
{
    for(int i=0; i<3; i++)
    {
        b();
    }
    NSString * sour = @"abc";
    NSString * str = [[NSString alloc] initWithString:sour];
    printf("Cycle\n");
    NSLog(@"%@",str);
}

void c(int i);
void d(int i)
{
    c(i-1);
}

void c(int i)
{
    if (i > 0) {
        d(i);
    }
}

void breakpoint(void)
{
    a();
    c(1);
}

int test()
{
    while(true) {
        breakpoint();
    }
    return 0;
}


int main(int argc, const char * argv[]) {
    sleep(1);
    test();
//    test_fun();
//    test_aes();
    return 0;
}


================================================
FILE: tools/verifyAlgorithm/test.py
================================================
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
#@File    :   test.py
#@Time    :   2021/07/29 15:15:38
#@Author  :   wt 

from wtpytracer import *

####################
## command :
##      python3 test.py ~/Desktop/1627533881instrace.log

## 定义需要检测的 变量 : flag + '_' + 地址 + '_' + 寄存器
Check_0x10000393c_w8 = 'Check_0x10000393c_w8'


### 翻译的测试代码
def f(x):
    ret = 0
    for index in range(x):
        ret = ret + index
        check_value(ret,Check_0x10000393c_w8) # check ret 和 0x10000393c 的 w8 的寄存器值
    return ret + x


if __name__ == '__main__':
    import sys
    args_list = sys.argv
    if len(args_list) != 2 :
        exit()
    file_name = args_list[1]

    try:
        set_trace_data(Check_0x10000393c_w8)
        parser_trace_log_file(file_name)
        enable(CheckFunctionTracer())
        f(5)
    finally:
        disable()


================================================
FILE: tools/verifyAlgorithm/wtpytracer.py
================================================
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
#@File    :   wtpytracer.py
#@Time    :   2021/07/27 18:17:18
#@Author  :   wt 

import re
import sys
import inspect
from collections import OrderedDict

class TracebackFancy:
    
    def __init__(self, traceback):
        self.t = traceback

    def getFrame(self):
        return FrameFancy(self.t.tb_frame)

    def getLineNumber(self):
        return self.t.tb_lineno if self.t is not None else None

    def getNext(self):
        return TracebackFancy(self.t.tb_next)

    def __str__(self):
        if self.t is None:
            return ""
        str_self = "%s @ %s" % (
            self.getFrame().getName(), self.getLineNumber())
        return str_self + "\n" + self.getNext().__str__()


class ExceptionFancy:

    def __init__(self, frame):
        self.etraceback = frame.f_exc_traceback
        self.etype = frame.exc_type
        self.evalue = frame.f_exc_value

    def __init__(self, tb, ty, va):
        self.etraceback = tb
        self.etype = ty
        self.evalue = va

    def getTraceback(self):
        return TracebackFancy(self.etraceback)

    def __nonzero__(self):
        return self.etraceback is not None or self.etype is not None or self.evalue is not None

    def getType(self):
        return str(self.etype)

    def getValue(self):
        return self.evalue


class CodeFancy:

    def __init__(self, code):
        self.c = code

    def getArgCount(self):
        return self.c.co_argcount if self.c is not None else 0

    def getFilename(self):
        return self.c.co_filename if self.c is not None else ""

    def getVariables(self):
        return self.c.co_varnames if self.c is not None else []

    def getName(self):
        return self.c.co_name if self.c is not None else ""

    def getFileName(self):
        return self.c.co_filename if self.c is not None else ""


class ArgsFancy:

    def __init__(self, frame, arginfo):
        self.f = frame
        self.a = arginfo

    def __str__(self):
        args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs()
        ret = ""
        count = 0
        size = len(args)
        for arg in args:
            ret = ret + ("%s = %s" % (arg, args[arg]))
            count = count + 1
            if count < size:
                ret = ret + ", "
        if varargs:
            if size > 0:
                ret = ret + " "
            ret = ret + "varargs are " + str(varargs)
        if kwargs:
            if size > 0:
                ret = ret + " "
            ret = ret + "kwargs are " + str(kwargs)
        return ret

    def getNumArgs(wantVarargs=False, wantKWArgs=False):
        args, varargs, keywords, values = self.a
        size = len(args)
        if varargs and wantVarargs:
            size = size + len(self.getVarArgs())
        if keywords and wantKWArgs:
            size = size + len(self.getKWArgs())
        return size

    def getArgs(self):
        args, _, _, values = self.a
        argWValues = OrderedDict()
        for arg in args:
            argWValues[arg] = values[arg]
        return argWValues

    def getVarArgs(self):
        _, vargs, _, _ = self.a
        if vargs:
            return self.f.f_locals[vargs]
        return ()

    def getKWArgs(self):
        _, _, kwargs, _ = self.a
        if kwargs:
            return self.f.f_locals[kwargs]
        return {}

class FrameFancy:
    
    def __init__(self, frame):
        self.f = frame

    def getCaller(self):
        return FrameFancy(self.f.f_back)

    def getLineNumber(self):
        return self.f.f_lineno if self.f is not None else 0

    def getCodeInformation(self):
        return CodeFancy(self.f.f_code) if self.f is not None else None

    def getExceptionInfo(self):
        return ExceptionFancy(self.f) if self.f is not None else None

    def getName(self):
        return self.getCodeInformation().getName() if self.f is not None else ""

    def getFileName(self):
        return self.getCodeInformation().getFileName() if self.f is not None else ""

    def getLocals(self):
        return self.f.f_locals if self.f is not None else {}

    def getArgumentInfo(self):
        return ArgsFancy(
            self.f, inspect.getargvalues(
                self.f)) if self.f is not None else None

class TracerClass:
    
    def callEvent(self, frame):
        pass

    def lineEvent(self, frame):
        pass

    def returnEvent(self, frame, retval):
        pass

    def exceptionEvent(self, frame, exception, value, traceback):
        pass

    def cCallEvent(self, frame, cfunct):
        pass

    def cReturnEvent(self, frame, cfunct):
        pass

    def cExceptionEvent(self, frame, cfunct):
        pass

tracer_impl = TracerClass()
data_dic = {}
old_trace_func = None

def parser_flag(flag):
    import re
    aa = re.split(r'_',flag)
    if len(aa) != 3 :
        return None,None
    return aa[1],aa[2]

class CheckFunctionTracer():
    def callEvent(self, frame):
        if 'check_value' == frame.getName():
            flag = frame.getArgumentInfo().getArgs()['check_flag']
            value = frame.getArgumentInfo().getArgs()['value']
            addr,register = parser_flag(flag)
            if addr in data_dic and register in data_dic[addr]:
                run_index = data_dic[addr][register]['run_index']
                data_len = len(data_dic[addr][register]['data'])
                if run_index >= data_len:
                    print('*** err : at address : {} . run_index : {} out of rang'.format(addr,run_index))
                    return
                if value == data_dic[addr][register]['data']['{}'.format(run_index + 1)] :
                    print('check : {} at {} times,match.'.format(addr,run_index + 1))
                    data_dic[addr][register]['run_index'] = run_index + 1

            # print("->>LoggingTracer : call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo()))



# @ check_flag 为 携带了地址,和寄存器名称
# @ value 为当前需要 check 的值
# 在 sys.settracer设置的回调中,只接管此函数
def check_value(value,check_flag):
    pass


def set_trace_data(check_flag):
    global data_dic
    addr,register = parser_flag(check_flag)
    if not addr or not register :
        print('err : check_flag is wrong.')
        return
    
    if addr in data_dic:
        data_dic[addr][register] = {
            'data':{},
            'run_index':0   
        }
    else:
        addr_dic = {
            register:{
                'data':{},
                'run_index':0
            }
        }
        data_dic[addr] = addr_dic


def add_data_in_data_dic(addr,register,value):
    global data_dic
    cur_reg_dic = data_dic[addr][register]
    data_len = len(cur_reg_dic['data'])
    data_dic[addr][register]['data']['{}'.format(data_len + 1)] = value

def parser_trace_log_file(fileName):
    global data_dic
    file = open(fileName)
    while True:
        lines = file.readlines(100000)
        if not lines:
            break
        for line in lines:
            matchObj = re.match(r'\s*(\S+)\s+',line,re.M|re.I)
            if matchObj:
                addr = str(matchObj.group()).replace(' ','')
                if addr in data_dic:
                    reg = data_dic[addr]
                    for register in data_dic[addr].keys():
                        register_out = re.findall(register +r'  : (\S+)',line)
                        if register_out:
                            register_value = int(register_out[0],16)
                            add_data_in_data_dic(addr,register,register_value)
        
    file.close()
    # {'1234':{'1':0,"2":1}}  # flag : {...}  address:{'x0':{data:{},run_index:0},'x1':{data:{},run_index:0}}


def the_tracer_check_data(frame, event, args = None):
    global data_dic
    global tracer_impl

    code = frame.f_code 

    func_name = code.co_name 
  
    line_no = frame.f_lineno 
    if tracer_impl is None:
        print('@@@ tracer_impl : None.')
        return None

    if event == 'call':
        tracer_impl.callEvent(FrameFancy(frame))

    return the_tracer_check_data



def enable(tracer_implementation=None):
    global tracer_impl,old_trace_func
    if tracer_implementation:
        tracer_impl = tracer_implementation  # 传递 工厂实力的对象
    old_trace_func = sys.gettrace()
    sys.settrace(the_tracer_check_data) # 注册回调到系统中


def check_run_ok():
    global data_dic
    for addr,addr_dic in data_dic.items():
        for _,reg_dic in addr_dic.items():
            if reg_dic['run_index'] == len(reg_dic['data']):
                print('->>> at {} check value is perfect.'.format(addr))
            else:
                print('*** err : at {} check {} times.'.format(addr,reg_dic['run_index']))

def disable():
    check_run_ok()
    global old_trace_func
    sys.settrace(old_trace_func)
    
Download .txt
gitextract_o893_d24/

├── .gitignore
├── README.md
├── lldbTrace.py
├── main.mm
└── tools/
    └── verifyAlgorithm/
        ├── checkDemo
        ├── test.py
        └── wtpytracer.py
Download .txt
SYMBOL INDEX (152 symbols across 3 files)

FILE: lldbTrace.py
  function log_d (line 29) | def log_d(msg): # debug log
  function log_t (line 35) | def log_t(msg): # trace log
  function log_c (line 40) | def log_c(msg): # console log
  function log_flush (line 45) | def log_flush():
  function dlog (line 52) | def dlog(msg):
  class WTListeningThread (line 123) | class WTListeningThread(threading.Thread):
    method __init__ (line 124) | def __init__(self, wait_event, notify_event,listener,process):
    method wait_timed_out (line 133) | def wait_timed_out(self):
    method exit (line 136) | def exit(self):
    method run (line 139) | def run(self):
  function get_c_char_star (line 169) | def get_c_char_star(address):
  function handle_command (line 182) | def handle_command(command,debugger:lldb.SBDebugger):
  function continue_and_wait_for_breakpoint (line 194) | def continue_and_wait_for_breakpoint(process, thread, listening_thread, ...
  function suspend_threads_escape_select_thread (line 210) | def suspend_threads_escape_select_thread(process:lldb.SBProcess,flag:bool):
  function match_registers (line 226) | def match_registers(text):
  class WTInstruction (line 242) | class WTInstruction():
    method __init__ (line 243) | def __init__(self, target, thread, frame,debugger,traceType=TRACE_TYPE...
    method increase_print_index (line 274) | def increase_print_index(self):
    method check_in_call_return_instruction_list (line 279) | def check_in_call_return_instruction_list(self):
    method decrease_print_index (line 287) | def decrease_print_index(self):
    method check_str_in_arr (line 291) | def check_str_in_arr(self,cur_str:str,cur_arr):
    method init_env (line 297) | def init_env(self):
    method get_current_pc (line 329) | def get_current_pc(self):
    method checkPCInList_transferCurrentSymbolInstrucionsToList (line 337) | def checkPCInList_transferCurrentSymbolInstrucionsToList(self,address):
    method updata_instruction_instructionList (line 370) | def updata_instruction_instructionList(self):
    method clean_env (line 380) | def clean_env(self):
    method deal_with (line 387) | def deal_with(self):
    method updata_last_instruction (line 390) | def updata_last_instruction(self):
    method get_current_symbol_name (line 393) | def get_current_symbol_name(self):
    method get_next_instruction (line 398) | def get_next_instruction(self):
    method print_tracing_progress (line 408) | def print_tracing_progress(self,count):
    method log_current_instruction (line 420) | def log_current_instruction(self,cur_pc):
    method parser_ins_symbol_name (line 448) | def parser_ins_symbol_name(self,last_symbole_name:str,cur_symbol_name ...
    method add_next_breakpoint (line 489) | def add_next_breakpoint(self):
    method add_call_return_addr (line 505) | def add_call_return_addr(self):
    method sub_call_return_addr (line 514) | def sub_call_return_addr(self):
    method check_need_delete_breakpoint_in_current_call_return_list_and_decrease_index (line 525) | def check_need_delete_breakpoint_in_current_call_return_list_and_decre...
    method delete_current_breakpoint (line 535) | def delete_current_breakpoint(self):
    method check_currentIns_is_endIns (line 559) | def check_currentIns_is_endIns(self):
    method check_ins_call (line 580) | def check_ins_call(self,mnemonic:str,cur_symbol:lldb.SBSymbol):
    method check_ins_jmp (line 615) | def check_ins_jmp(self,mnemonic:str,cur_symbol:lldb.SBSymbol):
    method check_ins_syscall (line 647) | def check_ins_syscall(self,mnemonic:str,cur_symbol:lldb.SBSymbol):
    method check_ins_other (line 665) | def check_ins_other(self,cur_symbol:lldb.SBSymbol):
    method check_out_tracing (line 673) | def check_out_tracing(self):
    method check_end_fun (line 685) | def check_end_fun(self):
    method check_symbol_valid (line 715) | def check_symbol_valid(self):
    method check_in_module (line 725) | def check_in_module(self):
    method deal_with_ins (line 735) | def deal_with_ins(self):
  class WTFunction (line 797) | class WTFunction():
    method __init__ (line 798) | def __init__(self, *args):
    method deal_with_fun (line 800) | def deal_with_fun(self):
  class TraceOptionParser (line 804) | class TraceOptionParser(optparse.OptionParser):
    method __init__ (line 805) | def __init__(self, result):
    method get_prog_name (line 810) | def get_prog_name(self):
    method exit (line 813) | def exit(self, status=0, msg=None):
  function parse_options (line 819) | def parse_options(command, result):
  function check_parser_command (line 834) | def check_parser_command():
  function ini_log_file (line 866) | def ini_log_file(mode_name:str):
  function test (line 898) | def test(debugger:lldb.SBDebugger):
  function trace (line 950) | def trace(debugger: lldb.SBDebugger, command: str, result: lldb.SBComman...
  class WTBlock (line 1058) | class WTBlock():
    method __init__ (line 1059) | def __init__(self, target, thread, frame,debugger,endAddress=None):
    method initEnv (line 1092) | def initEnv(self):
    method block_set_loop_flag (line 1098) | def block_set_loop_flag(self,flag_value):
    method block_add_append_msg (line 1101) | def block_add_append_msg(self,msg):
    method block_clear_append_msg (line 1105) | def block_clear_append_msg(self):
    method block_delete_breakpoint (line 1108) | def block_delete_breakpoint(self,inst_addr):
    method block_add_breakpoint (line 1122) | def block_add_breakpoint(self,inst_addr):
    method block_add_block_to_block_list (line 1139) | def block_add_block_to_block_list(self,block_id):
    method get_current_pc (line 1145) | def get_current_pc(self):
    method block_update_current_ins (line 1151) | def block_update_current_ins(self):
    method block_check_current_ins_in_end_tracing_address_list (line 1183) | def block_check_current_ins_in_end_tracing_address_list(self,curIns):
    method block_update_block_data (line 1188) | def block_update_block_data(self,block_id,block_dic):
    method block_update_current_block (line 1198) | def block_update_current_block(self):
    method block_at_bl (line 1274) | def block_at_bl(self,curIns):
    method block_at_header (line 1282) | def block_at_header(self,curIns):
    method block_step_into (line 1288) | def block_step_into(self):
    method block_get_data_about_function_and_symbol (line 1291) | def block_get_data_about_function_and_symbol(self,curIns):
    method block_get_reg_msg (line 1309) | def block_get_reg_msg(self):
    method block_get_current_insts_msg (line 1329) | def block_get_current_insts_msg(self,block_id):
    method block_log_msg (line 1359) | def block_log_msg(self,block_id):
    method block_log_end_msg (line 1378) | def block_log_end_msg(self):
    method block_get_symbol_name (line 1390) | def block_get_symbol_name(self):
    method block_print_tracing_progress (line 1399) | def block_print_tracing_progress(self,count):
    method block_get_block_id (line 1415) | def block_get_block_id(self,block):
    method block_print (line 1427) | def block_print(self):
  function block_parser_options (line 1441) | def block_parser_options(command, result):
  function block_ini_log_file (line 1455) | def block_ini_log_file():
  function block_check_parser_command (line 1473) | def block_check_parser_command():
  function test_block (line 1498) | def test_block(debugger:lldb.SBDebugger):
  function trace_block (line 1558) | def trace_block(debugger: lldb.SBDebugger, command: str, result: lldb.SB...
  function init_ASLR (line 1678) | def init_ASLR(debugger:lldb.SBDebugger):
  function setDefaultPath (line 1695) | def setDefaultPath(debugger: lldb.SBDebugger, command: str, result: lldb...
  function defaultPath (line 1701) | def defaultPath(debugger: lldb.SBDebugger, command: str, result: lldb.SB...
  function __lldb_init_module (line 1705) | def __lldb_init_module(debugger:lldb.SBDebugger, internal_dict):

FILE: tools/verifyAlgorithm/test.py
  function f (line 18) | def f(x):

FILE: tools/verifyAlgorithm/wtpytracer.py
  class TracebackFancy (line 12) | class TracebackFancy:
    method __init__ (line 14) | def __init__(self, traceback):
    method getFrame (line 17) | def getFrame(self):
    method getLineNumber (line 20) | def getLineNumber(self):
    method getNext (line 23) | def getNext(self):
    method __str__ (line 26) | def __str__(self):
  class ExceptionFancy (line 34) | class ExceptionFancy:
    method __init__ (line 36) | def __init__(self, frame):
    method __init__ (line 41) | def __init__(self, tb, ty, va):
    method getTraceback (line 46) | def getTraceback(self):
    method __nonzero__ (line 49) | def __nonzero__(self):
    method getType (line 52) | def getType(self):
    method getValue (line 55) | def getValue(self):
  class CodeFancy (line 59) | class CodeFancy:
    method __init__ (line 61) | def __init__(self, code):
    method getArgCount (line 64) | def getArgCount(self):
    method getFilename (line 67) | def getFilename(self):
    method getVariables (line 70) | def getVariables(self):
    method getName (line 73) | def getName(self):
    method getFileName (line 76) | def getFileName(self):
  class ArgsFancy (line 80) | class ArgsFancy:
    method __init__ (line 82) | def __init__(self, frame, arginfo):
    method __str__ (line 86) | def __str__(self):
    method getNumArgs (line 106) | def getNumArgs(wantVarargs=False, wantKWArgs=False):
    method getArgs (line 115) | def getArgs(self):
    method getVarArgs (line 122) | def getVarArgs(self):
    method getKWArgs (line 128) | def getKWArgs(self):
  class FrameFancy (line 134) | class FrameFancy:
    method __init__ (line 136) | def __init__(self, frame):
    method getCaller (line 139) | def getCaller(self):
    method getLineNumber (line 142) | def getLineNumber(self):
    method getCodeInformation (line 145) | def getCodeInformation(self):
    method getExceptionInfo (line 148) | def getExceptionInfo(self):
    method getName (line 151) | def getName(self):
    method getFileName (line 154) | def getFileName(self):
    method getLocals (line 157) | def getLocals(self):
    method getArgumentInfo (line 160) | def getArgumentInfo(self):
  class TracerClass (line 165) | class TracerClass:
    method callEvent (line 167) | def callEvent(self, frame):
    method lineEvent (line 170) | def lineEvent(self, frame):
    method returnEvent (line 173) | def returnEvent(self, frame, retval):
    method exceptionEvent (line 176) | def exceptionEvent(self, frame, exception, value, traceback):
    method cCallEvent (line 179) | def cCallEvent(self, frame, cfunct):
    method cReturnEvent (line 182) | def cReturnEvent(self, frame, cfunct):
    method cExceptionEvent (line 185) | def cExceptionEvent(self, frame, cfunct):
  function parser_flag (line 192) | def parser_flag(flag):
  class CheckFunctionTracer (line 199) | class CheckFunctionTracer():
    method callEvent (line 200) | def callEvent(self, frame):
  function check_value (line 222) | def check_value(value,check_flag):
  function set_trace_data (line 226) | def set_trace_data(check_flag):
  function add_data_in_data_dic (line 248) | def add_data_in_data_dic(addr,register,value):
  function parser_trace_log_file (line 254) | def parser_trace_log_file(fileName):
  function the_tracer_check_data (line 277) | def the_tracer_check_data(frame, event, args = None):
  function enable (line 297) | def enable(tracer_implementation=None):
  function check_run_ok (line 305) | def check_run_ok():
  function disable (line 314) | def disable():
Condensed preview — 7 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (91K chars).
[
  {
    "path": ".gitignore",
    "chars": 1799,
    "preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
  },
  {
    "path": "README.md",
    "chars": 589,
    "preview": "# lldbTrace\n\n##### How to use it?\n\n> 1.*Break at an address where you want to begin tracing.*\n>\n> ![](https://github.com"
  },
  {
    "path": "lldbTrace.py",
    "chars": 69455,
    "preview": "#!/usr/bin/python3\n# -*- encoding: utf-8 -*-\n#@File    :   lldb-trace.py\n#@Time    :   2021/06/25 22:16:01\n#@Author  :  "
  },
  {
    "path": "main.mm",
    "chars": 4996,
    "preview": "//\n//  main.m\n//  checkDemo\n//\n//  Created by wt on 2021/4/21.\n//\n\n#import <Foundation/Foundation.h>\n#import <CommonCryp"
  },
  {
    "path": "tools/verifyAlgorithm/test.py",
    "chars": 839,
    "preview": "#!/usr/bin/python3\n# -*- encoding: utf-8 -*-\n#@File    :   test.py\n#@Time    :   2021/07/29 15:15:38\n#@Author  :   wt \n\n"
  },
  {
    "path": "tools/verifyAlgorithm/wtpytracer.py",
    "chars": 8877,
    "preview": "#!/usr/bin/python3\n# -*- encoding: utf-8 -*-\n#@File    :   wtpytracer.py\n#@Time    :   2021/07/27 18:17:18\n#@Author  :  "
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the yangyss/lldb-trace GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 7 files (84.5 KB), approximately 21.7k tokens, and a symbol index with 152 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!