def save_loader_hunk(f, program_data):
    persistence.write_string(f, program_data.loader_system_name)
    write_segment_list(f, program_data.loader_segments)
    persistence.write_set_of_uint32s(f, program_data.loader_relocated_addresses)
    persistence.write_set_of_uint32s(f, program_data.loader_relocatable_addresses)
    persistence.write_uint16(f, program_data.loader_entrypoint_segment_id)
    persistence.write_uint32(f, program_data.loader_entrypoint_offset)
Ejemplo n.º 2
0
def save_loader_hunk(f, program_data):
    persistence.write_string(f, program_data.loader_system_name)
    write_segment_list(f, program_data.loader_segments)
    persistence.write_dict_uint32_to_set_of_uint32s(
        f, program_data.loader_relocated_addresses)
    persistence.write_set_of_uint32s(f,
                                     program_data.loader_relocatable_addresses)
    persistence.write_uint16(f, program_data.loader_entrypoint_segment_id)
    persistence.write_uint32(f, program_data.loader_entrypoint_offset)
Ejemplo n.º 3
0
def write_SegmentBlock(f, block, pc_offset):
    if block.line_data is None:
        line_data_count = 0
    else:
        line_data_count = len(block.line_data)

    s = struct.pack(SEGMENTBLOCK_PACK_FORMAT, block.segment_id,
                    block.segment_offset, block.address, block.length,
                    block.flags, block.line_count, line_data_count)
    f.write(s)

    if line_data_count > 0:
        if get_block_data_type(block) == DATA_TYPE_CODE:
            block_offset = 0
            for i, (type_id, entry) in enumerate(block.line_data):
                persistence.write_uint8(f, type_id)
                if type_id == SLD_INSTRUCTION:
                    if type(entry) is int:
                        persistence.write_uint16(f, entry)
                        # The length of this instruction is not stored, so we calculate it relative to the next one.
                        j = i + 1
                        while j < len(block.line_data):
                            next_type_id, next_entry = block.line_data[j]
                            if next_type_id == SLD_INSTRUCTION:
                                if type(next_entry) is int:
                                    block_offset = next_entry
                                else:
                                    block_offset = next_entry.pc - pc_offset
                                break
                            j += 1
                    else:
                        persistence.write_uint16(f, block_offset)
                        block_offset += entry.num_bytes
                elif type_id == SLD_EQU_LOCATION_RELATIVE:
                    persistence.write_uint32(f, entry)  # block offset
                elif type_id in (SLD_COMMENT_TRAILING, SLD_COMMENT_FULL_LINE):
                    persistence.write_string(f, entry)  # string
                else:
                    logger.error(
                        "Trying to save a savefile, did not know how to handle entry of type_id: %d, entry value: %s",
                        type_id, entry)
def write_SegmentBlock(f, block):
    if block.line_data is None:
        line_data_count = 0
    else:
        line_data_count = len(block.line_data)

    s = struct.pack(SEGMENTBLOCK_PACK_FORMAT, block.segment_id, block.segment_offset, block.address, block.length, block.flags, block.line_count, line_data_count)
    f.write(s)

    if line_data_count > 0:
        if get_block_data_type(block) == DATA_TYPE_CODE:
            block_offset = 0
            for i, (type_id, entry) in enumerate(block.line_data):
                persistence.write_uint8(f, type_id)
                if type_id == SLD_INSTRUCTION:
                    if type(entry) is int:
                        persistence.write_uint16(f, entry)
                        # The length of this instruction is not stored, so we calculate it relative to the next one.
                        j = i+1
                        while j < len(block.line_data):
                            next_type_id, next_entry = block.line_data[j]
                            if next_type_id == SLD_INSTRUCTION:
                                if type(next_entry) is int:
                                    block_offset = next_entry
                                else:
                                    block_offset = next_entry.pc-2
                                break
                            j += 1
                    else:
                        persistence.write_uint16(f, block_offset)
                        block_offset += entry.num_bytes
                elif type_id == SLD_EQU_LOCATION_RELATIVE:
                    persistence.write_uint32(f, entry) # block offset
                elif type_id in (SLD_COMMENT_TRAILING, SLD_COMMENT_FULL_LINE):
                    persistence.write_string(f, entry) # string
                else:
                    logger.error("Trying to save a savefile, did not know how to handle entry of type_id: %d, entry value: %s", type_id, entry)
