Exemplo n.º 1
0
    def goto_referring_address(self, acting_client):
        current_address = self.get_address(acting_client)
        if current_address is None:
            return ERRMSG_NO_IDENTIFIABLE_DESTINATION

        addresses = list(disassembly.get_referring_addresses(self.disassembly_data, current_address))
        if not len(addresses):
            return ERRMSG_NO_IDENTIFIABLE_DESTINATION

        # Addresses appear in numerical order.
        addresses.sort()
        # Symbols appear in place of addresses where they exist.
        converted_addresses = addresses[:]
        self._convert_addresses_to_symbols_where_possible(converted_addresses)
        address_rows = []
        for i, address in enumerate(addresses):
            code_string = self.get_source_code_for_address(acting_client, address)
            address_rows.append((self._address_to_string(address), converted_addresses[i], code_string))

        selected_address = acting_client.request_address_selection(TEXT_SELECT_REFERRING_ADDRESS_SHORT, TEXT_SELECT_REFERRING_ADDRESS_LONG, TEXT_GO_TO_SELECTION, address_rows, addresses)
        if selected_address is None:
            return False

        next_line_number = disassembly.get_line_number_for_address(self.disassembly_data, selected_address)
        if next_line_number is None:
            return ERRMSG_BUG_UNABLE_TO_GOTO_LINE

        self.set_line_number(acting_client, next_line_number)
        self.address_stack.append(current_address)
        return True
Exemplo n.º 2
0
    def pop_address(self, acting_client):
        if self.state_id != EditorState.STATE_LOADED:
            return ERRMSG_TODO_BAD_STATE_FUNCTIONALITY

        if not len(self.address_stack):
            return ERRMSG_NO_IDENTIFIABLE_DESTINATION

        address = self.address_stack.pop()
        # It is expected that if you can have pushed the address, there was a line number for it.
        line_number = disassembly.get_line_number_for_address(self.disassembly_data, address)
        self.set_line_number(acting_client, line_number)
Exemplo n.º 3
0
 def goto_address(self, acting_client):
     address = self.get_address(acting_client)
     if address is None: # Current line does not have an address.
         address = 0
     result = acting_client.request_address(address)
     if result is None: # Cancelled / aborted.
         return
     # Convert an entered symbol name to it's address.
     if type(result) in types.StringTypes:
         result = disassembly.get_address_for_symbol(self.disassembly_data, result)
         if result is None:
             return ERRMSG_NO_IDENTIFIABLE_DESTINATION
     line_number = disassembly.get_line_number_for_address(self.disassembly_data, result)
     self.set_line_number(acting_client, line_number)
Exemplo n.º 4
0
    def push_address(self, acting_client):
        if self.state_id != EditorState.STATE_LOADED:
            return ERRMSG_TODO_BAD_STATE_FUNCTIONALITY

        current_address = self.get_address(acting_client)
        if current_address is None:
            return ERRMSG_BUG_UNKNOWN_ADDRESS

        operand_addresses = disassembly.get_referenced_symbol_addresses_for_line_number(self.disassembly_data, self.line_number)
        if len(operand_addresses) == 1:
            next_line_number = disassembly.get_line_number_for_address(self.disassembly_data, operand_addresses[0])
            if next_line_number is None:
                return ERRMSG_BUG_UNABLE_TO_GOTO_LINE

            self.set_line_number(acting_client, next_line_number)
            self.address_stack.append(current_address)
            return
        elif len(operand_addresses) == 2:
            return ERRMSG_BUG_NO_OPERAND_SELECTION_MECHANISM

        return ERRMSG_NO_IDENTIFIABLE_DESTINATION
