Exemplo n.º 1
0
def _create_next_block(original):
	block = nodes.Block()
	block.first_address = original.last_address + 1
	block.last_address = block.first_address
	block.index = original.index + 1
	block.warpins_count = original.warpins_count

	return block
Exemplo n.º 2
0
def _blockenize(state, instructions):
    # Fix inverted comparison expressions (e.g. 0 < variable):
    _fix_inverted_comparison_expressions(state, instructions)

    # Fix "repeat until true" encapsulated by another loop
    _fix_broken_repeat_until_loops(state, instructions)

    # Fix "var_1 = var_1 [comparison] var_2 and (operation) var_1 or var_1" edge case
    _fix_broken_unary_expressions(state, instructions)

    addr = 1

    # Duplicates are possible and ok, but we need to sort them out
    last_addresses = set()

    while addr < len(instructions):
        instruction = instructions[addr]
        opcode = instruction.opcode

        if opcode not in _WARP_INSTRUCTIONS:
            addr += 1
            continue

        if opcode in _JUMP_WARP_INSTRUCTIONS:
            destination = get_jump_destination(addr, instruction)

            if opcode != ins.UCLO.opcode or destination != addr + 1:
                last_addresses.add(destination - 1)
                last_addresses.add(addr)
        else:
            last_addresses.add(addr)

        addr += 1

    last_addresses = sorted(list(last_addresses))
    last_addresses.append(len(instructions) - 1)

    # This could happen if something jumps to the first instruction
    # We don't need "zero block" with function header, so simply ignore
    # this
    if last_addresses[0] == 0:
        last_addresses.pop(0)

    previous_last_address = 0

    index = 0
    for last_address in last_addresses:
        block = nodes.Block()
        block.index = index
        block.first_address = previous_last_address + 1
        block.last_address = last_address

        state.blocks.append(block)
        state.block_starts[block.first_address] = block

        previous_last_address = last_address

        index += 1
Exemplo n.º 3
0
def _build_conditional_warp(state, last_addr, instructions):
    condition = instructions[-2]
    condition_addr = last_addr - 1

    warp = nodes.ConditionalWarp()

    if condition.opcode in (ins.ISTC.opcode, ins.ISFC.opcode):
        expression = _build_unary_expression(state, condition_addr, condition)

        setattr(warp, "_slot", condition.A)
    elif condition.opcode >= ins.IST.opcode:
        expression = _build_unary_expression(state, condition_addr, condition)

        setattr(warp, "_slot", condition.CD)
    else:
        expression = _build_comparison_expression(state, condition_addr,
                                                  condition)

    warp.condition = expression

    jump = instructions[-1]
    jump_addr = last_addr

    destination = get_jump_destination(jump_addr, jump)

    # A condition is inverted during the preparation phase above
    warp.false_target = state._warp_in_block(destination)
    warp.true_target = state._warp_in_block(jump_addr + 1)

    shift = 2
    if destination == (jump_addr + 1) \
            and condition.opcode not in (ins.ISTC.opcode, ins.ISFC.opcode):
        # This is an empty 'then' or 'else'. The simplest way to handle it is
        # to insert a Block containing just a no-op statement.
        block = nodes.Block()
        block.first_address = jump_addr + 1
        block.last_address = block.first_address
        block.index = warp.true_target.index
        block.warpins_count = 1
        setattr(block, "_last_body_addr", block.last_address - shift)

        block.warp = nodes.UnconditionalWarp()
        block.warp.type = nodes.UnconditionalWarp.T_FLOW
        block.warp.target = warp.true_target
        setattr(block.warp, "_addr", block.last_address - shift + 1)

        state.blocks.insert(state.blocks.index(warp.true_target), block)
        warp.true_target = block

        _create_no_op(state, jump_addr, block)

    return warp, shift
Exemplo n.º 4
0
def _blockenize(state, instructions):
    "将指令划分成代码块"
    addr = 1

    # Duplicates are possible and ok, but we need to sort them out
    last_addresses = set()

    while addr < len(instructions):
        instruction = instructions[addr]
        opcode = instruction.opcode

        if opcode not in _WARP_INSTRUCTIONS:
            addr += 1
            continue

        if opcode in _JUMP_WARP_INSTRUCTIONS:  # 跳转:当前指令地址,及跳转目的地的前一地址为一个代码块的末端
            destination = get_jump_destination(addr, instruction)

            if opcode != ins.UCLO.opcode or destination != addr + 1:
                last_addresses.add(destination - 1)
                last_addresses.add(addr)
        else:
            last_addresses.add(addr)

        addr += 1

    last_addresses = sorted(list(last_addresses))
    last_addresses.append(len(instructions) - 1)

    # This could happen if something jumps to the first instruction
    # We don't need "zero block" with function header, so simply ignore
    # this
    if last_addresses[0] == 0:
        last_addresses.pop(0)

    previous_last_address = 0

    index = 0
    for last_address in last_addresses:
        block = nodes.Block()
        block.index = index
        block.first_address = previous_last_address + 1
        block.last_address = last_address

        state.blocks.append(block)
        state.block_starts[block.first_address] = block

        previous_last_address = last_address

        index += 1
Exemplo n.º 5
0
def _unwarp_loops(blocks, repeat_until):
	loops = _find_all_loops(blocks, repeat_until)

	if len(loops) == 0:
		return blocks

	fixed = _cleanup_breaks_and_if_ends(loops, blocks)

	for start, end in fixed:
		start_index = blocks.index(start)
		end_index = blocks.index(end)

		if repeat_until:
			body = blocks[start_index:end_index]
		else:
			body = blocks[start_index + 1:end_index]

		loop = _unwarp_loop(start, end, body)
		body = loop.statements.contents

		block = nodes.Block()
		block.first_address = body[0].first_address
		block.last_address = body[-1].last_address
		block.index = start.index + 1
		block.contents.append(loop)

		block.warp = nodes.UnconditionalWarp()
		block.warp.type = nodes.UnconditionalWarp.T_FLOW
		block.warp.target = end

		_replace_targets(blocks, body[0], block)

		_set_end(body[-1])
		_unwarp_breaks(start, body, end)

		blocks = blocks[:start_index + 1] + [block] + blocks[end_index:]

	return blocks