Ejemplo n.º 1
0
    def mstep_func(self, args):
        frame = m_frame.get_selected_frame()
        ds = m_datastore.get_stack_frame_data(frame)
        if not ds:
            return
        if m_debug.Debug: m_debug.dbg_print("retrieved ds=", ds)
        asm_path = ds['frame_func_header_info']['asm_path']
        asm_line = ds['frame_func_src_info']['asm_line']
        asm_offset = ds['frame_func_src_info']['asm_offset']

        stop = False
        short_src_file_name = None
        short_src_file_line = None
        count = 0
        while not stop:
            # before we execute msi command, we must know should we stop keep executing msi after the current msi
            # is executed. If current msi command is executed and found it should stop, then we need the source file
            # information after stop.
            stop, short_src_file_name, short_src_file_line = m_asm.look_up_next_opcode(
                asm_path, asm_line, asm_offset)
            if m_debug.Debug:
                m_debug.dbg_print("stop =", stop, "short_src_file_name=",
                                  short_src_file_name, "short_src_file_line=",
                                  short_src_file_line)
            m_util.gdb_exec("msi -internal")
            count += 1
            if m_debug.Debug:
                m_debug.dbg_print("executed %d opcodes", count)
            # retrieve the new frame data since one opcode can change to a different frame
            frame = m_frame.get_selected_frame()
            ds = m_datastore.get_stack_frame_data(frame)
            if not ds:
                gdb_print("Warning: Failed to get new stack frame to continue")
                return
            if m_debug.Debug: m_debug.dbg_print("retrieved ds=", ds)
            asm_path = ds['frame_func_header_info']['asm_path']
            asm_line = ds['frame_func_src_info']['asm_line']
            asm_offset = ds['frame_func_src_info']['asm_offset']

        gdb_print("Info: executed %d %s" %
                  (count, 'opcode' if count == 1 else 'opcodes'))
        if m_debug.Debug:
            m_debug.dbg_print("short_src_file_name = ", short_src_file_name,
                              "short_src_file_line=", short_src_file_line)

        file_full_path = None
        for source_path in m_list.maple_source_path_list:
            file_full_path = m_list.find_one_file(short_src_file_name,
                                                  source_path)
            if not file_full_path:
                continue
            else:
                break

        if not file_full_path:
            gdb_print("Warning: source file %s not found" %
                      (short_src_file_name))
        else:
            m_list.display_src_file_lines(file_full_path, short_src_file_line)
        return
Ejemplo n.º 2
0
def display_symbol_detail(symbol_name, symbol_asm_path):
    if m_debug.Debug:
        m_debug.dbg_print("symbol_asm_path=", symbol_asm_path, "symbol_name=",
                          symbol_name)
    if not symbol_name or not symbol_asm_path:
        return

    data = m_datastore.mgdb_rdata.get_one_label_mirbin_info_cache(
        symbol_asm_path, symbol_name)
    d = m_asm.lookup_src_file_info(symbol_asm_path, data[0], data[1], data[2],
                                   "0000")
    if not d:
        return

    short_src_file_name, short_src_file_line = m_asm.lookup_next_src_file_info(symbol_asm_path,\
                                                                                d["asm_line"], d['asm_offset'])

    file_full_path = None
    for source_path in m_list.maple_source_path_list:
        file_full_path = m_list.find_one_file(short_src_file_name, source_path)
        if not file_full_path:
            continue
        else:
            break

    gdb_print("assembly file : " + symbol_asm_path)
    if not file_full_path:
        gdb_print("source        : unknown")
    else:
        gdb_print("source        : " + file_full_path)
    gdb_print("demangled name: " + m_symbol.get_demangled_maple_symbol(
        m_util.color_symbol(MColors.SP_SNAME, symbol_name[:-12])))