Exemplo n.º 5
0
    def load_file(self, acting_client):
        self.reset_state(acting_client)

        # Request a file name to load.
        result = acting_client.request_load_file()
        if result is None:
            return
        if type(result) in types.StringTypes:
            self.reset_state(acting_client)
            return result
        load_file, file_path = result

        self.state_id = EditorState.STATE_LOADING
        file_name = os.path.basename(file_path)
        is_saved_project = disassembly_persistence.check_is_project_file(load_file)

        for client in self.clients:
            client.event_load_start(client is acting_client, file_path)

        if is_saved_project:
            result = self._prolonged_action(acting_client, "TITLE_LOADING_PROJECT", "TEXT_GENERIC_LOADING", disassembly.load_project_file, load_file, file_name)
        else:
            new_options = disassembly.get_new_project_options(self.disassembly_data)
            identify_result = loaderlib.identify_file(load_file, file_name)
            # Parameters passed in, to help the client make up it's mind.
            if identify_result is not None:
                new_options.is_binary_file = False
                new_options.loader_load_address = loaderlib.get_load_address(identify_result[0])
                new_options.loader_entrypoint_offset = loaderlib.get_entrypoint_address(identify_result[0])
                new_options.loader_filetype = identify_result[1]["filetype"]
                new_options.loader_processor = identify_result[1]["processor"]
            else:
                new_options.is_binary_file = True
                new_options.loader_load_address = 0
                new_options.loader_entrypoint_offset = 0
                new_options.loader_filetype = loaderlib.constants.FILE_FORMAT_UNKNOWN
                new_options.loader_processor = ""
            # Prompt for new project option values.
            new_option_result = acting_client.request_new_project_option_values(new_options)
            if new_option_result is None or type(new_option_result) in types.StringTypes:
                self.reset_state(acting_client)
                return new_option_result

            result = self._prolonged_action(acting_client, "TITLE_LOADING_FILE", "TEXT_GENERIC_LOADING", disassembly.load_file, load_file, new_option_result, file_name)

        # Loading was cancelled.
        if result is None:
            self.reset_state(acting_client)
            return

        self.state_id = EditorState.STATE_LOADED
        self.disassembly_data, line_count = result

        # Register our event dispatching callbacks.
        disassembly.set_uncertain_reference_modification_func(self.disassembly_data, self._uncertain_reference_modification_callback)
        disassembly.set_symbol_insert_func(self.disassembly_data, self._symbol_insert_callback)
        disassembly.set_symbol_delete_func(self.disassembly_data, self._symbol_delete_callback)

        if line_count == 0:
            self.reset_state(acting_client)
            return ERRMSG_NOT_SUPPORTED_EXECUTABLE_FILE_FORMAT

        is_saved_project = disassembly_persistence.check_is_project_file(acting_client.get_load_file())
        if is_saved_project:
            # User may have optionally chosen to not save the input file, as part of the project file.
            if not disassembly.is_segment_data_cached(self.disassembly_data):
                load_options = disassembly.get_new_project_options(self.disassembly_data)
                # Parameters passed in, to help the client make up it's mind.
                load_options.input_file_filesize = self.disassembly_data.file_size
                load_options.input_file_filename = self.disassembly_data.file_name
                load_options.input_file_checksum = self.disassembly_data.file_checksum
                # Parameters received out, our "return values".
                load_options.loader_file_path = None
                load_options = acting_client.request_load_project_option_values(load_options)

                if load_options.loader_file_path is None:
                    self.reset_state(acting_client)
                    return ERRMSG_INPUT_FILE_NOT_FOUND

                # Verify that the given input file is valid, or error descriptively.
                with open(load_options.loader_file_path, "rb") as input_data_file:
                    input_data_file.seek(0, os.SEEK_END)
                    errmsg = None
                    if input_data_file.tell() != self.disassembly_data.file_size:
                        errmsg = ERRMSG_INPUT_FILE_SIZE_DIFFERS
                    elif util.calculate_file_checksum(input_data_file) != self.disassembly_data.file_checksum:
                        errmsg = ERRMSG_INPUT_FILE_CHECKSUM_MISMATCH
                    if type(errmsg) in types.StringTypes:
                        self.reset_state(acting_client)
                        return errmsg
                    disassembly.cache_segment_data(self.disassembly_data, input_data_file)
                    disassembly.load_project_file_finalise(self.disassembly_data)

        entrypoint_address = disassembly.get_entrypoint_address(self.disassembly_data)
        line_number = disassembly.get_line_number_for_address(self.disassembly_data, entrypoint_address)
        self.set_line_number(acting_client, line_number)

        def _pre_line_change_callback(line0, line_count):
            for client in self.clients:
                client.event_pre_line_change(client is acting_client, line0, line_count)
        self.disassembly_data.pre_line_change_func = _pre_line_change_callback
        def _post_line_change_callback(line0, line_count):
            for client in self.clients:
                client.event_post_line_change(client is acting_client, line0, line_count)
        self.disassembly_data.post_line_change_func = _post_line_change_callback

        for client in self.clients:
            client.event_load_successful(client is acting_client)
        return result
Exemplo n.º 6
0
 def get_line_number_for_address(self, acting_client, address):
     return disassembly.get_line_number_for_address(self.disassembly_data, address)
Exemplo n.º 7
0
 def get_source_code_for_address(self, acting_client, address):
     line_idx = disassembly.get_line_number_for_address(self.disassembly_data, address)
     return self.get_source_code_for_line_number(acting_client, line_idx)