Ejemplo n.º 5
0
def convert_project_format_4_to_5(input_file):
    """
    This function should encapsulate all application-specific logic involved to
    make it independent of as many changes as possible.

    Version 4 -> 5.
    Modifications:
    - symbols by address has gone from a label to a structure with metadata.
    """
    SNAPSHOT_HUNK_VERSIONS = {
        SAVEFILE_HUNK_SOURCEDATA: 1,
        SAVEFILE_HUNK_SOURCEDATAINFO: 1,
        SAVEFILE_HUNK_LOADER: 1,
        SAVEFILE_HUNK_LOADERINTERNAL: 1,
        SAVEFILE_HUNK_DISASSEMBLY: 2,
    }

    input_file.seek(0, os.SEEK_END)
    file_size = input_file.tell()
    input_file.seek(0, os.SEEK_SET)

    savefile_id = persistence.read_uint32(input_file)
    savefile_version = persistence.read_uint16(input_file)
    if savefile_version != 4:
        return None

    logger.info(
        "Upgrading save-file from version 4 to version 5: symbols by address.."
    )
    save_count = persistence.read_uint32(input_file)

    output_file = tempfile.TemporaryFile()
    persistence.write_uint32(output_file, savefile_id)
    persistence.write_uint16(output_file, 5)
    persistence.write_uint32(output_file, save_count)

    while input_file.tell() < file_size:
        # This should be pretty straightforward.
        hunk_header_offset = input_file.tell()
        hunk_id = persistence.read_uint16(input_file)
        hunk_length = persistence.read_uint32(input_file)
        hunk_payload_offset = input_file.tell()

        actual_hunk_version = persistence.read_uint16(input_file)
        expected_hunk_version = SNAPSHOT_HUNK_VERSIONS[hunk_id]
        if expected_hunk_version != actual_hunk_version:
            logger.error(
                "convert_project_format_4_to_5: hunk %d version mismatch %d != %d",
                hunk_id, expected_hunk_version, actual_hunk_version)
            return None
        logger.debug("convert_project_format_4_to_5: file hunk %d", hunk_id)

        if SAVEFILE_HUNK_LOADER != hunk_id:
            input_file.seek(hunk_header_offset, os.SEEK_SET)
            raw_hunk_length = (hunk_payload_offset -
                               hunk_header_offset) + hunk_length
            output_file.write(input_file.read(raw_hunk_length))
            continue

        # Write the as yet to be updated header.
        persistence.write_uint16(output_file, hunk_id)
        output_file_length_offset = output_file.tell()
        persistence.write_uint32(output_file, 0)
        output_file_payload_offset = output_file.tell()
        persistence.write_uint16(
            output_file, SNAPSHOT_HUNK_VERSIONS[SAVEFILE_HUNK_LOADER] + 1)

        # Transform the hunk from input file to output file.
        persistence.write_string(
            output_file,
            persistence.read_string(input_file))  # loader_system_name
        data_size = persistence.read_uint32(input_file)
        persistence.write_uint32(output_file, data_size)  # loader_segments
        output_file.write(input_file.read(data_size))
        set_value = persistence.read_set_of_uint32s(input_file)
        persistence.write_dict_uint32_to_list_of_uint32s(
            output_file, {k: []
                          for k in set_value})  # loader_relocated_addresses
        set_value = persistence.read_set_of_uint32s(input_file)
        persistence.write_set_of_uint32s(
            output_file, set_value)  # loader_relocatable_addresses
        persistence.write_uint16(
            output_file, persistence.read_uint16(
                input_file))  # loader_entrypoint_segment_id
        persistence.write_int32(
            output_file,
            persistence.read_uint32(input_file))  # loader_entrypoint_offset

        # Update the header length field, then fast forward to the end of the hunk.
        new_hunk_length = output_file.tell() - output_file_payload_offset
        output_file.seek(output_file_length_offset, os.SEEK_SET)
        persistence.write_uint32(output_file, new_hunk_length)
        output_file.seek(new_hunk_length, os.SEEK_CUR)

        if output_file.tell() - output_file_payload_offset != new_hunk_length:
            logger.error(
                "convert_project_format_4_to_5: block length mismatch %d != %d",
                output_file.tell() - output_file_payload_offset,
                new_hunk_length)
            return None

    return output_file
