Ejemplo n.º 1
0
    def __init__(self, main):
        super(RightTextView, self).__init__(False, 1)

        #################################################################
        # Right Textview
        #################################################################

        self.main = main
        self.uicore = self.main.uicore

        self.seek_index = 0
        self.seeks = []
        self.marks = []
        self.press_coords = []

        #################################################
        # Move buttons
        self.move_buttons = self.create_seek_buttons()
        self.pack_start(self.move_buttons, False, False, 1)

        self.hbox = Gtk.HBox(False, 0)

        self.buffer = GtkSource.Buffer()
        self.view = GtkSource.View.new_with_buffer(self.buffer)
        self.view.connect("button-press-event", self._get_press)
        self.view.connect("button-release-event", self._get_release)
        self.view.connect("key-release-event", self._cursor_moved)
        self.view.connect('motion-notify-event', self.call_tooltip)

        # FIXME options must be user selectable (statusbar)
        self.view.set_editable(False)
        self.view.set_highlight_current_line(True)
        # posible values: Gtk.WrapMode.NONE, Gtk.WrapMode.CHAR, Gtk.WrapMode.WORD...
        self.view.set_wrap_mode(Gtk.WrapMode.NONE)

        # setup view
        font_desc = Pango.FontDescription('monospace 9')
        if font_desc:
            self.view.modify_font(font_desc)

        self.buffer.set_highlight_syntax(True)
        if "ARM" in self.uicore.info.machine or "Thumb" in self.uicore.info.machine:
            language = self.main.lm.get_language('arm-asm')
        else:
            language = self.main.lm.get_language('asm')

        self.buffer.set_language(language)

        self.mgr = GtkSource.StyleSchemeManager.get_default()

        # Scrolled Window
        self.right_scrolled_window = Gtk.ScrolledWindow()
        self.right_scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
        self.right_scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
                                              Gtk.PolicyType.AUTOMATIC)
        self.right_scrolled_window.show()
        # Add Textview to Scrolled Window
        self.right_scrolled_window.add(self.view)
        self.hbox.pack_start(self.right_scrolled_window, True, True, 0)
        self.pack_start(self.hbox, True, True, 0)

        # Create the search widget
        Searchable.__init__(self, self.view, small=True)

        self.high_word = HighWord(self.view)

        # Used for code navigation on _search function
        self.match_start = None
        self.match_end = None
        self.search_string = ''

        self.view.connect("populate-popup", self._populate_comments_menu)
