Beispiel #1
0
def get_maple_frame_stack_sp_index(func_header_name):
    """
    for a given func header name, find out its sp value reported in operand_stack
    """

    # get the func.operand_stack length
    try:
        buffer = m_util.mdb_exec_to_str('p func')
    except:
        return None

    if 'No symbol "func" in current context.' in buffer:
        return None

    stack_header_name = buffer.split('header = ')[1].split()[1][1:-2]
    if stack_header_name != func_header_name:
        if m_debug.Debug: m_debug.dbg_print("func_header_name=", func_header_name, "stack_header_name=", stack_header_name)
        return None

    sp_str = buffer.split('sp = ')[1].split()[0][:-1]
    if not sp_str:
        return None

    try:
        sp = int(sp_str)
    except:
        return None

    return sp
Beispiel #2
0
def create_asm_mirbin_label_cache(asm_path, popen_only=False, proc_saved={}):
    """ Create a dictionary for a given asm file
        When it is called the first time with a given asm file, it starts
        a subprocess to handle the asm file and returns None;
        When called subsequently using the same asm file, it will wait for the
        first subprocess to finish and return a dictionary created from its output.
    """
    if m_debug.Debug: m_util.mdb_print("ASM Begin gen:" + asm_path)
    if not asm_path:
        for p in proc_saved.values():
            m_util.proc_communicate(p)
        return None
    #TODO:  This code prints to stdout on lldb which is a mess
    if m_debug.Debug: m_debug.dbg_print("asm_path=", asm_path)
    #if not path.exists(asm_path):
    if asm_path not in proc_saved:
        cmd="bash -c \"paste <(grep -bn _mirbin_info: '" + asm_path \
            + "') <(grep -Fb .cfi_endproc '" + asm_path \
            + "')\" | awk -F: -v a='\"' -v b='\":(' -v c=',' -v d='),' " \
            "'BEGIN { print \"import pickle\\nimport sys\\nd={\" } " \
            "{ print a$3b$1c$2c$4d } END { print \"}\\no=pickle.dumps(d,3)\\n" \
            "sys.stdout.write(o.decode(\\\"latin1\\\"))\" }' | python3"
        proc_saved[asm_path] = m_util.proc_popen(cmd)
    if popen_only: return None
    d = m_util.proc_communicate(proc_saved.pop(asm_path))
    if m_debug.Debug: m_util.mdb_print("ASM End/Load gen:" + str(d))
    return pickle.loads(d)
Beispiel #3
0
def get_demangled_maple_symbol(symbol, to_filename=False):
    """
    for a given Maple symbol, convert it to demangled symbol name
    """

    if not '_7C' in symbol:
        return None
    s = symbol
    s = s.replace('_7C', '')  # use the jni format
    s = s.replace('_3B', ';')
    s = s.replace('_2F', '.')
    s = s.replace('_28', '(')
    s = s.replace('_29', ')')
    s = s.replace('_3C', '<')
    s = s.replace('_3E', '>')
    s = s.replace('_24', '$')

    if to_filename == False:
        return s

    # to here, label becomes something like "Ljava.lang.Class;|getComponentType|()Ljava.lang.Class;"
    s = s.split('|')[0]
    s = s.replace(';', '')
    s = s[1:]
    f = s.replace('.', '/')
    f = f + '.java'
    if m_debug.Debug: m_debug.dbg_print("s=", s, "f=", f)

    return f
Beispiel #4
0
def get_modules_list():
    """
    wrapper of 'target modules list -o -s -g' cmd --  basic form is:
    [ 18] 0x00007fffe8fec000 /.../MAPLE/maple_engine/maple_runtime/lib/x86_64/libcore.so
    """
    buf = m_util.mdb_exec_to_str('target modules list -o -s -g')
    if m_debug.Debug: m_debug.dbg_print("Module List = ", buf)
    return buf
Beispiel #5
0
def get_maple_invoke_bp_stop_addr(buf):
    """
    get Maple breakpoint address and its coresponding information

    params:
      buf: a string output of m_util.gdb_exec_to_str("info b")

    Return:
      None on address and None on breakpoint information if no information found, or
      1, addr: int. breakpoint stop address
      2, info: additional breakpoint information stating breakpoint source code and line

    Return data example:
      addr = 0x00007ffff5b5f061
      info = at /home/test/gitee/maple_engine/maple_engine/src/invoke_method.cpp:151
    """

    #match_pattern = "in maple::maple_invoke_method(maple::method_header_t const*, maple::MFunction const*)"
    #match_pattern = "libmplre.so`maple::maple_invoke_method(maple::method_header_t const*, maple::MFunction const*)"
    match_pattern = "maple::maple_invoke_method"
    buf = buf.split('\n')

    target = lldb.debugger.GetTargetAtIndex(0)
    bp_count = target.GetNumBreakpoints()
    stream = lldb.SBStream()

    #for line in buf:
    for i in range(0, bp_count):
        target.GetBreakpointAtIndex(i).GetDescription(stream)
        if m_debug.Debug: print("selected bp desc=", stream.GetData())
        line = stream.GetData()
        if m_debug.Debug: m_debug.dbg_print("line=", line)
        if match_pattern in line or match_pattern == line:
            #x = line.split(match_pattern)
            #addr = x[0].split()[-1]
            info = target.GetBreakpointAtIndex(i).GetLocationAtIndex(
                0).GetAddress()
            #info.GetDescription(stream)
            #x = "  at " + stream.GetData().split(" at ")[1]
            addr = target.GetBreakpointAtIndex(i).GetLocationAtIndex(
                0).GetLoadAddress()
            #print("x: ", x)
            #print("Addr Info: ", info)
            #print("Addr: ", hex(addr))
            """
            try:
                addr = int(addr, 16)
            except:
                print("Issue Parsing Addr: ", addr, iaddr)
                return None, None

            info = match_pattern + " ".join(x[1:])
            """
            if m_debug.Debug:
                m_debug.dbg_print("addr = ", addr, "info = ", info)
            return addr, info
    return None, None
