Exemple #1
0
 def clear_database(self):
     if ask_yes_no(
             'Are you really sure that you want to clear the Classy databse?\n',
             False):
         database.get().clear()
         self.gui.update_fields()
         idaapi.refresh_idaview_anyway()
Exemple #2
0
    def s_create():
        db = database.get()

        name = idaapi.ask_str('', idaapi.HIST_IDENT,'Enter a class name')

        if name is None:
            return None

        if name in database.get().classes_by_name:
            idaapi.warning('That name is already used.')
            return None

        if not Class.s_name_is_valid(name):
            idaapi.warning('The class name "%s" is invalid.' % name)
            return None

        base_class = None
        base_name = idaapi.ask_str('', idaapi.HIST_IDENT,'Enter a base class name (leave empty for none)')
        if base_name is None:
            return None
        if base_name:
            if base_name not in db.classes_by_name:
                idaapi.warning('The class "%s" is not in the database.' % base_name)
                return None
            else:
                base_class = db.classes_by_name[base_name]
                if not base_class.can_be_derived():
                    idaapi.warning('The class %s cannot be derived because the VTable is not setup correctly' % base_class.name)
                    return None

        return Class(name, base_class)

        '''
Exemple #3
0
    def handle_set_struct(self):
        if self.edit_class is None:
            return

        default_struct_name = idc.get_struc_name(self.edit_class.struct_id)    \
                              if self.edit_class.struct_id != idc.BADADDR else \
                              self.edit_class.name

        dlg = ChooseStructDialog(default_struct_name, has_none_btn=True)
        if dlg.exec_() != QtWidgets.QDialog.Accepted:
            return

        if dlg.struct_id == self.edit_class.struct_id:
            return

        db = database.get()
        if dlg.struct_id in db.classes_by_struct_id:
            idaapi.warning(
                'The struct "%s" is already linked to the class "%s"' %
                (idc.get_struc_name(
                    dlg.struct_id), b.classes_by_struct_id[dlg.struct_id]))
            return

        delete_orphaned = False
        if self.edit_class.struct_id != idc.BADADDR:
            delete_orphaned = util.ask_yes_no(
                'Do you want to delete the orphaned class', False)

        self.edit_class.set_struct_id(dlg.struct_id, delete_orphaned)
        self.update_fields()
Exemple #4
0
    def reload_tree(self):
        db = database.get()

        self.items_by_class = {}
        self.class_tree.clear()
        for c in db.root_classes:
            self.add_child_class_item(self.class_tree, c)
Exemple #5
0
    def rename(self, new_name):
        old_name = self.name

        db = database.get()
        del db.classes_by_name[old_name]
        db.classes_by_name[new_name] = self

        self.name = new_name

        # Try to rename the struct
        if self.struct_id != idc.BADADDR:
            struct_name = idc.get_struc_name(self.struct_id)
            if struct_name == Class.s_safe_name(old_name):
                idc.set_struc_name(self.struct_id, self.safe_name())

        # Rename ctors and dtors
        for vm in self.vmethods:
            if vm.name == old_name:
                vm.name = new_name
            if vm.name == '~' + old_name:
                vm.name = '~' + new_name
        for m in self.methods:
            if m.name == old_name:
                m.name = new_name
            if m.name == '~' + old_name:
                m.name = '~' + new_name

        self.refresh()
Exemple #6
0
    def set_autosave_interval(self):
        db = database.get()

        new_interval, ok_pressed = QtWidgets.QInputDialog.getInt(
            None, 'Set autosave interval', 'Autosave interval [seconds]:',
            db.autosave_interval, 10)
        if ok_pressed:
            db.set_autosave_interval(new_interval)
Exemple #7
0
    def handle_remove(self):
        item = self.list.currentItem()
        if item is None:
            return

        t = item.data(QtCore.Qt.UserRole)
        del database.get().typedefs[t]

        self.update_list()
Exemple #8
0
    def update_list(self):
        db = database.get()

        self.list.clear()
        for t in db.typedefs:
            item = QtWidgets.QListWidgetItem('typedef %s %s;' %
                                             (db.typedefs[t], t))
            item.setData(QtCore.Qt.UserRole, t)
            self.list.addItem(item)
Exemple #9
0
    def export_all_symbols(self):
        path = QtWidgets.QFileDialog.getSaveFileName(
            None, 'Export all symbols', '',
            'Linker script (*.ld);;All files (*)')
        if not path[0]:
            return

        f = open(path[0], 'w')
        f.write(database.get().generate_symbols())
        f.close()
Exemple #10
0
 def set_signature(self, name, args, return_type='void', is_const=False, ctor_type=1, dtor_type=1):
     signature = Method.s_make_signature(self.owner, name, args, is_const, return_type)
     itanium_mangler.mangle_function(signature, database.get().typedefs, ctor_type, dtor_type)    # throws excption when invalid
     self.name = name
     self.args = args
     self.return_type = return_type
     self.is_const = is_const
     self.ctor_type = ctor_type
     self.dtor_type = dtor_type
     self.refresh()
Exemple #11
0
    def unlink(self):
        if self.owner and self in self.owner.methods:
            self.owner.methods.remove(self)

        self.owner = None

        if self.ea != idc.BADADDR:
            del database.get().known_methods[self.ea]
            idc.set_name(self.ea, '', idc.SN_CHECK)
            idc.set_func_cmt(self.ea, '', False)
Exemple #12
0
    def update_signature(self):
        self.return_type = self.return_type_w.text().encode(
            'ascii', 'replace').strip().decode() or 'void'
        self.owner_type = self.owner_type_w.text().encode(
            'ascii', 'replace').strip().decode()
        self.name = self.name_w.text().encode('ascii',
                                              'replace').strip().decode()
        self.args = self.args_w.text().encode('ascii',
                                              'replace').strip().decode()
        self.is_const = self.is_const_w.isChecked()
        self.ctor_type = self.ctor_type_w.currentIndex() + 1
        self.dtor_type = self.dtor_type_w.currentIndex()

        # ctors and dtors shouldn't have a return type, dtors shouldn't have args
        if self.owner_type:
            owner_last_type = self.owner_type.split('::')[-1]
            if self.name == owner_last_type:
                self.return_type = ''
            elif self.name == '~' + owner_last_type:
                self.return_type = ''
                self.args = ''

        signature_segs = []
        if self.return_type:
            signature_segs.append(self.return_type)
            signature_segs.append(' ')
        if self.owner_type:
            signature_segs.append(self.owner_type)
            signature_segs.append('::')
        signature_segs.append(self.name)
        signature_segs.append('(')
        signature_segs.append(self.args)
        signature_segs.append(')')
        if self.is_const:
            signature_segs.append(' const')
        self.signature = ''.join(signature_segs)
        self.signature_w.setText(self.signature)

        self.is_signature_valid = False
        self.mangled = None
        try:
            if not self.name or (' ' in self.name):
                raise ValueError('Name is invalid')
            self.mangled = itanium_mangler.mangle_function(
                self.signature,
                database.get().typedefs, self.ctor_type, self.dtor_type)
            self.is_signature_valid = True
            self.status = ''
            self.status_w.setText('Valid')
        except (ValueError, NotImplementedError) as e:
            self.status = str(e)
            self.status_w.setText('Invalid: ' + self.status)
        self.mangled_w.setText(str(self.mangled))
Exemple #13
0
    def __init__(self, ea, owner, name):
        self.ea = ea
        self.owner = owner
        self.name = name
        self.args = ''
        self.return_type = 'void'
        self.is_const = False
        self.ctor_type = 1
        self.dtor_type = 1

        if ea != idc.BADADDR:
            database.get().known_methods[ea] = self
Exemple #14
0
    def create_open_database(self):
        db = database.get()

        try:
            db.open()
        except Exception as e:
            idaapi.warning('Creating/opening Classy database failed: %s' %
                           str(e))

        if db.is_open:
            self.menumgr.set_state(MenuState.DATABASE_OPENED)
        else:
            self.menumgr.set_state(MenuState.DATABASE_CLOSED)
Exemple #15
0
    def unlink_struct(self, delete_orphaned=False):
        if self.struct_id == idc.BADADDR:
            return

        del database.get().classes_by_struct_id[self.struct_id]

        if delete_orphaned:
            idc.del_struc(self.struct_id)
        else:
            struct_name = idc.get_struc_name(self.struct_id)
            idc.set_struc_cmt(self.struct_id, 'Orphaned from %s' % self.name, False)
            idc.set_struc_name(self.struct_id, '%s_orphaned' % struct_name)

        self.struct_id = idc.BADADDR
Exemple #16
0
    def try_set_typedef(self, t):
        val = idaapi.ask_str('', idaapi.HIST_IDENT, 'Enter typedef value')
        if val is None:
            return

        val_segs = val.split()
        itanium_mangler.fix_multi_seg_types(val_segs)
        if len(val_segs) != 1 or (
                val_segs[0] not in itanium_mangler.BUILTIN_TYPES
                and not itanium_mangler.check_identifier(val_segs[0])):
            idaapi.warning('That value is invalid.')
            return

        database.get().typedefs[t] = val.strip()
        self.update_list()
Exemple #17
0
    def save_as(self):
        db = database.get()

        path = QtWidgets.QFileDialog.getSaveFileName(
            None, 'Export Classy database', '', 'Classy database (*.cdb)')
        if not path[0]:
            return

        # Check for user idiocy
        if os.path.normpath(path[0]) == os.path.normpath(db.path):
            idaapi.warning(
                'You cannot overwrite the currently active Classy database.')
            return

        db.save_as(path[0])
Exemple #18
0
    def set_struct_id(self, new_struct_id, delete_orphaned=False):
        db = database.get()

        if self.struct_id == new_struct_id:
            return

        if new_struct_id in db.classes_by_struct_id:
            raise ValueError('The struct is already assigned to the class %s' % db.classes_by_struct_id[new_struct_id]).name

        self.unlink_struct(delete_orphaned)

        self.struct_id = new_struct_id
        if self.struct_id != idc.BADADDR:
            db.classes_by_struct_id[self.struct_id] = self

        self.refresh()
Exemple #19
0
    def handle_add(self):
        t = idaapi.ask_str('', idaapi.HIST_IDENT, 'Enter typedef name')
        if t is None:
            return

        if t in database.get().typedefs:
            idaapi.warning('That name is already used.')
            return

        if not itanium_mangler.check_identifier(t):
            idaapi.warning('That name is invalid.')
            return

        # Todo: prevent overwriting builtins

        self.try_set_typedef(t)
Exemple #20
0
    def term(self):
        try:
            db = database.get()

            if db.is_open and ask_yes_no(
                    'Do you want to save the classy database?', True):
                db.save()
            db.close()

            database.destroy_instance()

        except ValueError:  # Database instance might not be created
            pass

        self.menumgr.cleanup()

        log('Unloaded')
Exemple #21
0
    def handle_remove_method(self):
        db = database.get()

        if self.edit_class is None:
            return

        row_item = self.methods.item(self.methods.currentRow(), 0)
        if row_item is None:
            return

        m = row_item.data(QtCore.Qt.UserRole)
        if type(
                m
        ) != database_entries.Method or m not in self.edit_class.methods:
            return

        m.unlink()

        self.update_fields()
Exemple #22
0
    def unlink(self, delete_orphaned_struct=False):
        if len(self.derived) > 0:
            raise ValueError('Cannot unlink classes with derived classes')

        for m in self.methods:
            m.unlink()

        for vm in self.vmethods:
            if vm.owner == self:
                vm.unlink()

        self.unlink_struct(delete_orphaned_struct)

        if self.base is not None:
            self.base.derived.remove(self)

        db = database.get()
        del db.classes_by_name[self.name]
        if self.base is None:
            db.root_classes.remove(self)
Exemple #23
0
    def handle_set_name(self):
        if self.edit_class is None:
            return

        new_name = idaapi.ask_str(self.edit_class.name, idaapi.HIST_IDENT,
                                  'Enter a class name')
        if new_name is None or new_name == self.edit_class.name:
            return

        if new_name in database.get().classes_by_name:
            idaapi.warning('That name is already used.')
            return

        if not database_entries.Class.s_name_is_valid(new_name):
            idaapi.warning('The class name "%s" is invalid.' % new_name)
            return

        self.edit_class.rename(new_name)
        self.update_fields()
        self.parent_gui.update_class(self.edit_class)
Exemple #24
0
    def edit_deleted_virtual_vals(self):
        db = database.get()

        txt = idaapi.ask_str(
            ', '.join([('0x%X' % x) for x in db.deleted_virtual_vals]),
            idaapi.HIST_IDENT, "Enter deleted virtual values")
        if txt is None or not txt.strip():
            return

        new_deleted_virtual_vals = []

        for s in txt.split(','):
            try:
                new_deleted_virtual_vals.append(int(s, 0))
            except ValueError:
                idaapi.warning(
                    'Parsing "%s" failed. Deleted virtual values were not modified.'
                    % s)
                return

        db.deleted_virtual_vals = new_deleted_virtual_vals
Exemple #25
0
    def handle_add_method(self):
        db = database.get()

        if self.edit_class is None:
            return

        sel_ea = idc.get_screen_ea()

        if sel_ea == idc.BADADDR:
            return

        existing_method = None
        if sel_ea in db.known_methods:
            existing_method = db.known_methods[sel_ea]
            if type(existing_method) != database_entries.Method:
                idaapi.warning("Cannot unlink function that is in a VTable")
                return

        name = idc.get_name(sel_ea, 0)
        if name.startswith('_Z'):  # Ignore already mangled names
            name = ''
        if not name:
            name = 'sub_%X' % sel_ea

        dlg = SignatureDialog(name=name,
                              owner_type=self.edit_class.name,
                              fixed_owner_type=True)
        if dlg.exec_() != QtWidgets.QDialog.Accepted:
            return

        if existing_method is not None:
            existing_method.unlink()

        method = database_entries.Method(sel_ea, self.edit_class, dlg.name)
        method.set_signature(dlg.name, dlg.args, dlg.return_type, dlg.is_const,
                             dlg.ctor_type, dlg.dtor_type)
        self.edit_class.methods.append(method)
        method.refresh()

        self.update_fields()
Exemple #26
0
    def __init__(self, name, base):

        self.name = name

        self.base = base
        self.derived = []

        self.struct_id = idc.BADADDR

        if self.base is not None:
            self.base.derived.append(self)

        self.methods = []

        self.vtable_start = None
        self.vtable_end = None
        self.vmethods = []
        self.reset_vtable()

        db = database.get()
        db.classes_by_name[name] = self
        if self.base is None:
            db.root_classes.append(self)
Exemple #27
0
 def save(self):
     database.get().save()
Exemple #28
0
 def s_is_pure_virtual_dst(dst):
     return dst in database.get().pure_virtual_vals
Exemple #29
0
 def s_is_deleted_virtual_dst(dst):
     return dst in database.get().deleted_virtual_vals
Exemple #30
0
def refresh_all():
    db = database.get()

    for c in db.classes_by_name.values():
        c.refresh()