Ejemplo n.º 3
0
    def display_array_char_values(self, addr, type_size, item_num):

        if item_num > 32:
            item_list = [i for i in range(24)]
            item_list = item_list + [i for i in range(item_num - 8, item_num)]
        else:
            item_list = [i for i in range(item_num)]

        steps = 0
        show_snip = True
        buf = 'String Value: "' + MColors.MP_STR_V
        for i in item_list:
            obj_addr = addr + 4 + type_size * i  # class reference is a pointer, 8 bytes
            cmd = 'x/1hx ' + hex(obj_addr)
            if m_debug.Debug: m_debug.dbg_print("cmd=", cmd)
            try:
                buffer = m_util.gdb_exec_to_str(cmd)
            except:
                buf = '  {}'.format('no-data')
                gdb_print(buf)
                steps += 1
                return

            steps += 1
            v = buffer.split(':')[1].strip()
            buf = buf + int(v, 16).to_bytes(
                2, byteorder='big').decode("utf-16-be")

            if item_num > 32 and steps >= 24 and show_snip == True:
                buf = buf + '...'
                show_snip = False

        gdb_print(buf + MColors.ENDC + '"')
        return
Ejemplo n.º 4
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
Ejemplo n.º 5
0
def get_current_frame_rip(frame):
    """
    for a given frame, get its register "pc" value, and use the pc value to get the first
    instruction's memory address, return it as frame's rip

    params:
      frame: a gdb.Frame object

    returns:
      rip address, or frame's first instruction address: an int
    """

    if not frame:
        return None

    arch = frame.architecture()
    current_pc = frame.read_register("pc")
    if m_debug.Debug: m_debug.dbg_print("current_pc obj=", current_pc)
    current_pc = int(current_pc)

    # arch.disassemble(start_pc) returns a list of disassembled instructions from start_pc.
    # each element of the list is a dict contains 'addr', 'asm', 'length' which addr is the
    # memory address of the instruction.
    # see https://sourceware.org/gdb/onlinedocs/gdb/Architectures-In-Python.html#Architectures-In-Python
    disa = arch.disassemble(current_pc)[0]
    if m_debug.Debug: m_debug.dbg_print("disa=", disa)

    return disa['addr']
Ejemplo n.º 6
0
    def update_gdb_runtime_data(self):

        addr_offset, so_path, asm_path, func_header, mirmpl_path = m_frame.get_newest_maple_frame_func_lib_info(
        )
        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):
            gdb_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):
            gdb_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:
            gdb_print("create def cache using file: " + def_file_path)
            self.create_class_def(def_file_path)
Ejemplo n.º 7
0
def mni_display_last_opcodes():
    # to display the latest instructions will be executed after this command
    frame = m_frame.get_selected_frame()
    if not frame:
        return
    ds = m_datastore.get_stack_frame_data(frame)
    if not ds:
        return
    if m_debug.Debug: m_debug.dbg_print("retrieved ds=", ds)

    if m_set.msettings['stack'] == 'on':
        m_util.gdb_exec('mlocal -stack')

    asm_path = ds['frame_func_header_info']['asm_path']
    asm_line = ds['frame_func_src_info']['asm_line']
    asm_offset = ds['frame_func_src_info']['asm_offset']

    gdb_print("asm file: %s%s%s" % (MColors.BT_SRC, asm_path, MColors.ENDC))
    f = open(asm_path, 'r')
    f.seek(asm_offset)
    line = f.readline()
    gdb_print(str(asm_line) + " : " + line.rstrip())
    line = f.readline()
    gdb_print(str(asm_line+1) + " : " + line.rstrip())
    line = f.readline()
    gdb_print(str(asm_line+2) + " : " + line.rstrip())
    f.close()
Ejemplo n.º 8
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*)"
    buf = buf.split('\n')
    for line in buf:
        if m_debug.Debug: m_debug.dbg_print("line=", line)
        if match_pattern in line:
            x = line.split(match_pattern)
            addr = x[0].split()[-1]
            try:
                addr = int(addr, 16)
            except:
                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