Ejemplo n.º 2
0
class RightTextView(Gtk.VBox, Searchable):
    '''Right TextView elements'''
    def __init__(self, main):
        super(RightTextView, self).__init__(False, 1)

        #################################################################
        # Right Textview
        #################################################################

        self.main = main
        self.uicore = self.main.uicore

        self.seek_index = 0
        self.seeks = []
        self.marks = []
        self.press_coords = []

        #################################################
        # Move buttons
        self.move_buttons = self.create_seek_buttons()
        self.pack_start(self.move_buttons, False, False, 1)

        self.hbox = Gtk.HBox(False, 0)

        self.buffer = GtkSource.Buffer()
        self.view = GtkSource.View.new_with_buffer(self.buffer)
        self.view.connect("button-press-event", self._get_press)
        self.view.connect("button-release-event", self._get_release)
        self.view.connect("key-release-event", self._cursor_moved)
        self.view.connect('motion-notify-event', self.call_tooltip)

        # FIXME options must be user selectable (statusbar)
        self.view.set_editable(False)
        self.view.set_highlight_current_line(True)
        # posible values: Gtk.WrapMode.NONE, Gtk.WrapMode.CHAR, Gtk.WrapMode.WORD...
        self.view.set_wrap_mode(Gtk.WrapMode.NONE)

        # setup view
        font_desc = Pango.FontDescription('monospace 9')
        if font_desc:
            self.view.modify_font(font_desc)

        self.buffer.set_highlight_syntax(True)
        if "ARM" in self.uicore.info.machine or "Thumb" in self.uicore.info.machine:
            language = self.main.lm.get_language('arm-asm')
        else:
            language = self.main.lm.get_language('asm')

        self.buffer.set_language(language)

        self.mgr = GtkSource.StyleSchemeManager.get_default()

        # Scrolled Window
        self.right_scrolled_window = Gtk.ScrolledWindow()
        self.right_scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
        self.right_scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
                                              Gtk.PolicyType.AUTOMATIC)
        self.right_scrolled_window.show()
        # Add Textview to Scrolled Window
        self.right_scrolled_window.add(self.view)
        self.hbox.pack_start(self.right_scrolled_window, True, True, 0)
        self.pack_start(self.hbox, True, True, 0)

        # Create the search widget
        Searchable.__init__(self, self.view, small=True)

        self.high_word = HighWord(self.view)

        # Used for code navigation on _search function
        self.match_start = None
        self.match_end = None
        self.search_string = ''

        self.view.connect("populate-popup", self._populate_comments_menu)

    def _cursor_moved(self, widget, event):
        cursor = self.buffer.get_iter_at_mark(self.buffer.get_insert())
        start = find_word_bound(cursor, -1, self.buffer)
        end = find_word_bound(cursor, +1, self.buffer)
        word = self.buffer.get_text(start, end, False)
        self.high_word._find(word)

    def do_seek(self, widget, direction):
        if self.seek_index <= 1 and direction == 'b':
            pass
        elif self.seek_index == len(self.seeks) and direction == 'f':
            pass
        else:
            if direction == 'b':
                self.seek_index -= 1
            elif direction == 'f':
                self.seek_index += 1

            self.marks = []

            mark = self.buffer.create_mark(None,
                                           self.seeks[self.seek_index - 1][0],
                                           False)
            self.view.scroll_to_mark(mark, 0.0, True, 0, 0.03)
            self.marks.append([
                self.seeks[self.seek_index - 1][0],
                self.seeks[self.seek_index - 1][1]
            ])

    def setup_sections_bar(self):
        # Setup sections bar
        # The check is used to avoid duplicated bars
        # when loading a new file from inside bokken
        if not hasattr(self, "sec_bar"):
            # MEOW
            #self.sec_bar = sections_bar.SectionsBar(self.uicore)
            self.hbox.pack_start(self.sec_bar, False, False, 0)
            self.sec_bar.show()
            vscrollbar = self.right_scrolled_window.get_vscrollbar()
            self.sec_bar.setup(vscrollbar)

    def _populate_comments_menu(self, textview, menu):
        '''Populates the context menu with the Comments item.'''
        # Get textbuffer coordinates from textview ones
        x, y = self.view.get_pointer()
        x, y = self.view.window_to_buffer_coords(Gtk.TextWindowType.WIDGET, x,
                                                 y)
        iter = self.view.get_line_at_y(y)[0]

        line = self.get_line_on_coords(x, y)

        opcodes = ui.opcodes.instructions
        for opcode in opcodes.keys():
            if opcode.split(' ')[0].lower() in line or opcode.split(
                    ' ')[0] in line:
                # Add a menu entry with opcode information
                opmenu = Gtk.Menu()

                opcodem = Gtk.ImageMenuItem((Gtk.STOCK_INFO))
                opcodem.set_submenu(opmenu)
                opcodem.get_children()[0].set_markup(
                    'Opcode info: <b>' + opcode.split(' ')[0].lower() + '</b>')

                opcode1 = Gtk.ImageMenuItem(Gtk.STOCK_EXECUTE)
                opcode_text = cgi.escape(opcode).lower()
                opcode1.get_children()[0].set_markup('<b>' + opcode_text +
                                                     '</b>')

                opcode2 = Gtk.MenuItem("")
                opcode2.get_children()[0].set_markup(
                    cgi.escape(opcodes[opcode]))

                opmenu.append(opcode1)
                opmenu.append(Gtk.SeparatorMenuItem())
                opmenu.append(opcode2)
                menu.prepend(opcodem)

        # Just show the comment menu if the line has offset/va
        match_address = re.match('\s+(0x[0-9a-z]+)\s', line)
        if match_address:
            addr = match_address.groups()[0]
            # Add comment menu
            opc = Gtk.ImageMenuItem((Gtk.STOCK_ADD))
            opc.get_children()[0].set_label('Add comment')
            menu.prepend(opc)
            opc.connect("activate", self._call_comments_dialog, iter, addr)

            # Add Xrefs menu
            refs = []
            xrefs = []

            xmenu = xrefs_menu.XrefsMenu(self.uicore, self.main)
            addr = self.uicore.core.num.get(addr)
            fcn = self.uicore.core.anal.get_fcn_in(addr, 0)

            if fcn:
                for ref in fcn.get_refs():
                    if not "0x%08x" % ref.addr in refs:
                        refs.append("0x%08x" % ref.addr)
                for xref in fcn.get_xrefs():
                    if not "0x%08x" % xref.addr in xrefs:
                        xrefs.append("0x%08x" % xref.addr)

                xmenu.create_menu("0x%08x" % addr, refs, xrefs, False)
                sep = Gtk.SeparatorMenuItem()
                menu.prepend(sep)
                if hasattr(xmenu, 'xfrommenu'):
                    menu.prepend(xmenu.xfrommenu)
                if hasattr(xmenu, 'xtomenu'):
                    menu.prepend(xmenu.xtomenu)
                menu.prepend(xmenu.fcnm)

        menu.show_all()

    def _call_comments_dialog(self, widget, iter, offset):
        dialog = comments_dialog.CommentsDialog()
        resp = dialog.run()
        if resp == Gtk.ResponseType.ACCEPT:
            start, end = dialog.input_buffer.get_bounds()
            comment = dialog.input_buffer.get_text(start, end)
            tainted_comment = comment.replace('\n', '\n  ; ')
            tainted_comment = '  ; ' + tainted_comment
            dialog.destroy()
            self.buffer.insert(iter, tainted_comment + '\n')
            self.uicore.add_comment(offset, comment)

    def set_completion(self):
        # Seek entry EntryCompletion
        self.completion = Gtk.EntryCompletion()
        self.liststore = Gtk.ListStore(str)
        # Add function names to the list
        for function in self.uicore.allfuncs:
            self.liststore.append([function])

        self.completion.set_model(self.liststore)
        self.seek.set_completion(self.completion)
        self.completion.set_text_column(0)

    def _get_press(self, widget, event):
        x, y = event.get_coords()
        self.press_coords = [x, y]

    def _get_release(self, widget, event):
        x, y = event.get_coords()
        if [x, y] == self.press_coords:
            self._get_clicked_word()

    def _get_clicked_word(self):
        # Get textbuffer coordinates from textview ones
        x, y = self.view.get_pointer()
        x, y = self.view.window_to_buffer_coords(Gtk.TextWindowType.WIDGET, x,
                                                 y)
        word = self.get_word_on_coords(x, y)
        self._search(word)
        self.high_word._find(word)

    def create_seek_buttons(self):
        self.hbox = Gtk.HBox(False, 1)

        self.back = Gtk.Button()
        self.back_img = Gtk.Image()
        self.back_img.set_from_stock(Gtk.STOCK_GO_BACK, Gtk.IconSize.MENU)
        self.back.set_image(self.back_img)
        self.back.set_relief(Gtk.ReliefStyle.NONE)
        self.back.connect('clicked', self.do_seek, 'b')

        self.forward = Gtk.Button()
        self.forward_img = Gtk.Image()
        self.forward_img.set_from_stock(Gtk.STOCK_GO_FORWARD,
                                        Gtk.IconSize.MENU)
        self.forward.set_image(self.forward_img)
        self.forward.set_relief(Gtk.ReliefStyle.NONE)
        self.forward.connect('clicked', self.do_seek, 'f')

        self.seek = Gtk.Entry()
        self.seek.set_max_length(30)
        self.seek.set_icon_from_stock(1, Gtk.STOCK_JUMP_TO)
        self.seek.set_activates_default(True)
        self.seek.connect("activate", self.goto)
        self.seek.connect("icon-press", self.goto)
        self.seek.set_icon_tooltip_text(1, 'Go')

        self.hbox.pack_start(self.back, False, False, 0)
        self.hbox.pack_start(self.forward, False, False, 0)
        self.hbox.pack_start(self.seek, True, True, 0)

        return self.hbox

    def goto(self, widget, icon_pos=None, event=None):
        text = self.seek.get_text()
        self._search(text)

    def call_tooltip(self, widget, event):
        x = int(event.x)
        y = int(event.y)
        x, y = self.view.window_to_buffer_coords(Gtk.TextWindowType.WIDGET, x,
                                                 y)
        search_string = self.get_word_on_coords(x, y)

        self.addr_tip = ''
        if search_string:
            # If it's an address, search lines beginning with it.
            if '[' in search_string:
                search_string = search_string.strip('[').strip(']')
            if '0x' in search_string[0:2]:
                integer = int(search_string, 16)
                hex_addr = "0x%08x" % integer
                self.addr_tip = hex_addr
            elif 'loc.' in search_string:
                self.addr_tip = "0x%08x" % self.uicore.core.num.get(
                    search_string)
            elif any(k in search_string
                     for k in ['fcn.', 'main', 'entry0', '_init', '_fini']):
                self.addr_tip = "0x%08x" % self.uicore.core.num.get(
                    search_string)
                self.dograph = True
            elif 'imp.' in search_string:
                self.addr_tip = "0x%08x" % self.uicore.core.num.get(
                    search_string)
            elif 'reloc.' in search_string:
                self.addr_tip = "0x%08x" % self.uicore.core.num.get(
                    search_string)
            elif 'str.' in search_string:
                # Not working until we add strings section into dasm
                #self.addr_tip = "0x%08x" % self.uicore.core.num.get(search_string)
                self.addr_tip = search_string
            elif 'sub_' in search_string:
                self.addr_tip = '0x' + search_string[4:]
            elif '.' in search_string:
                if '[' in search_string:
                    search_string = search_string.strip('[').strip(']')
                self.addr_tip = "0x%08x" % self.uicore.core.num.get(
                    search_string)
            else:
                pass

            if self.addr_tip:
                value = self.uicore.send_cmd_str('pdi 15 @ ' + self.addr_tip)
                widget.set_tooltip_markup("<span font_family=\"monospace\">" +
                                          value.rstrip() + "</span>")
            else:
                widget.set_tooltip_markup("")

    def _search(self, search_string, iter=None):

        self.dograph = False
        self.search_string = ''
        if search_string:
            # If it's an address, search lines beginning with it.
            if '[' in search_string:
                search_string = search_string.strip('[').strip(']')
            if '0x' in search_string[0:2]:
                integer = int(search_string, 16)
                hex_addr = "0x%08x" % integer
                self.search_string = hex_addr
            elif 'loc.' in search_string:
                self.search_string = "0x%08x" % self.uicore.core.num.get(
                    search_string)
            elif any(k in search_string
                     for k in ['fcn.', 'main', 'entry0', '_init', '_fini']):
                self.search_string = "0x%08x" % self.uicore.core.num.get(
                    search_string)
                self.dograph = True
            elif 'imp.' in search_string:
                self.search_string = "0x%08x" % self.uicore.core.num.get(
                    search_string)
            elif 'reloc.' in search_string:
                self.search_string = "0x%08x" % self.uicore.core.num.get(
                    search_string)
            elif 'str.' in search_string:
                # Not working until we add strings section into dasm
                #self.search_string = "0x%08x" % self.uicore.core.num.get(search_string)
                self.search_string = search_string
            elif 'sub_' in search_string:
                self.search_string = '0x' + search_string[4:]
            elif '.' in search_string:
                if '[' in search_string:
                    search_string = search_string.strip('[').strip(']')
                self.search_string = "0x%08x" % self.uicore.core.num.get(
                    search_string)
            else:
                pass

            if self.search_string:
                startIter = self.textbuf.get_start_iter()
                # find the positions where the phrase is found
                res = []
                while True:
                    result = startIter.forward_search(
                        self.search_string, Gtk.TextSearchFlags.TEXT_ONLY,
                        None)
                    if result:
                        res.append((result[0], result[1]))
                        startIter = result[1]
                    else:
                        break

                if res:
                    self.marks = []

                    for iter in res:
                        self.match_start, self.match_end = iter

                        if self.match_start:
                            self.buffer.place_cursor(self.match_start)
                            mark = self.buffer.create_mark(
                                None, self.match_start, False)
                            self.view.scroll_to_mark(mark, 0.0, True, 0, 0.03)
                            self.last_search_iter = self.match_end
                            self.marks.append(
                                [self.match_start, self.match_end])

                    # Update the browse history list.
                    # It may happen that the self.seeks list is still empty.
                    # Note: This entire code is pretty bad.  We should make a couple
                    # of functions to navigate the history and remove this clowntown
                    # code together with the do_seek() method.
                    if len(self.seeks
                           ) == 0 or self.match_start != self.seeks[-1]:
                        self.seeks.insert(self.seek_index,
                                          [self.match_start, self.match_end])
                        self.seek_index += 1
                        if len(self.seeks) != self.seek_index:
                            self.seeks = self.seeks[:self.seek_index]

                else:
                    self.search_string = None
                    self.last_search_iter = None
                self.main.tviews.update_graph(self, self.search_string)

    def get_line_on_coords(self, x, y):
        '''This function returns the entire line containing the coordinates
        (x,y) of a TextView.'''

        # Get textiter at coordinates.
        start_iter, _ = self.view.get_line_at_y(y)
        end_iter = start_iter.copy()
        end_iter.forward_line()
        t_buffer = start_iter.get_buffer()

        return t_buffer.get_text(start_iter, end_iter, False)

    def get_word_on_coords(self, x, y):
        '''This function returns the word surrounding the coordinates (x,y) of
        a TextView.  Very useful for clicking on words or doing tooltips.
        I tried to make this work with the Pango functions of the TextIter, but
        it happens that their idea of word separators doesn't correlate very
        well with ASM and r2 output. :o)'''
        def is_word_sep(x, garbage=None):
            word_separators = [' ', ',', '=', '\t', '\n', '(', ')']
            return x in word_separators

        def simple_backward_find_char(src_iter, callback):
            # We return False if we reach the end of the buffer.
            while src_iter.backward_char():
                if callback(src_iter.get_char()):
                    return True
            return False

        def simple_forward_find_char(src_iter, callback):
            # We return False if we reach the end of the buffer.
            while src_iter.forward_char():
                if callback(src_iter.get_char()):
                    return True
            return False

        while 1:
            # Get textiter at coordinates.
            start_iter = self.view.get_iter_at_location(x, y)
            end_iter = start_iter.copy()
            t_buffer = start_iter.get_buffer()
            if is_word_sep(start_iter.get_char()):
                break

            # The gunichar data type, used in backward_find_char(),
            # forward_find_char() et al, seem broken in GNOME 3.18 (#759276),
            # so we'll have to do it manually.
            #ret = start_iter.backward_find_char(is_word_sep)
            ret = simple_backward_find_char(start_iter, is_word_sep)

            # We went too far rewinding (off-by-one in fact), so let's forward one
            # character, unless ret is False, which means that we reached the start
            # of the buffer, in which case we won't do anything.
            if ret:
                start_iter.forward_char()
            #end_iter.forward_find_char(is_word_sep)
            simple_forward_find_char(end_iter, is_word_sep)
            break

        return t_buffer.get_text(start_iter, end_iter, True)