Beispiel #6
0
def get_maple_symbol_full_syntax(symbol):
    """
    for a given Maple symbol, return its full syntax, also known as its
    symbol description.

    params
      symbol: string.  symbol we can see in lldb stack data.
           e.g. __cinf_Ljava_2Flang_2FString_3B,
                __cinf_ALjava_2Flang_2FString_3B
                __cinf_ZLsun_xxxxxxxxxxxxxxxxxxxx
                __cinf_JLjavax_yyyyyyyyyyyyyyy
                __cinf_FLsun_xxxxxxxxxxxxxxxxx

    return:
      type_size: int. object size
      full syntax in string.
      examples of full syntax:
        array int my_array[]
        boolean my_var
    """

    if m_debug.Debug: m_debug.dbg_print("symbol=", symbol)
    # check a special symbol for Java native array string
    if symbol is '__cinf_Ljava_2Flang_2FString_3B':
        return 'array string', 0

    # if it is class object, not primitive nor array
    if symbol[:8] in maple_symbol_type_dict:
        if symbol[7] == 'L':  # if it is a Maple java object
            full_syntax = maple_symbol_type_dict[symbol[:8]]
        else:
            full_syntax = maple_symbol_type_dict[symbol[:8]] + ' ' + symbol[8:]
        if symbol[7] in java_type_to_size_dict:
            type_size = java_type_to_size_dict[symbol[7]]
        else:
            type_size = 1
        if m_debug.Debug:
            m_debug.dbg_print("full_syntax=", full_syntax, "type_size=",
                              type_size)
        return full_syntax, type_size

    # to check if it is array of class, or array of primitive type.
    array_type_prefix = symbol[3:8]
    if array_type_prefix == 'inf_A':
        dimension = 0
        while array_type_prefix in symbol:
            dimension += 1
            array_type_prefix += 'A'
        array_type_prefix = 'inf_' + 'A' * dimension
        name = symbol.split(array_type_prefix)[1]
        return 'array ' + name + '[]' * dimension, java_type_to_size_dict[
            name[0]]
    else:
        return 'unknown ' + symbol, 0
Beispiel #7
0
def get_modules_lookup(hdaddr):
    """
    wrapper of 'target modules lookup -v -a' cmd --  basic form is:
    target modules lookup -v -a 0x7fffeb98cea8
      Address: libcore.so[0x00000000029a0ea8] (libcore.so.PT_LOAD[0]..text + 21571096)
      Summary: libcore.so`Ljava_2Fio_2FPrintStream_3B_7Cprintln_7C_28Ljava_2Flang_2FString_3B_29V_mirbin_info
       Module: file = "/.../MAPLE/maple_engine/maple_runtime/lib/x86_64/libcore.so", arch = "x86_64"
       Symbol: id = {0x0003f050}, range = [0x00007fffeb98cea8-0x00007fffeb98cf20), name="Ljava_2Fio_2FPrintStream_3B_7Cprintln_7C_28Ljava_2Flang_2FString_3B_29V_mirbin_info"
    """
    buf = m_util.mdb_exec_to_str('target modules lookup -v -a '+hdaddr)
    if m_debug.Debug: m_debug.dbg_print("Module Info = ", buf)
    return buf
Beispiel #8
0
def get_one_frame_stack_dynamic(sp, idx):
    """
    for a given sp and index number in a dynamic caller operand_stack data, return its
    data type and value.

    Note, at runtime, caller.operand_stack is dynamic, sp, idx, types and values are all
    changing during the run time.
    """
    if idx > sp:
        return None, None

    # get the caller.operand_stack length
    length = None
    try:
        buffer = m_util.mdb_exec_to_str('p func->operand_stack.size()')
    except:
        return None, None

    if buffer[0] != '(':
        return None, None
    if ' = ' in buffer:
        try:
            length = int(buffer.split(' = ')[1])
        except:
            return None, None
    else:
        return None, None
    if m_debug.Debug: m_debug.dbg_print("length=", length)


    if length <= sp or length < idx:
        return None, None

    try:
        maple_type = m_util.mdb_exec_to_str('p func->operand_stack[' + str(idx) + '].ptyp')
    except:
        return None, None
    maple_type = maple_type.split(' = ')[1].split('maple::PTY_')[1].rstrip()

    try:
        buffer = m_util.mdb_exec_to_str('p func->operand_stack[' + str(idx) + ']')
    except:
        return None, None

    value = buffer.split('x = ')[1][1:].split('}')[0]
    if maple_type in value:
        v = value.split(maple_type + ' = ')[1].split(',')[0]
    else:
        return None, None

    if m_debug.Debug: m_debug.dbg_print("return maple_type=", maple_type, "v=", v)
    return maple_type, v
Beispiel #9
0
def get_mirheader_name_by_mirheader_addr(addr):
    cmd = 'x ' + addr
    try:
        result = m_util.mdb_exec_to_str(cmd)
    except:
        return None
    result = result.rstrip()
    if m_debug.Debug: m_debug.dbg_print("result=", result, "addr=", addr)

    if addr in result:
        return result.split()[1][1:-2]
    else:
        return None
Beispiel #10
0
def get_initialized_maple_func_addrs():
    """
    get an initialized Maple frame func header address

    returns:
      func header address in string format of xxxxxx:yyyyyy: format where
      xxxxxx means (header - lib_base_addr),
      yyyyyy means (pc - header - header_size)
    """
    #print("Here the mess starts")
    header = get_initialized_maple_func_attr('func.header')
    pc = get_initialized_maple_func_attr('func.pc')

    if m_debug.Debug: m_debug.dbg_print("header=", header, "pc=", pc)
    if not header or not pc:
        return None

    try:
        header = int(header, 16)
    except:
        return None
    try:
        pc = int(pc, 16)
    except:
        return None

    lib_addr = get_lib_addr_from_proc_mapping(header)
    if m_debug.Debug: m_debug.dbg_print("header=", header, "lib_addr=",lib_addr, "pc=", pc)
    if not lib_addr:
        return None
    try:
        buf = m_util.mdb_exec_to_str('x/1xw ' + str(header))
    except:
        return None

    if not buf:
        return None
    header_size = int(buf.split(':')[1],16)

    if (header < lib_addr):
        mdb_print ("Warning: The header address is lower than lib_addr.")
        return None
    if (pc < header):
        mdb_print ("Warning: The pc address is lower than the header address.")
        return None

    xxxxxx = header - lib_addr
    yyyyyy = pc - header - header_size

    return hex(xxxxxx) + ":" + "{:04x}".format(yyyyyy)+":"
Beispiel #11
0
    def create_mirbin_info_cache(self, asm_file):
        if m_debug.Debug:
            print("Entered create_mirbin_info_cache")
        if self.mirbin_info_cache_has_key(asm_file):
            return

        self.mirbin_info.init_new_asm(asm_file)

        d = m_asm.create_asm_mirbin_label_cache(asm_file)
        self.mirbin_info_cache_assign(asm_file, d)

        if m_debug.Debug:
            count = len(self.mirbin_info.mirbin_info_cache[asm_file].keys())
            m_debug.dbg_print("asm file ", asm_file, count, "labels found")