Ejemplo n.º 9
0
def get_obj_prop_list_head(addr):
    cmd = "p *(struct __jsobject *)" + str(addr)
    # example of output could be:
    # 1. when prop_list is not available meaning nothing should be interpreted.
    #   "$40 = {prop_list = 0x0, prototype = {obj = 0x2, id = JSBUILTIN_OBJECTPROTOTYPE}, extensible = 1 '\001', object_class = JSGLOBAL, object_type = 0 '\000',
    #   is_builtin = 1 '\001', proto_is_builtin = 1 '\001', builtin_id = JSBUILTIN_GLOBALOBJECT, shared = {fast_props = 0x0, array_props = 0x0, fun = 0x0,
    #   prim_string = 0x0, prim_regexp = 0x0, prim_number = 0, prim_bool = 0, arr = 0x0, primDouble = 0}}
    #
    # 2. when prop_list is available, we should get the list and traverse the prop list
    #    $85 = {prop_list = 0x7ffff63d4178, prototype = {obj = 0x2, id = JSBUILTIN_OBJECTPROTOTYPE}, extensible = 1 '\001', object_class = JSGLOBAL, object_type = 0 '\000'    #    , is_builtin = 1 '\001', proto_is_builtin = 1 '\001', builtin_id = JSBUILTIN_GLOBALOBJECT, shared = {fast_props = 0x0, array_props = 0x0, fun = 0x0,
    #    prim_string = 0x0, prim_regexp = 0x0, prim_number = 0, prim_bool = 0, arr = 0x0, primDouble = 0}}

    buf = gdb.execute(cmd, to_string = True)
    buf = buf.rstrip()
    if m_debug.Debug: m_debug.dbg_print("get_obj_prop_list_head buf = ", buf)

    if buf[0] != '$' or 'prop_list = ' not in buf:
        return None
    prop_list = buf.split("prop_list = ")[1].split(',')[0]
    try:
        prop_list_addr = int(prop_list, 16)
    except:
        return None

    if m_debug.Debug: m_debug.dbg_print("prop_list_addr=", prop_list_addr)
    if prop_list_addr == 0:
        return None
    else:
        return prop_list
Ejemplo n.º 10
0
    def update_mbp(self):
        """
        when enabled maple breakpoints reach to 0, we disable the breakpint of maple::maple_invoke_method
        for better performance. When enabled maple breakpoints changes from 0 to 1 or more, we enable the
        breakpoint maple::maple_invoke_method.
        However, if the maple::maple_invoke_method is pending, we do not do anything since it is not
        activated yet

        However, the beter way to do this is to use mbp_id.enabled = True or False to enable or disable
        the maple::maple_invoke_method. We chose not to do it this way, because our regression test suite
        needs an output pattern that can be checked easily. changing enabled=True or False does not make
        this easier.
        """

        mbp_id = get_mbp_id()
        if not mbp_id:
            return
        # if maple:maple_invoke_method breakpoint is pending, we do not have to do anything.
        if mbp_id.pending:
            return

        # get the maple breakpoint number for those are enabled
        mbp_num = self.get_enabled_mbp_number()
        if m_debug.Debug: m_debug.dbg_print("mbp_num returned =", mbp_num)
        # disable maple:maple_invoke_method breakpoint
        buf = m_util.gdb_exec_to_str("info b")
        if mbp_num == 0:
            # disable this breakpoint
            update_maple_invoke_bp(buf, False)
        else:
            # enable this breakpoint
            update_maple_invoke_bp(buf, True)
Ejemplo n.º 11
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.gdb_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
Ejemplo n.º 12
0
    def mstepi_update_and_display(self, frame):
        # this will update the Maple gdb runtime metadata store.
        m_datastore.mgdb_rdata.update_gdb_runtime_data()
        m_datastore.mgdb_rdata.update_frame_change_counter()

        ds = m_datastore.get_stack_frame_data(frame)
        if not ds:
            return
        if m_debug.Debug: m_debug.dbg_print("retrieved ds=", ds)

        if m_set.msettings['stack'] == 'on':
            m_util.gdb_exec('mlocal -stack')

        asm_path = ds['frame_func_header_info']['asm_path']
        asm_line = ds['frame_func_src_info']['asm_line']
        asm_offset = ds['frame_func_src_info']['asm_offset']

        gdb_print("asm file: %s%s%s" %
                  (MColors.BT_SRC, asm_path, MColors.ENDC))
        f = open(asm_path, 'r')
        f.seek(asm_offset)
        gdb_print("=> %d : %s" % (asm_line, f.readline().rstrip()))
        gdb_print("   %d : %s" % (asm_line + 1, f.readline().rstrip()))
        gdb_print("   %d : %s" % (asm_line + 2, f.readline().rstrip()))
        f.close()
        m_util.gdb_exec('display')