Ejemplo n.º 3
0
class RightTextView(gtk.VBox, Searchable):
    '''Right TextView elements'''

    def __init__(self, core, textviews, main):
        super(RightTextView,self).__init__(False, 1)

        #################################################################
        # Right Textview
        #################################################################

        self.uicore = core
        self.main = main
        self.textviews = textviews

        self.seek_index = 0
        self.seeks = []
        self.marks = []
        self.press_coords = []

        #################################################
        # Move buttons
        self.move_buttons = self.create_seek_buttons()
        self.pack_start(self.move_buttons, False, False, 1)

        self.hbox = gtk.HBox(False, 0)

        # Use GtkSourceView to add eye candy :P
        # create buffer
        lm = gtksourceview2.LanguageManager()
        # Add ui dir to language paths
        paths = lm.get_search_path()
        paths.append(os.path.dirname(__file__) + os.sep + 'data' + os.sep)
        lm.set_search_path(paths)
        self.buffer = gtksourceview2.Buffer()
        self.buffer.set_data('languages-manager', lm)
        self.view = gtksourceview2.View(self.buffer)
        self.view.connect("button-press-event", self._get_press)
        self.view.connect("button-release-event", self._get_release)
        self.view.connect("key-release-event", self._cursor_moved)
        tooltip_handle = self.view.connect('motion-notify-event', self.call_tooltip)

        # FIXME options must be user selectable (statusbar)
        self.view.set_editable(False)
        self.view.set_highlight_current_line(True)
        # posible values: gtk.WRAP_NONE, gtk.WRAP_CHAR, gtk.WRAP_WORD...
        self.view.set_wrap_mode(gtk.WRAP_NONE)

        # setup view
        font_desc = pango.FontDescription('monospace 9')
        if font_desc:
            self.view.modify_font(font_desc)

        self.buffer.set_highlight_syntax(True)
        manager = self.buffer.get_data('languages-manager')
        if "ARM" in self.uicore.info.machine or "Thumb" in self.uicore.info.machine:
            language = manager.get_language('arm-asm')
        else:
            language = manager.get_language('asm')

        self.buffer.set_language(language)

        self.mgr = gtksourceview2.style_scheme_manager_get_default()

        # Scrolled Window
        self.right_scrolled_window = gtk.ScrolledWindow()
        self.right_scrolled_window.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        self.right_scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.right_scrolled_window.show()
        # Add Textview to Scrolled Window
        self.right_scrolled_window.add(self.view)
        self.hbox.pack_start(self.right_scrolled_window, expand=True, fill=True)
        self.pack_start(self.hbox, expand=True, fill=True)

        # Create the search widget
        Searchable.__init__(self, self.view, small=True)

        self.high_word = HighWord(self.view)

        # Used for code navigation on _search function
        self.match_start = None
        self.match_end = None
        self.search_string = ''

        self.view.connect("populate-popup", self._populate_comments_menu)

    def _cursor_moved(self, widget, event):
        cursor = self.buffer.get_iter_at_mark(self.buffer.get_insert())
        start = find_word_bound(cursor, -1, self.buffer)
        end = find_word_bound(cursor, +1, self.buffer)
        word = self.buffer.get_text(start, end, False)
        self.high_word._find(word)

    def do_seek(self, widget, direction):
        if self.seek_index <= 1 and direction == 'b':
            pass
        elif self.seek_index == len(self.seeks) and direction == 'f':
            pass
        else:
            if direction == 'b':
                self.seek_index -= 1
            elif direction == 'f':
                self.seek_index += 1

            self.marks = []

            mark = self.buffer.create_mark(None, self.seeks[self.seek_index-1][0], False)
            self.view.scroll_to_mark(mark, 0.0, True, 0, 0.03)
            self.marks.append([self.seeks[self.seek_index-1][0], self.seeks[self.seek_index-1][1]])

    def setup_sections_bar(self):
        # Setup sections bar
        # The check is used to avoid duplicated bars
        # when loading a new file from inside bokken
        if not hasattr(self,"sec_bar"):
            self.sec_bar = sections_bar.SectionsBar(self.uicore)
            self.hbox.pack_start(self.sec_bar, False, False, 0)
            self.sec_bar.show()
            vscrollbar = self.right_scrolled_window.get_vscrollbar()
            self.sec_bar.setup(vscrollbar)

    def _populate_comments_menu(self, textview, menu):
        '''Populates the context menu with the Comments item.'''
        # Get textbuffer coordinates from textview ones
        x, y = self.view.get_pointer()
        x, y = self.view.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, x, y)
        iter = self.view.get_line_at_y(y)[0]

        line = self.get_line_on_coords(x, y)

        for opcode in instructions.keys():
            if opcode.split(' ')[0].lower() in line or opcode.split(' ')[0] in line:
                # Add a menu entry with opcode information
                opmenu = gtk.Menu()

                opcodem = gtk.ImageMenuItem((gtk.STOCK_INFO))
                opcodem.set_submenu(opmenu)
                opcodem.get_children()[0].set_markup('Opcode info: <b>' + opcode.split(' ')[0].lower() + '</b>')

                opcode1 = gtk.ImageMenuItem(gtk.STOCK_EXECUTE)
                opcode_text = opcode.replace('<', '"').replace('>', '"').lower()
                opcode1.get_children()[0].set_markup('<b>' + opcode_text + '</b>')

                opcode2 = gtk.MenuItem("")
                opcode2.get_children()[0].set_markup(instructions[opcode].replace('<', '"').replace('>', '"'))

                opmenu.append(opcode1)
                opmenu.append(gtk.SeparatorMenuItem())
                opmenu.append(opcode2)
                menu.prepend(opcodem)

        # Just show the comment menu if the line has offset/va
        match_address = re.match('\s+(0x[0-9a-z]+)\s', line)
        if match_address:
            addr = match_address.groups()[0]
            # Add comment menu
            opc = gtk.ImageMenuItem((gtk.STOCK_ADD))
            opc.get_children()[0].set_label('Add comment')
            menu.prepend(opc)
            opc.connect("activate", self._call_comments_dialog, iter, addr)

            # Add Xrefs menu
            refs = []
            xrefs = []

            xmenu = xrefs_menu.XrefsMenu(self.uicore, self.main)
            addr = self.uicore.core.num.get(addr)
            fcn = self.uicore.core.anal.get_fcn_in(addr, 0)

            if fcn:
                for ref in fcn.get_refs():
                    if not "0x%08x" % ref.addr in refs:
                        refs.append("0x%08x" % ref.addr)
                for xref in fcn.get_xrefs():
                    if not "0x%08x" % xref.addr in xrefs:
                        xrefs.append("0x%08x" % xref.addr)

                refs_menu = xmenu.create_menu("0x%08x" % addr, refs, xrefs, False)
                sep = gtk.SeparatorMenuItem()
                menu.prepend(sep)
                if hasattr(xmenu, 'xfrommenu'):
                    menu.prepend(xmenu.xfrommenu)
                if hasattr(xmenu, 'xtomenu'):
                    menu.prepend(xmenu.xtomenu)
                menu.prepend(xmenu.fcnm)

        menu.show_all()

    def _call_comments_dialog(self, widget, iter, offset):
        dialog = comments_dialog.CommentsDialog()
        resp = dialog.run()
        if resp == gtk.RESPONSE_ACCEPT:
            start, end = dialog.input_buffer.get_bounds()
            comment = dialog.input_buffer.get_text(start, end)
            tainted_comment = comment.replace('\n', '\n  ; ')
            tainted_comment = '  ; ' + tainted_comment
            dialog.destroy()
            self.buffer.insert(iter, tainted_comment + '\n')
            self.uicore.add_comment(offset, comment)

    def set_completion(self):
        # Seek entry EntryCompletion
        self.completion = gtk.EntryCompletion()
        self.liststore = gtk.ListStore(str)
        # Add function names to the list
        for function in self.uicore.allfuncs:
            self.liststore.append([function])

        self.completion.set_model(self.liststore)
        self.seek.set_completion(self.completion)
        self.completion.set_text_column(0)

    def _get_press(self, widget, event):
        x, y = event.get_coords()
        self.press_coords = [x, y]

    def _get_release(self, widget, event):
        x, y = event.get_coords()
        if [x, y] == self.press_coords:
            self._get_clicked_word()

    def _get_clicked_word(self):
        # Get textbuffer coordinates from textview ones
        x, y = self.view.get_pointer()
        x, y = self.view.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, x, y)
        word = self.get_word_on_coords(x, y)
        self._search(word)
        self.high_word._find(word)

    def create_seek_buttons(self):
        self.hbox = gtk.HBox(False, 1)

        self.back = gtk.Button()
        self.back_img = gtk.Image()
        self.back_img.set_from_stock(gtk.STOCK_GO_BACK, gtk.ICON_SIZE_MENU)
        self.back.set_image(self.back_img)
        self.back.set_relief(gtk.RELIEF_NONE)
        self.back.connect('clicked', self.do_seek, 'b')

        self.forward = gtk.Button()
        self.forward_img = gtk.Image()
        self.forward_img.set_from_stock(gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_MENU)
        self.forward.set_image(self.forward_img)
        self.forward.set_relief(gtk.RELIEF_NONE)
        self.forward.connect('clicked', self.do_seek, 'f')

        self.seek = gtk.Entry(30)
        self.seek.set_icon_from_stock(1, gtk.STOCK_JUMP_TO)
        self.seek.set_activates_default(True)
        self.seek.connect("activate", self.goto)
        self.seek.connect("icon-press", self.goto)
        self.seek.set_icon_tooltip_text(1, 'Go')

        self.hbox.pack_start(self.back, False, False)
        self.hbox.pack_start(self.forward, False, False)
        self.hbox.pack_start(self.seek, True, True)

        return self.hbox

    def goto(self, widget, icon_pos=None, event=None):
        text = self.seek.get_text()
        self._search(text)

    def call_tooltip(self, widget, event):
        x = int(event.x)
        y = int(event.y)
        x, y = self.view.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, x, y)
        search_string = self.get_word_on_coords(x,y)

        self.addr_tip =''
        if search_string:
            # If it's an address, search lines beginning with it.
            if '[' in search_string:
                search_string = search_string.strip('[').strip(']')
            if '0x' in search_string[0:2]:
                integer = int(search_string, 16)
                hex_addr = "0x%08x" % integer
                self.addr_tip = hex_addr
            elif 'loc.' in search_string:
                self.addr_tip = "0x%08x" % self.uicore.core.num.get(search_string)
            elif any( k in search_string for k in ['fcn.', 'main', 'entry0', '_init', '_fini'] ):
                self.addr_tip = "0x%08x" % self.uicore.core.num.get(search_string)
                self.dograph = True
            elif 'imp.' in search_string:
                self.addr_tip = "0x%08x" % self.uicore.core.num.get(search_string)
            elif 'reloc.' in search_string:
                self.addr_tip = "0x%08x" % self.uicore.core.num.get(search_string)
            elif 'str.' in search_string:
                # Not working until we add strings section into dasm
                #self.addr_tip = "0x%08x" % self.uicore.core.num.get(search_string)
                self.addr_tip = search_string
            elif 'sub_' in search_string:
                self.addr_tip = '0x' + search_string[4:]
            elif '.' in search_string:
                if '[' in search_string:
                    search_string = search_string.strip('[').strip(']')
                self.addr_tip = "0x%08x" % self.uicore.core.num.get(search_string)
            else:
                pass

            if self.addr_tip:
                value = self.uicore.send_cmd_str('pdi 15 @ ' + self.addr_tip)
                widget.set_tooltip_markup("<span font_family=\"monospace\">" + value.rstrip() + "</span>")
            else:
                widget.set_tooltip_markup("")

    def _search(self, search_string, iter = None):

        self.dograph = False
        self.search_string = ''
        if search_string:
            # If it's an address, search lines beginning with it.
            if '[' in search_string:
                search_string = search_string.strip('[').strip(']')
            if '0x' in search_string[0:2]:
                integer = int(search_string, 16)
                hex_addr = "0x%08x" % integer
                self.search_string = hex_addr
            elif 'loc.' in search_string:
                self.search_string = "0x%08x" % self.uicore.core.num.get(search_string)
            elif any( k in search_string for k in ['fcn.', 'main', 'entry0', '_init', '_fini'] ):
                self.search_string = "0x%08x" % self.uicore.core.num.get(search_string)
                self.dograph = True
            elif 'imp.' in search_string:
                self.search_string = "0x%08x" % self.uicore.core.num.get(search_string)
            elif 'reloc.' in search_string:
                self.search_string = "0x%08x" % self.uicore.core.num.get(search_string)
            elif 'str.' in search_string:
                # Not working until we add strings section into dasm
                #self.search_string = "0x%08x" % self.uicore.core.num.get(search_string)
                self.search_string = search_string
            elif 'sub_' in search_string:
                self.search_string = '0x' + search_string[4:]
            elif '.' in search_string:
                if '[' in search_string:
                    search_string = search_string.strip('[').strip(']')
                self.search_string = "0x%08x" % self.uicore.core.num.get(search_string)
            else:
                pass

            if self.search_string:
                startIter =  self.textbuf.get_start_iter()
                # find the positions where the phrase is found
                res = []
                while True:
                    result = startIter.forward_search(self.search_string, gtk.TEXT_SEARCH_TEXT_ONLY, None)
                    if result:
                        res.append((result[0], result[1]))
                        startIter = result[1]
                    else:
                        break

                if res:
                    self.marks = []

                    for iter in res:
                        self.match_start, self.match_end = iter

                        if self.match_start:
                            self.buffer.place_cursor(self.match_start)
                            mark = self.buffer.create_mark(None, self.match_start, False)
                            self.view.scroll_to_mark(mark, 0.0, True, 0, 0.03)
                            self.last_search_iter = self.match_end
                            self.marks.append([self.match_start, self.match_end])

                    # Update the browse history list.
                    # It may happen that the self.seeks list is still empty.
                    # Note: This entire code is pretty bad.  We should make a couple
                    # of functions to navigate the history and remove this clowntown
                    # code together with the do_seek() method.
                    if len(self.seeks) == 0 or self.match_start != self.seeks[-1]:
                        self.seeks.insert(self.seek_index, [self.match_start, self.match_end])
                        self.seek_index += 1
                        if len(self.seeks) != self.seek_index:
                            self.seeks = self.seeks[:self.seek_index]

                else:
                    self.search_string = None
                    self.last_search_iter = None
                self.textviews.update_graph(self, self.search_string)

    def get_line_on_coords(self, x, y):
        '''This function returns the entire line containing the coordinates
        (x,y) of a TextView.'''

        # Get textiter at coordinates.
        start_iter, _ = self.view.get_line_at_y(y)
        end_iter = start_iter.copy()
        end_iter.forward_line()
        t_buffer = start_iter.get_buffer()

        return t_buffer.get_text(start_iter, end_iter)

    def get_word_on_coords(self, x, y):
        '''This function returns the word surrounding the coordinates (x,y) of
        a TextView.  Very useful for clicking on words or doing tooltips.
        I tried to make this work with the Pango functions of the TextIter, but
        it happens that their idea of word separators doesn't correlate very
        well with ASM and r2 output. :o)'''

        def is_word_sep(x, bogus):
            word_separators = [' ', ',', '\t', '\n', '(', ')']
            return x in word_separators

        # Get textiter at coordinates.
        start_iter = self.view.get_iter_at_location(x, y)
        end_iter = start_iter.copy()
        t_buffer = start_iter.get_buffer()

        ret = start_iter.backward_find_char(is_word_sep)
        # We went too far rewinding (off-by-one in fact), so let's forward one
        # character, unless ret is False, which means that we reached the start
        # of the buffer, in which case we won't do anything.
        if ret:
            start_iter.forward_char()
        end_iter.forward_find_char(is_word_sep)

        return t_buffer.get_text(start_iter, end_iter)