Beispiel #12
0
def get_lib_addr_from_proc_mapping(addr):
    """
    for a given Maple method address, find out the base address of the .so lib
    this address belongs to

    params:
      addr: address of a method in int

    returns:
      lib so base address in int
    """

    buf = get_modules_lookup(addr)
    start = None
    start_min = None
    end = None
    end_max = None
    path = None
    so_path = None
    asm_path = None
    for (hexstart, hexend, path) in re.findall(proc_mapping_re, buf):
        try:
            start = int(hexstart, 16)
        except:
            start = None
        try:
            end = int(hexend, 16)
        except:
            end = None
        if not start or not end or not path:
            continue

        if addr >= start and addr <= end:
            if not start_min:
                start_min = start
            else:
                start_min = start if start < start_min else start

            if not end_max:
                end_max = end
            else:
                end_max = end if end > end_max else end

            if m_debug.Debug: m_debug.dbg_print("start = ", hex(start), " start_min = ", hex(start_min), " end = ", hex(end), "end_max = ", hex(end_max), " addr = ", hex(addr))

            return start

    if m_debug.Debug: m_debug.dbg_print("return lib addr None")
    return None
Beispiel #13
0
    def create_mirmpl_info_cache(self, mirmpl_path):
        if m_debug.Debug:
            print("Entered create_mirmpl_info_cache")
        if self.mirmpl_info_cache_has_key(mirmpl_path):
            return

        self.mirmpl_info.init_new_mirmpl(mirmpl_path)

        d = m_mirmpl.create_mirmpl_label_cache(mirmpl_path)
        self.mirmpl_info_cache_assign(mirmpl_path, d)

        if m_debug.Debug:
            count = len(self.mirmpl_info.mirmpl_info_cache[mirmpl_path].keys())
            m_debug.dbg_print("mirmpl path ", mirmpl_path, count,
                              "labels found")
Beispiel #14
0
def look_up_next_opcode(asm_path, asm_line, asm_offset):
    """
      for a given asm file and asm line number and offset of the asm line number, return whether next opcode
      is going to jump to different source code line (e.g. Java code). If True, return next opcode's short
      source file name and line.

      params:
        asm_path: string. asm (.s) file full path.
        asm_line: int
        asm_offset: int. start offset in asm file line

      return:
        True if msi cmd should stop at next opcodd, and source code short file name and source line
        False if msi cmd should not stop. None as source name, None as source line
    """
    if m_debug.Debug:
        m_debug.dbg_print("asm_path = ", asm_path, "asm_line = ", asm_line,
                          "asm_offset=", asm_offset)

    f = open(asm_path, "r")
    f.seek(asm_offset)
    line = f.readline()

    short_src_file_name = None
    short_src_file_linenum = None
    additional_lines = 0
    while True:
        line = f.readline()
        if "// LINE " in line:
            x = line.split()
            short_src_file_name = x[2]
            short_src_file_linenum = int(x[4][:-1])
            if m_debug.Debug:
                m_debug.dbg_print("short_src_file_name = ", short_src_file_name,\
                                  "short_src_file_linenum", short_src_file_linenum,\
                                  "found in asm line_num =", asm_line + additional_lines)
            f.close()
            return True, short_src_file_name, short_src_file_linenum
        elif ".byte " in line:
            f.close()
            return False, None, None
        elif ".cfi_endproc" in line:
            break
        else:
            continue

    f.close()
    return False, None, None
Beispiel #15
0
def lookup_mirmpl_info(mirmpl_path, mirmpl_line_tuple, mir_instidx):
    """ in file mirmpl_path, and mirmpl_line_tuple,  for a given func_addr_offset_pc, lookup the
        matching line's line-num and its offset
        params: mirmpl: string. mirmpl file full path.
                mirmpl_line_tuple: a tuple for a Maple symbol.
                                    tuple[0] = mirmpl symbol block line number
                                    tuple[1] = mirmpl symbol block start offset
                                    tuple[2] = mirmpl symbol block end offset
                mir_instidx: string. mir_instidx offset_pc e.g. 0008

        return:
            a dict {'mirmpl_line': int, 'mirmpl_line_offset': int}
            where mirmple_line: func_addr_offset_pc found at this line, and at this mirmpl file offset
    """
    if m_debug.Debug:
        m_debug.dbg_print("mirmpl_path=", mirmpl_path, "mirmpl_line_tuple=",
                          mirmpl_line_tuple, "mir_instidx=", mir_instidx)

    offset = mirmpl_line_tuple[1]
    line_num = mirmpl_line_tuple[0]
    end_offset = mirmpl_line_tuple[2]

    if not mir_instidx:
        # return this symbol block's first address
        return {'mirmpl_line': line_num, 'mirmpl_line_offset': offset}

    f = open(mirmpl_path, "r")
    f.seek(offset)
    while offset < end_offset:
        line = f.readline()
        if mir_instidx in line:
            if m_debug.Debug:
                m_debug.dbg_print("found ", mir_instidx, " at line", line_num,
                                  "line=", line)
            f.close()
            return {'mirmpl_line': line_num, 'mirmpl_line_offset': offset}
        else:
            line_num += 1
            offset += len(line)

    f.close()

    return None
Beispiel #16
0
def find_one_file(name, path):
    """ find the file with specified name and given base path """
    if not name:
        return None
    exist = m_datastore.mlldb_rdata.in_fullpath_cache(name, path)
    if exist:
        return m_datastore.mlldb_rdata.get_fullpath_cache(name, path)
    res = None
    for root, dirs, files in os.walk(path):
        if name in files:
            res = os.path.join(root, name)
            if not res:
                if m_debug.Debug:
                    m_debug.dbg_print(
                        "find_one_file found file with None fullpath")
            break
    m_datastore.mlldb_rdata.add_fullpath_cache(name, path, res)
    if res == None:
        return (".../" + name)
    return res
Beispiel #17
0
def get_symbol_name_by_current_frame_args():
    """
    get the Maple symbol name and its address in currect frame stack via 'info args' command
    """

    cmd = 'info args'
    try:
        result = m_util.mdb_exec_to_str(cmd)
    except:
        return None, None
    if m_debug.Debug: m_debug.dbg_print("result=", result)

    offset = result.find('_mirbin_info>')
    if offset is -1:  #no Maple metadata pattern
        return None, None
    x = result.split()
    for i in range(len(x)):
        if x[i].find('_mirbin_info>') != -1:
            return x[i - 1], x[i][1:-1]
    return None, None