Ejemplo n.º 13
0
 def get_array_length(self, addr):
     cmd = 'x/1xw ' + hex(addr)
     try:
         buffer = m_util.gdb_exec_to_str(cmd)
     except:
         return 0
     item_num = int(buffer.split(':')[1].strip(), 16)
     if m_debug.Debug: m_debug.dbg_print("item_num=", item_num)
     return item_num
Ejemplo n.º 14
0
def get_mbp_id():
    """ get a Maple breakpoint gdb.Breakpoint object id """
    blist = gdb.breakpoints()
    for b in blist:
        if m_debug.Debug:            m_debug.dbg_print("b.type=", b.type, "b.location=", b.location, "b.thread=", b.thread, "b.enabled=", b.enabled,\
          "b.is_valid()=", b.is_valid())
        if 'maple::maple_invoke_method' in b.location and b.is_valid():
            return b
    return None
Ejemplo n.º 15
0
def is_mbp_existed():
    """ determine where a Maple breakpoint exists """
    blist = gdb.breakpoints()
    for b in blist:
        if m_debug.Debug:            m_debug.dbg_print("b.type=", b.type, "b.location=", b.location, "b.thread=", b.thread, "b.enabled=", b.enabled,\
          "b.is_valid()=", b.is_valid())
        if 'maple::maple_invoke_method' in b.location and b.is_valid():
            return True, b
    return False, None
Ejemplo n.º 16
0
def get_prop_list_node_data(node_addr):
    # input: node_addr is the address of node, a pointer value to 'struct __jsprop'
    # output: return node data in dict format.
    # dict:
    # {'tag': 'JSTYPE_NUMBER'
    #  'ascii_name': 'var'
    #  'utf16_name : 'ㅶ'
    #  'next': 0x12323434
    #  'name_addr': 0x55555576d1a8
    #  'value':  6 (if tag JSTYPE_NUMBER)
    #         :  hello world (if tag = JSTYPE_STRING
    #         :  index (if tag = JSTYPE_OBJECT)
    #         :  None: if tag = JSTYPE_UNDEFINED or JSTYPE_NONE or JSTYPE_NULL
    #
    cmd = "p *(struct __jsprop *)" + node_addr
    if m_debug.Debug: m_debug.dbg_print("cmd=", cmd)
    buf = gdb.execute(cmd, to_string = True)
    buf = buf.rstrip()
    if m_debug.Debug: m_debug.dbg_print("get_prop_list_data buf=", buf)

    # example of output:
    # "$86 = {n = {index = 1433850280, name = 0x55555576d1a8}, next = 0x0, desc = {{named_data_property = {value = {asbits = 34359738368, s = {payload = {i32 = 0,u32 = 0, boo = 0, str = 0, obj = 0, ptr = 0}, tag = JSTYPE_UNDEFINED}}}, named_accessor_property = {get = 0x800000000, set = 0x0}}, {s = {attr_writable = 3 '\003', attr_enumerable = 3 '\003', attr_configurable = 2 '\002', fields = 0 '\000'}, attrs = 131843}}, isIndex = false}"
    if buf[0] != '$' or 'next = ' not in buf or 'desc = ' not in buf:
        return data
    prop_next = buf.split("next = ")[1].split(',')[0]
    prop_name_addr = buf.split("name = ")[1].split(',')[0][:-1]
    tag = buf.split("tag = ")[1].split('}}}')[0]

    if m_debug.Debug: m_debug.dbg_print("prop_next=", prop_next, "prop_name_addr=", prop_name_addr, "tag=", tag)
    ascii_name, utf16_name = get_prop_name_value(prop_name_addr)
    if m_debug.Debug: m_debug.dbg_print("ascii_name=", ascii_name, "utf16_name=", utf16_name)
    element = {}
    element['tag'] = tag
    element['ascii_name'] = ascii_name
    element['utf16_name'] = utf16_name
    element['next'] = prop_next
    element['name_addr'] = prop_name_addr


    if tag == 'JSTYPE_UNDEFINED' or tag == 'JSTYPE_NONE' or tag == 'JSTYPE_NULL':
        element['value'] = ""
    elif tag == 'JSTYPE_NUMBER':
        value = buf.split('payload = {i32 = ')[1].split(',')[0]
        element['value'] = value
    elif tag == 'JSTYPE_BOOLEAN':
        value = buf.split('boo = ')[1].split(',')[0]
        element['value'] = value
    elif tag == 'JSTYPE_STRING':
        index = buf.split('str = ')[1].split(',')[0]
        ascii_v, utf16_v = get_string_value_from_index(index)
        element['value'] = ascii_v
    else:
        element['value'] = ""

    if m_debug.Debug: m_debug.dbg_print("element=", element)
    return element