Ejemplo n.º 6
0
def convert_project_format_4_to_5(input_file):
    """
    This function should encapsulate all application-specific logic involved to
    make it independent of as many changes as possible.

    Version 4 -> 5.
    Modifications:
    - symbols by address has gone from a label to a structure with metadata.
    """
    SNAPSHOT_HUNK_VERSIONS = {
        SAVEFILE_HUNK_SOURCEDATA: 1,
        SAVEFILE_HUNK_SOURCEDATAINFO: 1,
        SAVEFILE_HUNK_LOADER: 1,
        SAVEFILE_HUNK_LOADERINTERNAL: 1,
        SAVEFILE_HUNK_DISASSEMBLY: 2,
    }

    input_file.seek(0, os.SEEK_END)
    file_size = input_file.tell()
    input_file.seek(0, os.SEEK_SET)

    savefile_id = persistence.read_uint32(input_file)
    savefile_version = persistence.read_uint16(input_file)
    if savefile_version != 4:
        return None

    logger.info("Upgrading save-file from version 4 to version 5: symbols by address..")
    save_count = persistence.read_uint32(input_file)

    output_file = tempfile.TemporaryFile()
    persistence.write_uint32(output_file, savefile_id)
    persistence.write_uint16(output_file, 5)
    persistence.write_uint32(output_file, save_count)

    while input_file.tell() < file_size:
        # This should be pretty straightforward.
        hunk_header_offset = input_file.tell()
        hunk_id = persistence.read_uint16(input_file)
        hunk_length = persistence.read_uint32(input_file)
        hunk_payload_offset = input_file.tell()

        actual_hunk_version = persistence.read_uint16(input_file)
        expected_hunk_version = SNAPSHOT_HUNK_VERSIONS[hunk_id]
        if expected_hunk_version != actual_hunk_version:
            logger.error("convert_project_format_4_to_5: hunk %d version mismatch %d != %d", hunk_id, expected_hunk_version, actual_hunk_version)
            return None
        logger.debug("convert_project_format_4_to_5: file hunk %d", hunk_id)

        if SAVEFILE_HUNK_LOADER != hunk_id:
            input_file.seek(hunk_header_offset, os.SEEK_SET)
            raw_hunk_length = (hunk_payload_offset - hunk_header_offset) + hunk_length
            output_file.write(input_file.read(raw_hunk_length))
            continue

        # Write the as yet to be updated header.
        persistence.write_uint16(output_file, hunk_id)
        output_file_length_offset = output_file.tell()
        persistence.write_uint32(output_file, 0)
        output_file_payload_offset = output_file.tell()
        persistence.write_uint16(output_file, SNAPSHOT_HUNK_VERSIONS[SAVEFILE_HUNK_LOADER] + 1)

        # Transform the hunk from input file to output file.
        persistence.write_string(output_file, persistence.read_string(input_file)) # loader_system_name
        data_size = persistence.read_uint32(input_file)
        persistence.write_uint32(output_file, data_size) # loader_segments
        output_file.write(input_file.read(data_size))
        set_value = persistence.read_set_of_uint32s(input_file)
        persistence.write_dict_uint32_to_list_of_uint32s(output_file, { k: [] for k in set_value }) # loader_relocated_addresses
        set_value = persistence.read_set_of_uint32s(input_file)
        persistence.write_set_of_uint32s(output_file, set_value) # loader_relocatable_addresses
        persistence.write_uint16(output_file, persistence.read_uint16(input_file)) # loader_entrypoint_segment_id
        persistence.write_int32(output_file, persistence.read_uint32(input_file)) # loader_entrypoint_offset

        # Update the header length field, then fast forward to the end of the hunk.
        new_hunk_length = output_file.tell() - output_file_payload_offset
        output_file.seek(output_file_length_offset, os.SEEK_SET)
        persistence.write_uint32(output_file, new_hunk_length)
        output_file.seek(new_hunk_length, os.SEEK_CUR)

        if output_file.tell() - output_file_payload_offset != new_hunk_length:
            logger.error("convert_project_format_4_to_5: block length mismatch %d != %d", output_file.tell() - output_file_payload_offset, new_hunk_length)
            return None

    return output_file