Ejemplo n.º 4
0
    def __init__(self, core, textviews, main):
        super(RightTextView,self).__init__(False, 1)

        #################################################################
        # Right Textview
        #################################################################

        self.uicore = core
        self.main = main
        self.textviews = textviews

        self.seek_index = 0
        self.seeks = []
        self.marks = []
        self.press_coords = []

        #################################################
        # Move buttons
        self.move_buttons = self.create_seek_buttons()
        self.pack_start(self.move_buttons, False, False, 1)

        self.hbox = gtk.HBox(False, 0)

        # Use GtkSourceView to add eye candy :P
        # create buffer
        lm = gtksourceview2.LanguageManager()
        # Add ui dir to language paths
        paths = lm.get_search_path()
        paths.append(os.path.dirname(__file__) + os.sep + 'data' + os.sep)
        lm.set_search_path(paths)
        self.buffer = gtksourceview2.Buffer()
        self.buffer.set_data('languages-manager', lm)
        self.view = gtksourceview2.View(self.buffer)
        self.view.connect("button-press-event", self._get_press)
        self.view.connect("button-release-event", self._get_release)
        self.view.connect("key-release-event", self._cursor_moved)
        tooltip_handle = self.view.connect('motion-notify-event', self.call_tooltip)

        # FIXME options must be user selectable (statusbar)
        self.view.set_editable(False)
        self.view.set_highlight_current_line(True)
        # posible values: gtk.WRAP_NONE, gtk.WRAP_CHAR, gtk.WRAP_WORD...
        self.view.set_wrap_mode(gtk.WRAP_NONE)

        # setup view
        font_desc = pango.FontDescription('monospace 9')
        if font_desc:
            self.view.modify_font(font_desc)

        self.buffer.set_highlight_syntax(True)
        manager = self.buffer.get_data('languages-manager')
        if "ARM" in self.uicore.info.machine or "Thumb" in self.uicore.info.machine:
            language = manager.get_language('arm-asm')
        else:
            language = manager.get_language('asm')

        self.buffer.set_language(language)

        self.mgr = gtksourceview2.style_scheme_manager_get_default()

        # Scrolled Window
        self.right_scrolled_window = gtk.ScrolledWindow()
        self.right_scrolled_window.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        self.right_scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.right_scrolled_window.show()
        # Add Textview to Scrolled Window
        self.right_scrolled_window.add(self.view)
        self.hbox.pack_start(self.right_scrolled_window, expand=True, fill=True)
        self.pack_start(self.hbox, expand=True, fill=True)

        # Create the search widget
        Searchable.__init__(self, self.view, small=True)

        self.high_word = HighWord(self.view)

        # Used for code navigation on _search function
        self.match_start = None
        self.match_end = None
        self.search_string = ''

        self.view.connect("populate-popup", self._populate_comments_menu)