Ejemplo n.º 17
0
def get_msi_bp_dync_id():
    """ gets an msi breakpoint gdb.Breakpoint object id """
    blist = gdb.breakpoints()
    for b in blist:
        if m_debug.Debug:
            m_debug.dbg_print("b.type=", b.type, "b.location=", b.location, "b.thread=", \
                    b.thread, "b.enabled=", b.enabled, "b.is_valid()=", b.is_valid())
        if '__inc_opcode_cnt_dyn' == b.location and b.is_valid():
            return b
    return None
Ejemplo n.º 18
0
def is_msi_bp_dync_existed():
    """ determines if the msi breakpoints exist or not """
    blist = gdb.breakpoints()
    for b in blist:
        if m_debug.Debug:
            m_debug.dbg_print("b.type=", b.type, "b.location=", b.location, "b.thread=", \
                    b.thread, "b.enabled=", b.enabled, "b.is_valid()=", b.is_valid())
        if '__inc_opcode_cnt_dyn' == b.location and b.is_valid():
            return True, b
    return False, None
Ejemplo n.º 19
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 gdb 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
Ejemplo n.º 20
0
    def mfinish_func(self, args):
        frame = m_frame.get_newest_frame()
        if not frame:
            return
        silent_finish()

        frame = m_frame.get_selected_frame()
        if m_debug.Debug: m_debug.dbg_print("frame.name()=", frame.name())
        m_util.gdb_exec("msi")
        m_util.gdb_exec("mlist")
        m_datastore.mgdb_rdata.update_frame_change_counter()
Ejemplo n.º 21
0
    def create_mirmpl_info_cache(self, mirmpl_path):
        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")
Ejemplo n.º 22
0
    def create_mirbin_info_cache(self, asm_file):
        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")
Ejemplo n.º 23
0
    def display_array_primitive_values(self, addr, full_syntax, type_size):
        buffer = 'Object Type: {}'.format(MColors.MP_FSYNTAX + full_syntax +
                                          MColors.ENDC)
        gdb_print(buffer)
        item_num = self.get_array_length(addr)
        buffer = 'Level 1 {}: length={}'.format(
            MColors.MP_FSYNTAX + full_syntax + MColors.ENDC, item_num)
        gdb_print(buffer)

        if item_num > 10:
            item_list = [
                0, 1, 2, 3, 4, 5, 6, item_num - 3, item_num - 2, item_num - 1
            ]
        else:
            item_list = [i for i in range(item_num)]

        steps = 0
        show_snip = True
        for i in item_list:
            obj_addr = addr + 4 + type_size * i  # class reference is a pointer, 8 bytes
            if type_size == 8:
                cmd = 'x/1gx ' + hex(obj_addr)
            elif type_size == 4:
                cmd = 'x/1xw ' + hex(obj_addr)
            elif type_size == 2:
                cmd = 'x/1xh ' + hex(obj_addr)
            elif type_size == 1:
                cmd = 'x/1xb ' + hex(obj_addr)
            else:
                return
            if m_debug.Debug: m_debug.dbg_print("cmd=", cmd)
            try:
                buffer = m_util.gdb_exec_to_str(cmd)
            except:
                buf = '  [{}] {}'.format(i, 'no-data')
                gdb_print(buf)
                steps += 1
                continue

            steps += 1
            v = buffer.split(':')[1].strip()
            v = hex(int(v, 16))  #remove leading 0s. e.g. 0x000123 to 0x123
            if full_syntax == 'array C[]':  # display unicode character
                v = v + ", '" + int(v, 16).to_bytes(
                    2, byteorder='big').decode("utf-16-be") + "'"
            buf = '  [{}] {}'.format(i, v)
            gdb_print(buf)

            if item_num > 10 and steps > 6 and show_snip == True:
                gdb_print("  ...")
                show_snip = False

        return