Beispiel #18
0
    def update_mdb_runtime_data(self):

        if m_debug.Debug: print("update mdb rt data ...")
        addr_offset, so_path, asm_path, func_header, mirmpl_path = m_frame.get_newest_maple_frame_func_lib_info(
        )

        targ = lldb.debugger.GetSelectedTarget()
        module_cnt = targ.GetNumModules()
        #for x in range(0, module_cnt):
        #    mod = targ.GetModuleAtIndex(x)
        #    print("Module:",mod)

        if m_debug.Debug:
            m_debug.dbg_print("addr_offset=", addr_offset)
            m_debug.dbg_print("so_path=", so_path)
            m_debug.dbg_print("asm_path=", asm_path)
            m_debug.dbg_print("func_header=", func_header)
            m_debug.dbg_print("mirmpl_path=", mirmpl_path)

        if not addr_offset or not so_path or not asm_path or not func_header or not mirmpl_path:
            return

        if not self.mirmpl_info_cache_has_key(mirmpl_path):
            if m_debug.Debug:
                mdb_print("create Maple mir.mpl cache using file: " +
                          mirmpl_path)
            self.create_mirmpl_info_cache(mirmpl_path)

        if not self.mirbin_info_cache_has_key(asm_path):
            if m_debug.Debug:
                mdb_print("create Maple symbol cache using file: " + asm_path)
            self.create_mirbin_info_cache(asm_path)

        def_file_path = asm_path[:
                                 -1] + 'macros.def' if 'VtableImpl' in asm_path else asm_path[:
                                                                                              -1] + 'VtableImpl.macros.def'
        if not def_file_path in self.class_def.def_paths:
            if m_debug.Debug:
                mdb_print("create def cache using file: " + def_file_path)
            self.create_class_def(def_file_path)
Beispiel #19
0
def lookup_next_src_file_info(asm_path, asm_line, asm_offset):
    """
      for a given asm file and asm line number and offset of the asm line number, return the next
      source file name and line.

      params:
        asm_path: string. asm (.s) file full path.
        asm_line: int
        asm_offset: int

      return:
        source code short file name or None if not found
        source code line number or 0 if not found
    """
    if m_debug.Debug:
        m_debug.dbg_print("asm_path = ", asm_path, "asm_line = ", asm_line,
                          "asm_offset=", asm_offset)

    f = open(asm_path, "r")
    f.seek(asm_offset)
    short_src_file_name = None
    short_src_file_linenum = None

    additional_lines = 0
    while additional_lines < 5:
        line = f.readline()
        if "// LINE " in line:
            x = line.split()
            short_src_file_name = x[2]
            short_src_file_linenum = int(x[4][:-1])
            if m_debug.Debug:                m_debug.dbg_print("short_src_file_name = ", short_src_file_name, "short_src_file_linenum", short_src_file_linenum,\
                 "found in asm line_num =", asm_line + additional_lines )
            f.close()
            return short_src_file_name, short_src_file_linenum
        else:
            additional_lines += 1

    f.close()
    return None, None
Beispiel #20
0
def get_symbol_name_by_current_func_args():
    """
    get the 'func' symbol name and its address in currect frame stack
    """

    cmd = 'p func'
    try:
        result = m_util.mdb_exec_to_str(cmd)
    except:
        return None, None
    if m_debug.Debug: m_debug.dbg_print("result=", result)

    if 'header = ' in result and '_mirbin_info>' in result:
        s = result.split('header = ')
        address = s[1].split()[0]
        name = s[1].split()[1].split('>')[0][1:]
        caller = result.split('caller = ')[1].split(',')[0]
        if m_debug.Debug:
            m_debug.dbg_print("address=", address, "name=", name, "caller=",
                              caller)
        return address, name
    else:
        return None, None
Beispiel #21
0
def get_uninitialized_maple_func_addrs():
    """
    get func addr information from an uninitialized Maple frame.
    NOTE: call this when Maple func is NOT initialized yet.

    returns:
      1, func header address in string format of xxxxxx:yyyyyy: format where
         xxxxxx means (header - lib_base_addr),
         yyyyyy means (pc - header - header_size)
      2, so_path: in string. so library full path.
      3, asm_path: in string. asm (.s) file full path
      4, func_header: func header address in string.
      5, mirmpl_path: in string. .mpl.mir.mpl file full path
    """

    func_header = get_maple_frame_addr()
    if not func_header:
        return None, None, None, None, None
    if m_debug.Debug: m_debug.dbg_print("func_header=", func_header)

    offset, func_lib_addr, so_path, asm_path, mirmpl_path = get_lib_so_info(func_header)
    if not func_lib_addr or not so_path or not asm_path or not mirmpl_path:
        return None, None, None, None, None
    if m_debug.Debug: m_debug.dbg_print("func_lib_addr=", func_lib_addr)

    #header = int(func_header, 16)
    #fla = int(func_lib_addr, 16)
    #if (header < fla):
    #    if m_debug.Debug: m_debug.dbg_print("Warning: The header address is lower than lib_addr.")
    #    return None, None, None, None, None

    #offset = header - fla

    # when a func in a frame is not initialized yet, pc value is 0000
    pc = '0000'

    return hex(int(offset, 16)) + ":" + pc + ":", so_path, asm_path, func_header, mirmpl_path
Beispiel #22
0
    def get_maple_class_def(self, class_name):
        if class_name in self.maple_class_def_cache:
            if m_debug.Debug:
                m_debug.dbg_print("class_name", class_name, "found")
                m_debug.dbg_print("return maple_class_def_cache[class_name]:",
                                  self.maple_class_def_cache[class_name])
            return self.maple_class_def_cache[class_name]

        if m_debug.Debug:
            m_debug.dbg_print("class_name", class_name, "Not found")
        return None
Beispiel #23
0
    def get_asm_mirbin_item(self, asm, mirbin_name):
        if not asm in self.mirbin_info_cache:
            if m_debug.Debug:
                m_debug.dbg_print("asm", asm,
                                  "not found in mirbin info cache ")
            return None

        if not mirbin_name in self.mirbin_info_cache[asm]:
            if m_debug.Debug:
                m_debug.dbg_print("Maple label", mirbin_name,
                                  "not found in mirbin info cache ")
            m_debug.dbg_print("Maple label", mirbin_name,
                              "not found in mirbin info cache ")
            return None

        if m_debug.Debug:
            m_debug.dbg_print("return ",
                              self.mirbin_info_cache[asm][mirbin_name])
        return self.mirbin_info_cache[asm][mirbin_name]