Ejemplo n.º 5
0
    def __init__(self, main):
        super(RightTextView, self).__init__(False, 1)

        #################################################################
        # Right Textview
        #################################################################

        self.main = main
        self.uicore = self.main.uicore

        self.seek_index = 0
        self.seeks = []
        self.marks = []
        self.press_coords = []

        #################################################
        # Move buttons
        self.move_buttons = self.create_seek_buttons()
        self.pack_start(self.move_buttons, False, False, 1)

        self.hbox = Gtk.HBox(False, 0)

        self.buffer = GtkSource.Buffer()
        self.view = GtkSource.View.new_with_buffer(self.buffer)
        self.view.connect("button-press-event", self._get_press)
        self.view.connect("button-release-event", self._get_release)
        self.view.connect("key-release-event", self._cursor_moved)
        self.view.connect('motion-notify-event', self.call_tooltip)

        # FIXME options must be user selectable (statusbar)
        self.view.set_editable(False)
        self.view.set_highlight_current_line(True)
        # posible values: Gtk.WrapMode.NONE, Gtk.WrapMode.CHAR, Gtk.WrapMode.WORD...
        self.view.set_wrap_mode(Gtk.WrapMode.NONE)

        # setup view
        font_desc = Pango.FontDescription('monospace 9')
        if font_desc:
            self.view.modify_font(font_desc)

        self.buffer.set_highlight_syntax(True)
        if "ARM" in self.uicore.info.machine or "Thumb" in self.uicore.info.machine:
            language = self.main.lm.get_language('arm-asm')
        else:
            language = self.main.lm.get_language('asm')

        self.buffer.set_language(language)

        self.mgr = GtkSource.StyleSchemeManager.get_default()

        # Scrolled Window
        self.right_scrolled_window = Gtk.ScrolledWindow()
        self.right_scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
        self.right_scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        self.right_scrolled_window.show()
        # Add Textview to Scrolled Window
        self.right_scrolled_window.add(self.view)
        self.hbox.pack_start(self.right_scrolled_window, True, True, 0)
        self.pack_start(self.hbox, True, True, 0)

        # Create the search widget
        Searchable.__init__(self, self.view, small=True)

        self.high_word = HighWord(self.view)

        # Used for code navigation on _search function
        self.match_start = None
        self.match_end = None
        self.search_string = ''

        self.view.connect("populate-popup", self._populate_comments_menu)