Ejemplo n.º 24
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.gdb_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.gdb_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.gdb_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
Ejemplo n.º 25
0
def get_maple_frame_func_lib_info(frame):
    """
    for a given Maple frame, find and return function related frame information

    params:
      frame: a gdb.Frame object.

    returns:
      1, func_header_offset: in string.
      2, so_path: string. so library file full path.
      3, asm_path: string. asm file full path.
      4, func_header: int. address of function header.
      5, mirmpl_path: in string. .mpl.mir.mpl file full path
    """

    frame_rip = get_current_frame_rip(frame)
    buf = m_util.gdb_exec_to_str("info b")
    bp_addr, bp_info = m_breakpoint.get_maple_invoke_bp_stop_addr(buf)
    if m_debug.Debug:
        m_debug.dbg_print("frame_rip =", frame_rip, "bp_addr=", bp_addr)

    # if breakpoint address is not same to frame_rip (first instruction address of the frame),
    # this means program already passed first instruction of the function
    if bp_addr != frame_rip:
        func_addr_offset = m_info.get_initialized_maple_func_addrs()
        # func_addr_offset in string
        if not func_addr_offset:
            if m_debug.Debug: m_debug.dbg_print("func_addr_offset=None")
            return None, None, None, None, None
        func_header = m_info.get_initialized_maple_func_attr('func.header')
        start_addr, so_path, asm_path, mirmpl_path = m_info.get_lib_so_info(
            func_header)
        if m_debug.Debug:            m_debug.dbg_print("func_addr_offset=", func_addr_offset, "so_path=", so_path, \
                              "asm_path=", asm_path, "func_header=", func_header, "mirmpl_path=", mirmpl_path)
        return func_addr_offset, so_path, asm_path, func_header, mirmpl_path

    # the breakpoint address is same to frame.rip (first instruction address in the memory),
    # this means program just stops at the first instruction of the function, so the func is NOT
    # initialized yet
    func_addr_offset, so_path, asm_path, func_header, mirmpl_path = m_info.get_uninitialized_maple_func_addrs(
    )

    # func_addr_offset in string , format of func_addr:offset:
    if not func_addr_offset or not so_path or not asm_path or not func_header or not mirmpl_path:
        if m_debug.Debug:
            m_debug.dbg_print("func_addr_offset=", func_addr_offset,
                              "so_path=", so_path, "asm_path=", asm_path)
        if m_debug.Debug:
            m_debug.dbg_print("func_header=", func_header, "mirmpl_path=",
                              mirmpl_path)
        return None, None, None, None, None
    return func_addr_offset, so_path, asm_path, func_header, mirmpl_path
Ejemplo n.º 26
0
def get_mirheader_name_by_mirheader_addr(addr):
    cmd = 'x ' + addr
    try:
        result = m_util.gdb_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