Beispiel #24
0
def get_symbol_name_by_current_frame_args():
    """
    get the Maple symbol name and its address in currect frame stack via 'frame variable' command
    """

    mir_addr = m_info.get_maple_frame_addr()
    a = int(mir_addr, 0)
    buf = m_info.get_modules_lookup(mir_addr)
    start = None
    mir_name = None
    """
      Address: libcore.so[0x00000000029a0ea8] (libcore.so.PT_LOAD[0]..text + 21571096)
      Summary: libcore.so`Ljava_2Fio_2FPrintStream_3B_7Cprintln_7C_28Ljava_2Flang_2FString_3B_29V_mirbin_info
       Module: file = "/vagrant/MAPLE/maple_engine/maple_runtime/lib/x86_64/libcore.so", arch = "x86_64"
       Symbol: id = {0x0003f050}, range = [0x00007fffeb98cea8-0x00007fffeb98cf20), name="Ljava_2Fio_2FPrintStream_3B_7Cprintln_7C_28Ljava_2Flang_2FS
    """
    if m_debug.Debug: m_debug.dbg_print("result=", buf)

    infos = buf.split('\n')

    if not infos:
        return None, None

    try:
        #if m_debug.Debug: m_debug.dbg_print("Infos:", infos)
        for line in infos:
            if "Symbol:" in line:
                y = line[14:].split()
                z = y[5].split('-')
                start = z[0][1:]
                if m_debug.Debug: m_debug.dbg_print("lib start addr:", start)
            if "Summary:" in line:
                y = line[14:].split()
                offset = line.find('_mirbin_info')
                if offset is -1:  #no Maple metadata pattern
                    return None, None
                mir_name = y
                if m_debug.Debug: m_debug.dbg_print("name", mir_name)

            else:
                #if m_debug.Debug: m_debug.dbg_print("Infos line:", line)
                continue
        return start, mir_name
    except Exception:
        print("-" * 60)
        print("Exception caught in m_break code:")
        traceback.print_stack(file=sys.stdout)
        print("-" * 60)
        traceback.print_exc(file=sys.stdout)
        print("-" * 60)
        return None, None

    return None, None
Beispiel #25
0
    def get_mirmpl_item(self, mirmpl, symbol):
        if not mirmpl in self.mirmpl_info_cache:
            if m_debug.Debug:
                m_debug.dbg_print("mirmpl", mirmpl,
                                  "not found in mirmpl info cache ")
            return None
        if not symbol in self.mirmpl_info_cache[mirmpl]:
            if m_debug.Debug:
                m_debug.dbg_print("Maple label", symbol,
                                  "not found in mirmpl_info_cache[", mirmpl,
                                  "]")
            return None

        if m_debug.Debug:
            m_debug.dbg_print("return ",
                              self.mirmpl_info_cache[mirmpl][symbol])
        return self.mirmpl_info_cache[mirmpl][symbol]
Beispiel #26
0
def get_maple_caller_argument_value(arg_idx, arg_num, mtype):
    """
    for a given Maple caller's arg_idx, arg_num and type,
    get its value from caller's operand_stack

    params:
      arg_idx: the argument index in a Maple method.
               e.g. method1(int a, long b, string c), for
               argument "a", its arg index is 0, c is 2.
      arg_num: number of argument a method has
      mtype  : a string. definition in m_asm.py
               for "a", it could be 'i32', 'i64'
    returns:
       the argument value in string.
    """

    if m_debug.Debug: m_debug.dbg_print("pass in arg_idx=", arg_idx, "arg_num=", arg_num, "mtype=", mtype)

    # get the caller.sp first
    try:
        #buffer = m_util.mdb_exec_to_str('p caller.sp')
        buffer = m_util.mdb_exec_to_str('p caller->sp')
    except:
        return None

    if 'No symbol "caller" in current context.' in buffer:
        return None
    if ' = ' in buffer:
        sp = int(buffer.split(' = ')[-1])
    else:
        return None

    if  arg_idx > sp: #sp must be >= num of args
        return None
    if m_debug.Debug: m_debug.dbg_print("sp=", sp)

    # get the caller.operand_stack length
    try:
        buffer = m_util.mdb_exec_to_str('p caller->operand_stack.size()')
    except:
        return None
    if m_debug.Debug: m_debug.dbg_print("ss=", buffer)

    #if buffer[0] != '$':
    if not buffer or buffer[0] != '(':
        return None
    if ' = ' in buffer:
        try:
            length = int(buffer.split(' = ')[1])
        except:
            return None
    else:
        return None
    if m_debug.Debug: m_debug.dbg_print("length=", length)

    if length < arg_idx:
        return None

    # get the caller.operand_stack[arg_idx]
    idx = sp - arg_num + arg_idx + 1
    if m_debug.Debug: m_debug.dbg_print("idx=", idx)

    try:
        #buffer = m_util.mdb_exec_to_str('p caller->operand_stack[' + str(idx) + ']')
        stbuffer = m_util.mdb_exec_to_str('p caller->operand_stack')
        #if m_debug.Debug: m_debug.dbg_print("stbuffer=", stbuffer)
        buffer = stbuffer.split('x = (')[(idx+1)]
        #if m_debug.Debug: m_debug.dbg_print("buffer=", buffer)
        vline = buffer.split(')')[0]
        if m_debug.Debug: m_debug.dbg_print("vline=", vline)

    except:
        return None

    #vline = buffer.split('x = ')[1][1:].split('}')[0]
    v = vline.split(mtype+' = ')[1].split(',')[0] if mtype in vline else None
    return v
Beispiel #27
0
def get_loaded_lib_asm_path():
    asm_path_list = []
    #objfiles = mdb.objfiles()
    objfiles = {}
    for objfile in objfiles:
        if not lib_file_filter(objfile.filename):
            continue

        so_path = os.path.realpath(objfile.filename)
        if m_debug.Debug: m_debug.dbg_print("realpath so_path=",so_path)
        asm_path = so_path[:-3] + '.VtableImpl.s'
        asm_path = os.path.realpath(asm_path)
        if os.path.exists(so_path) and os.path.exists(asm_path):
            # both .so file and co-responding .s file exist in same directory
            if m_debug.Debug: m_debug.dbg_print("return lib info: so_path=",so_path, "asm_path=", asm_path)
            asm_path_list.append(asm_path)
            continue

        asm_path = so_path[:-3] + '.s'
        asm_path = os.path.realpath(asm_path)
        if os.path.exists(so_path) and os.path.exists(asm_path):
            # both .so file and co-responding .s file exist in same directory
            if m_debug.Debug: m_debug.dbg_print("return lib info: so_path=",so_path, "asm_path=", asm_path)
            asm_path_list.append(asm_path)
            continue

        so_path_short_name = so_path.split('/')[-1][:-3]

        base = so_path.split('/')
        asm_path = ''
        for i in range(len(base) - 4):
            asm_path += '/' + base[i]
        asm_path += '/maple_build/out/x86_64/'+ so_path_short_name + '.VtableImpl.s'
        asm_path = os.path.realpath(asm_path)
        if os.path.exists(so_path) and os.path.exists(asm_path):
            # special case where .so and .VtableImpl.s are in such a different folders
            if m_debug.Debug:
                m_debug.dbg_print("return lib info: so_path=",so_path, "asm_path=", asm_path)
            asm_path_list.append(asm_path)
            continue

        if not 'maple_lib_asm_path' in m_set.msettings:
            continue
        for v in m_set.msettings['maple_lib_asm_path']:
            asm_path = v + '/' + so_path_short_name + '.VtableImpl.s'
            asm_path = os.path.realpath(asm_path)
            #asm_path = path.split('maple/out')[0] + 'maple/out/common/share/' + so_path_short_name + '.VtableImpl.s'
            if os.path.exists(so_path) and os.path.exists(asm_path):
                # .s file is in the search path list
                if m_debug.Debug:
                    m_debug.dbg_print("return lib info: so_path=",so_path, "asm_path=", asm_path)
                asm_path_list.append(asm_path)
                continue

    if m_debug.Debug:
       m_debug.dbg_print("returning asm_path_list length", len(asm_path_list))
       m_debug.dbg_print("returning asm_path_list ", asm_path_list)

    return asm_path_list
Beispiel #28
0
def get_lib_so_info(addr):
    """
    for a given Maple method address, look up the lib so file, and get information
    about the so library and its co-responding asm file info.

    params:
      addr: address of a method in hex string with prefix '0x', i.e 0x7fff6021c308

    returns:
      1, so lib start address: int
      2, lib so file full path in string
      3, lib asm file full path in string
      4, lib mpl.mir.mpl file full path in string
    """
    start = None
    end = None
    path = None
    so_path = None
    asm_path = None
    mirmpl_path = None
    a = int(addr, 0)
    buf = get_modules_lookup(addr)
    """
  Address: libcore.so[0x00000000029a0ea8] (libcore.so.PT_LOAD[0]..text + 21571096)
  Summary: libcore.so`Ljava_2Fio_2FPrintStream_3B_7Cprintln_7C_28Ljava_2Flang_2FString_3B_29V_mirbin_info
   Module: file = "/vagrant/MAPLE/maple_engine/maple_runtime/lib/x86_64/libcore.so", arch = "x86_64"
   Symbol: id = {0x0003f050}, range = [0x00007fffeb98cea8-0x00007fffeb98cf20), name="Ljava_2Fio_2FPrintStream_3B_7Cprintln_7C_28Ljava_2Flang_2FS
    """
    infos = buf.split('\n')
    offset = 0
    if not infos:
        return None, None, None, None, None

    try:
        #if m_debug.Debug: m_debug.dbg_print("Infos:", infos)
        for line in infos:
            if "Module:" in line:
                x = line[14:].split()
                so_path = x[2][1:][:-2]
                if m_debug.Debug: m_debug.dbg_print("base file:",so_path)
            elif "Symbol:" in line:
                y = line[14:].split()
                z = y[5].split('-')
                start = z[0][1:]
                end = z[1][2:]
                if m_debug.Debug: m_debug.dbg_print("lib start addr:", start,"end:",end)
            elif "Address:" in line:
                x = line[14:].split()
                y = x[0].split('[')
                offset = y[1][:-1]
                if m_debug.Debug: m_debug.dbg_print("offset:",offset)

            else:
                #if m_debug.Debug: m_debug.dbg_print("Infos line:", line)
                continue

        if not so_path.rstrip().lower().endswith('.so'):
            if m_debug.Debug: m_debug.dbg_print("path does not end with .so, path = ", so_path)
            return None, None, None, None, None

        so_path = so_path.rstrip().replace('/./','/')
        #if m_debug.Debug: m_debug.dbg_print("mdb.solib_name(addr)=", mdb.solib_name(a))
        mirmpl_path = so_path[:-3] + '.mpl.mir.mpl'
        mirmpl_path = os.path.realpath(mirmpl_path)
        asm_path = so_path[:-3] + '.VtableImpl.s'
        asm_path = os.path.realpath(asm_path)
        if os.path.exists(so_path) and os.path.exists(asm_path) and os.path.exists(mirmpl_path):
            # both .so file and co-responding .s file exist in same directory
            if m_debug.Debug: m_debug.dbg_print("return lib info: start=", start, "so_path=",so_path,\
                                                "asm_path=", asm_path, "mirmpl_path=", mirmpl_path)
            return offset, start, so_path, asm_path, mirmpl_path
        else:
            if m_debug.Debug: m_debug.dbg_print("first round fails validation, path = ", so_path)

        asm_path = so_path[:-3] + '.s'
        asm_path = os.path.realpath(asm_path)
        mirmpl_path = so_path[:-3] + '.mpl.mir.mpl'
        mirmpl_path = os.path.realpath(mirmpl_path)
        if os.path.exists(so_path) and os.path.exists(asm_path) and os.path.exists(mirmpl_path):
            # both .so file and co-responding .s file exist in same directory
            if m_debug.Debug: m_debug.dbg_print("return lib info: start=", start, "so_path=",so_path, \
                                                "asm_path=", asm_path, "mirmpl_path=", mirmpl_path)
            return offset, start, so_path, asm_path, mirmpl_path
        else:
            if m_debug.Debug: m_debug.dbg_print("second round fails validation, path = ", so_path)

        so_path_short_name = so_path.split('/')[-1][:-3]

        base = so_path.split('/')
        asm_path = ''
        for i in range(len(base) - 4):
            asm_path += '/' + base[i]
        mirmpl_path = asm_path + '/maple_build/out/x86_64/'+ so_path_short_name + '.mpl.mir.mpl'
        mirmpl_path = os.path.realpath(mirmpl_path)
        asm_path += '/maple_build/out/x86_64/'+ so_path_short_name + '.VtableImpl.s'
        asm_path = os.path.realpath(asm_path)
        if os.path.exists(so_path) and os.path.exists(asm_path) and os.path.exists(mirmpl_path):
            # special case where .so and .VtableImpl.s are in such a different folders
            if m_debug.Debug:
                m_debug.dbg_print("return lib info: start=", start, "so_path=",so_path, \
                                    "asm_path=", asm_path, "mirmpl_path=", mirmpl_path)
            return offset, start, so_path, asm_path, mirmpl_path
        else:
            if m_debug.Debug: m_debug.dbg_print("third round fails validation, path = ", so_path)

        if not 'maple_lib_asm_path' in m_set.msettings:
            return None, None, None, None
        for v in m_set.msettings['maple_lib_asm_path']:
            mirmpl_path = v + '/'+ so_path_short_name + '.mpl.mir.mpl'
            mirmpl_path = os.path.realpath(mirmpl_path)
            asm_path = v + '/' + so_path_short_name + '.VtableImpl.s'
            asm_path = os.path.realpath(asm_path)
            #asm_path = path.split('maple/out')[0] + 'maple/out/common/share/' + so_path_short_name + '.VtableImpl.s'
            if os.path.exists(so_path) and os.path.exists(asm_path) and os.path.exists(mirmpl_path):
                # .s file is in the search path list
                if m_debug.Debug:
                    m_debug.dbg_print("return lib info: start=", start, "so_path=",so_path, \
                                        "asm_path=", asm_path, "mirmpl_path", mirmpl_path)
                return offset, start, so_path, asm_path, mirmpl_path
            else:
                if m_debug.Debug: m_debug.dbg_print("settings round fails validation, path = ", so_path)
    except Exception:
        print("-"*60)
        print("Exception caught in m_break code:")
        traceback.print_stack(file=sys.stdout)
        print("-"*60)
        traceback.print_exc(file=sys.stdout)
        print("-"*60)
        return None, None, None, None, None

    return None, None, None, None, None