Ejemplo n.º 27
0
    def mtype_func(self, args, from_tty):
        s = args.split()
        if len(s) == 0 or len(s) > 1:
            self.usage()
            return

        # create a re.recompile pattern
        reg = r"(%s)+" % s[0]
        pattern = re.compile(reg)

        # class_list is a sorted list that contains class names
        class_list = m_datastore.mgdb_rdata.get_class_def_list()
        if m_debug.Debug:
            m_debug.dbg_print("return class_list length:", len(class_list))
        if len(class_list) == 0:
            gdb_print("The class information table is not available yet")
            gdb_print(
                "Retry this after running Maple breakpoint and Maple stack commands"
            )
            return

        count = 0
        last_matching_class_name = None
        for class_name in class_list:
            m = pattern.search(class_name)
            if not m:
                continue
            count += 1
            buffer = '#{} class name: {}'.format(
                count, MColors.TP_CNAME + class_name + MColors.ENDC)
            gdb_print(buffer)
            last_matching_class_name = class_name

        if count > 1:
            return

        inheritance_list = self.get_class_inheritance_list(
            last_matching_class_name)
        if not inheritance_list:
            return
        if m_debug.Debug:
            m_debug.dbg_print("return inheritance_list length:",
                              len(inheritance_list))
        self.display_class_list(inheritance_list)

        gdb_print("\n  Method list:")
        updated_asm_path_list = get_updated_lib_asm_path_list()
        symbol = "^" + last_matching_class_name + "_7C"
        print_prefix = ""
        search_display_symbol_list(symbol, 4, print_prefix,
                                   updated_asm_path_list)
Ejemplo n.º 28
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)
    """

    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.gdb_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):
        gdb_print ("Warning: The header address is lower than lib_addr.")
        return None
    if (pc < header):
        gdb_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)+":"
Ejemplo n.º 29
0
def search_display_symbol_list(sym_regexp, indent, print_prefix,
                               asm_path_list):
    """
    search symbols using symb_regexp, print matching symbol name with given prefix.
    params:
      sym_regexp: string. regular expression for the symbol to be searched
      print_prefix: string. the prefix for print.
      asm_path_list: search with the asm paths in asm_path_list
      indent: int. number of space characters

    returns:
      count: number of matched symbol
      last_matchimg_symbol_name: string, or None if count = 0
      last_matching_symbol_path: string, or None if count = 0
    """

    # create a re.recompile pattern
    reg = r"(%s)+" % sym_regexp
    pattern = re.compile(reg)

    count = 0
    last_matching_symbol_name = None
    last_matching_symbol_path = None
    asm_path = None
    for asm_path in asm_path_list:
        # asm_symbol_list is a sorted list contains all the symbols from asm_path
        asm_symbol_list = m_datastore.mgdb_rdata.get_mirbin_cache_symbol_list(
            asm_path)
        if m_debug.Debug:
            m_debug.dbg_print("asm=", asm_path, ", len(asm_symbol_list)=",
                              len(asm_symbol_list))
        for symbol_name in asm_symbol_list:
            m = pattern.search(symbol_name)
            if not m:
                continue
            count += 1
            indent_str = ' ' * indent
            if print_prefix:
                buffer = '{}#{} {}: {}'.format(
                    indent_str, count, print_prefix,
                    m_util.color_symbol(MColors.SP_SNAME, symbol_name[:-12]))
            else:
                buffer = '{}#{} {}'.format(
                    indent_str, count,
                    m_util.color_symbol(MColors.TP_MNAME, symbol_name[:-12]))
            gdb_print(buffer)
            last_matching_symbol_name = symbol_name
            last_matching_symbol_path = asm_path

    return count, last_matching_symbol_name, last_matching_symbol_path
Ejemplo n.º 30
0
    def get_class_inheritance_list(self, class_name):
        inherit_list = []
        name = class_name
        count = 0
        while True:
            obj_class_dict = m_datastore.mgdb_rdata.get_class_def(name)
            if m_debug.Debug:
                m_debug.dbg_print("count=", count, "obj_class_dict=",
                                  obj_class_dict)
            if not obj_class_dict:
                return None
            inherit_list = [{
                'class_name': name,
                'obj_class': obj_class_dict
            }] + inherit_list
            count += 1
            if obj_class_dict['base_class'] == 'THIS_IS_ROOT':
                break
            else:
                name = obj_class_dict['base_class']

        if m_debug.Debug:
            m_debug.dbg_print("count=", count, "obj_class_dict=",
                              obj_class_dict)
        for i, v in enumerate(inherit_list):
            if m_debug.Debug: m_debug.dbg_print("  inherit_list #", i, v)
        if m_debug.Debug: m_debug.dbg_print()

        return inherit_list