Beispiel #29
0
def get_stack_frame_data(frame):
    """
    For a given Maple stack frame, get all finds of frame data including
    1, function. Header info
    2, function. Source code information
    3, function. Local variable and argument information.

    params:
      frame: a gdb.frame object. A SELECTED Maple frame from current stack.

    returns:
       a dict contains following keys and values
        'frame_func_src_info':  whatever m_asm.lookup_src_file_info() returns
                {'short_src_file_name': a string. source code short name
                 'short_src_file_line': a int. source code file line
                 'asm_line': a int. line number where func_header_name offset is found in asm file
                 'asm_offset': a int. offset in the asm file co-repsonding to asm_line
                 'mirmpl_line': a int. symbol block line in mir.mpl file
                 'mirmpl_line_offset': a int. symbol block line offset in mir.mpl file
                 'mir_instidx': a string. symbol block mir instidx offset, e.g. 0008 in both .s and .s file
                }
        'frame_func_header_info':
                {'func_name': func_name, string.
                 'so_path': so_path full path, a string
                 'asm_path': asm_path full path,a string
                 'mirmpl_path': mir.mpl file full path. a string
                 'func_addr_offset': func_addr_offset, string in xxxx:yyyy: format
                 'func_header_name' : func_header_name, a string. e.g. xxxxxxxxxxx_mirbin_info
                 'func_header_asm_tuple': func_header_name_block_asm_tuple, (asm line, asm_start_offset, asm_end_offset)
                 'func_header_mirmpl_tuple': func_header_name_block_mir_tuple, (mir line, mir_start_offset, mir_end_offset)
                }
        'func_argus_locals': same return as m_asm.get_func_arguments() returns
                {'locals_type': local variable type list, e.g. ['void', 'v2i64'],
                 'locals_name': local variable name list['%%retval', '%%thrownval'],
                 'formals_type': func argument type list. e.g. ['a64'],
                 'formals_name': func argument name list. e.g. ['%1']
                }
    """
    #m_debug.Debug = True
    if m_debug.Debug: m_debug.dbg_print("==== get_stack_frame_data =====")

    func_addr_offset, so_path, asm_path, func_header, mirmpl_path = m_frame.get_maple_frame_func_lib_info(
        frame)
    if m_debug.Debug:
        m_debug.dbg_print("func_addr_offset =", func_addr_offset,
                          "func_header=", func_header)
        m_debug.dbg_print("so_path =", so_path, "asm_path=", asm_path,
                          "mirmpl_path=", mirmpl_path)
    if not func_addr_offset or not so_path or not asm_path or not func_header or not mirmpl_path:
        return None

    ### get the function label of the frame
    label_addr, func_header_name = m_symbol.get_symbol_name_by_current_frame_args(
    )
    if m_debug.Debug: m_debug.dbg_print("func_header_name=", func_header_name)
    if func_header_name:
        fhn = func_header_name[0].split('`')
        func_header_name = fhn[1]
        func_name = func_header_name[:-12]
        if m_debug.Debug: m_debug.dbg_print("func_name=", func_name)
    else:
        label_addr, func_header_name = m_symbol.get_symbol_name_by_current_func_args(
        )
        fhn = func_header_name[0].split('`')
        func_header_name = fhn[1]
        func_name = func_header_name[:-12]
        if m_debug.Debug: m_debug.dbg_print("func_name=", func_name)

    if m_debug.Debug: m_debug.dbg_print("func_header_name=", func_header_name)
    if not func_header_name:
        return None

    # if mirbin_info_cache for this asm file is not created yet in m_datastore, create it
    # if not m_datastore.mgdb_rdata.mirbin_info_cache_has_key(asm_path):
    if not mlldb_rdata.mirbin_info_cache_has_key(asm_path):
        if m_debug.Debug:
            m_debug.dbg_print("create mirbin info cache for asm file",
                              asm_path)
        mlldb_rdata.create_mirbin_info_cache(asm_path)

    # if mirmpl_info_cache for this mir.mpl file is not created yet in m_datastore, create it
    # if not m_datastore.mgdb_rdata.mirmpl_info_cache_has_key(mirmpl_path):
    if not mlldb_rdata.mirmpl_info_cache_has_key(mirmpl_path):
        if m_debug.Debug:
            m_debug.dbg_print("create mirmpl info cache for mirmpl file",
                              mirmpl_path)
        mlldb_rdata.create_mirmpl_info_cache(mirmpl_path)

    asm_line_tuple = mlldb_rdata.get_one_label_mirbin_info_cache(
        asm_path, func_header_name)
    if not asm_line_tuple:
        if m_debug.Debug:
            m_debug.dbg_print("no asm_line_tuple found", asm_path, "for",
                              func_header_name)
        return None
    if m_debug.Debug:
        m_debug.dbg_print("asm_line_tuple=", asm_line_tuple)
        m_debug.dbg_print("func_addr_offset=", func_addr_offset)
        m_debug.dbg_print("func_addr_offset.split(':')[1]=",
                          func_addr_offset.split(':')[1])
    func_addr_offset_pc = func_addr_offset.split(':')[1]
    d = m_asm.lookup_src_file_info(asm_path, asm_line_tuple[0], asm_line_tuple[1], asm_line_tuple[2],\
                                              func_addr_offset_pc)
    if not d:
        if m_debug.Debug:
            m_debug.dbg_print("lookup_src_file_info returns None")
        return None
    if m_debug.Debug: m_debug.dbg_print("first round returns dict d:", d)

    # In some cases, when func_addr_offset's pc partion is 0000, or func_addr_offset is followed by "MPL_CLINIT_CHECK",
    # the source code file information can be missing.
    # In this case, we can check few more lines from its reported asm line ONLY for pc = '0000' or "MPI_CLINIT_CHECK" situation
    if not d['short_src_file_name'] and (
            func_addr_offset_pc == '0000' or d['short_src_file_line']
            == -1) and d['asm_offset'] != 0 and d['asm_line'] != 0:
        if m_debug.Debug:
            m_debug.dbg_print(
                "func offset pc is 0000, check short_src_file again")
        d['short_src_file_name'], d['short_src_file_line'] = \
            m_asm.lookup_next_src_file_info(asm_path, d['asm_line'], d['asm_offset'])
        if m_debug.Debug:
            m_debug.dbg_print(
                "second round for func offset pc 0000 returns dict d:", d)

    # read the mpl.mir.mpl file, get the func_addr_offset_pc line and offset at .mpl.mir.mpl file
    # note, func_header_name ends with symbol_mirbin_info, while mir.mpl's symbol has no '_mirbin_info'
    #print("mirmpl_path=",mirmpl_path, "func_header_name[:-12]=",func_header_name[:-12])
    mirmpl_line_tuple = mlldb_rdata.get_one_label_mirmpl_info_cache(
        mirmpl_path, func_header_name[:-12])
    mir_instidx = d['mir_instidx']
    #print("mirmpl_line_tuple=",mirmpl_line_tuple, "mir_instidx=", mir_instidx)
    d_mirmpl = m_mirmpl.lookup_mirmpl_info(mirmpl_path, mirmpl_line_tuple,
                                           mir_instidx)
    #rint("d_mirmpl=",d_mirmpl)
    # dictionary of d_mirmpl: {'mirmpl_line': int, 'mirmpl_Line_offset': int}
    if not d_mirmpl:
        if m_debug.Debug: m_debug.dbg_print("lookup_mirmpl_info returns None")
        return None
    if m_debug.Debug:
        m_debug.dbg_print(
            "m_mirmpl.lookup_mirmpl_info() returns dict d_mirmpl:", d_mirmpl)

    # merge two dictionaries
    d = {**d, **d_mirmpl}
    if m_debug.Debug: m_debug.dbg_print("After merging asm_d and mirmpl_d:", d)

    asm_line_offset = asm_line_tuple[1]
    asm_line_num = d['asm_line']
    mirmpl_line_num = d['mirmpl_line']
    mirmpl_line_offset = d['mirmpl_line_offset']
    src_file_short_name = d['short_src_file_name']
    src_file_line = d['short_src_file_line']

    if not asm_line_offset:
        return None

    ### get the method arguments and local variables
    func_argus_locals = m_asm.get_func_arguments(asm_path, func_header_name,
                                                 asm_line_offset)
    if m_debug.Debug:
        m_debug.dbg_print("func_argus_locals:", func_argus_locals)
    if not func_argus_locals:
        return None

    rdata = {}
    rdata['frame_func_src_info'] = d
    rdata['frame_func_header_info'] = { 'so_path': so_path, \
                                        'asm_path': asm_path, \
                                        'mirmpl_path': mirmpl_path, \
                                        'func_addr_offset': func_addr_offset, \
                                        'func_name': func_name, \
                                        'func_header_name' : func_header_name, \
                                        'func_header_asm_tuple': asm_line_tuple, \
                                        'func_header_mirmpl_tuple': mirmpl_line_tuple \
                                      }
    rdata['func_argus_locals'] = func_argus_locals

    return rdata
Beispiel #30
0
def does_mbp_exist():
    """ determine where a Maple breakpoint exists """
    target = lldb.debugger.GetSelectedTarget()
    #namelist = lldb.SBStringList()
    #namelist.AppendString('maple::maple_invoke_method')
    #print(dir(namelist))
    #namelist.AppendString('maple::maple_invoke_method')
    #print ("namelist.GetSize()=", namelist.GetSize())
    #print ("namelist.GetStringAtIndex(0)=", namelist.GetStringAtIndex(0))
    #print (dir(target.GetBreakpointNames(namelist)))
    #print (target.GetBreakpointNames(namelist))
    #print (dir(namelist))
    #print ("namelist.IsValid()=", namelist.IsValid())
    #print ("namelist.GetSize()=", namelist.GetSize())
    #print ("namelist.GetStringAtIndex(0)=", namelist.GetStringAtIndex(0))

    num_bp = target.GetNumBreakpoints()
    if m_debug.Debug: m_debug.dbg_print("does_mbp_exist: num_bp=", num_bp)
    for i in range(num_bp):
        bp = target.GetBreakpointAtIndex(i)
        if m_debug.Debug: m_debug.dbg_print("\nbp=", bp)
        enabled_bool = bp.IsEnabled()
        if m_debug.Debug:
            m_debug.dbg_print("id=", bp.GetID(), "enabled_bool=", enabled_bool,
                              "isValid()=", bp.IsValid())
        if m_debug.Debug:
            m_debug.dbg_print("num_location=",
                              bp.GetNumLocations(), "num_resolved_loc=",
                              bp.GetNumResolvedLocations())
        #print("bp.GetThreadName()=", bp.GetThreadName(), "bp.GetQueueName()=", bp.GetQueueName())
        #print("bp.MatchesName(maple::maple_invoke_method)=", bp.MatchesName('maple::maple_invoke_method'))

        stream = lldb.SBStream()
        bp.GetDescription(stream)
        if m_debug.Debug:
            m_debug.dbg_print("selected bp desc=", stream.GetData())
        bp_name = stream.GetData().split("name = ")[1].split(",")[0].replace(
            "'", "")
        if m_debug.Debug: m_debug.dbg_print("bp_name=", bp_name)

        if bp_name == 'maple::maple_invoke_method':
            return True, bp

        #__getattr__ = lambda self, name: _swig_getattr(self, SBBreakpointLocation, name)
        #print ("__getattr__=", __getattr)

        # using GetLocatioAtIndex() could help to get the breakpoint name Once we run the
        # the program.
        '''
        bl = bp.GetLocationAtIndex(0)
        print ("bl=", bl)
        if not bl:
            continue
        print("bl.GetAddress()=", bl.GetAddress())
        print("bl.GetAddress().GetSymbol().GetName()=", bl.GetAddress().GetSymbol().GetName())
        bp_name = bl.GetAddress().GetSymbol().GetName()
        print("bl.GetLoadAddress()=", bl.GetLoadAddress())
        '''
        '''
        for bl in bp:
            print("bl=", bl)
            bl_load_addr = bl.GetLoadAddress()
            bl_addr = bl.GetAddress()
            print("bp", bp.GetID(), "loc addr=", bl_addr, "loc_load_addr=", loc_load_addr)
            if 'maple::maple_invoke_method' in bl_addr.GetSymbol().GetName() and enabled_bool:
                print("found match")
                return True, bp
            else:
                print("no match")
        '''

    return False, None