static void hijack_xor_sequences(reloc_seq_t *seq, hijacksection_t *hijacksection, pefile_t *pefile) { reloc_seq_t *seq_ptr; assert(seq != NULL); assert(hijacksection != NULL); assert(pefile != NULL); for (seq_ptr = seq; seq_ptr != NULL; seq_ptr = seq_ptr->next) { reloc_insn_list_t *ilistptr; if (seq_ptr->relocated) continue; // See if there is a guaranteed ZF=1 instruction like xor eax, eax in the seq. for (ilistptr = seq_ptr->instructions; ilistptr != NULL; ilistptr = ilistptr->next) { disassembly_t *in = ilistptr->insn; armoring_swirly(); if (in->Instruction.type == insn_xor) { if (operands_match(in)) { if (split_reloc_sequence(seq_ptr, in->MemoryAddress - seq_ptr->start) != FALSE) { hijack_xor_seq(seq_ptr->next, hijacksection, pefile); seq_ptr = seq_ptr->next; } else { hijack_xor_seq(seq_ptr, hijacksection, pefile); } break; } } } } }
static bool instructions_match(fs_inst *a, fs_inst *b) { return a->opcode == b->opcode && a->saturate == b->saturate && a->predicate == b->predicate && a->predicate_inverse == b->predicate_inverse && a->conditional_mod == b->conditional_mod && a->dst.type == b->dst.type && operands_match(a->opcode, a->src, b->src); }
static bool instructions_match(fs_inst *a, fs_inst *b) { return a->opcode == b->opcode && a->saturate == b->saturate && a->predicate == b->predicate && a->predicate_inverse == b->predicate_inverse && a->conditional_mod == b->conditional_mod && a->dst.type == b->dst.type && a->sources == b->sources && (a->is_tex() ? (a->texture_offset == b->texture_offset && a->mlen == b->mlen && a->regs_written == b->regs_written && a->base_mrf == b->base_mrf && a->sampler == b->sampler && a->eot == b->eot && a->header_present == b->header_present && a->shadow_compare == b->shadow_compare) : true) && operands_match(a, b); }
bool fs_visitor::opt_cse_local(bblock_t *block, exec_list *aeb) { bool progress = false; void *mem_ctx = ralloc_context(this->mem_ctx); for (fs_inst *inst = (fs_inst *)block->start; inst != block->end->next; inst = (fs_inst *) inst->next) { /* Skip some cases. */ if (is_expression(inst) && !inst->predicate && inst->mlen == 0 && !inst->force_uncompressed && !inst->force_sechalf && !inst->conditional_mod) { bool found = false; aeb_entry *entry; foreach_list(entry_node, aeb) { entry = (aeb_entry *) entry_node; /* Match current instruction's expression against those in AEB. */ if (inst->opcode == entry->generator->opcode && inst->saturate == entry->generator->saturate && operands_match(entry->generator->src, inst->src)) { found = true; progress = true; break; } } if (!found) { /* Our first sighting of this expression. Create an entry. */ aeb_entry *entry = ralloc(mem_ctx, aeb_entry); entry->tmp = reg_undef; entry->generator = inst; aeb->push_tail(entry); } else { /* This is at least our second sighting of this expression. * If we don't have a temporary already, make one. */ bool no_existing_temp = entry->tmp.file == BAD_FILE; if (no_existing_temp) { entry->tmp = fs_reg(this, glsl_type::float_type); entry->tmp.type = inst->dst.type; fs_inst *copy = new(ralloc_parent(inst)) fs_inst(BRW_OPCODE_MOV, entry->generator->dst, entry->tmp); entry->generator->insert_after(copy); entry->generator->dst = entry->tmp; } /* dest <- temp */ fs_inst *copy = new(ralloc_parent(inst)) fs_inst(BRW_OPCODE_MOV, inst->dst, entry->tmp); inst->replace_with(copy); /* Appending an instruction may have changed our bblock end. */ if (inst == block->end) { block->end = copy; } /* Continue iteration with copy->next */ inst = copy; } }
bool fs_visitor::opt_cse_local(bblock_t *block, exec_list *aeb) { bool progress = false; void *mem_ctx = ralloc_context(this->mem_ctx); int ip = block->start_ip; for (fs_inst *inst = (fs_inst *)block->start; inst != block->end->next; inst = (fs_inst *) inst->next) { /* Skip some cases. */ if (is_expression(inst) && !inst->predicate && !inst->is_partial_write() && !inst->conditional_mod) { bool found = false; aeb_entry *entry; foreach_list(entry_node, aeb) { entry = (aeb_entry *) entry_node; /* Match current instruction's expression against those in AEB. */ if (inst->opcode == entry->generator->opcode && inst->saturate == entry->generator->saturate && inst->dst.type == entry->generator->dst.type && operands_match(entry->generator->src, inst->src)) { found = true; progress = true; break; } } if (!found) { /* Our first sighting of this expression. Create an entry. */ aeb_entry *entry = ralloc(mem_ctx, aeb_entry); entry->tmp = reg_undef; entry->generator = inst; aeb->push_tail(entry); } else { /* This is at least our second sighting of this expression. * If we don't have a temporary already, make one. */ bool no_existing_temp = entry->tmp.file == BAD_FILE; if (no_existing_temp) { int written = entry->generator->regs_written; fs_reg orig_dst = entry->generator->dst; fs_reg tmp = fs_reg(GRF, virtual_grf_alloc(written), orig_dst.type); entry->tmp = tmp; entry->generator->dst = tmp; for (int i = 0; i < written; i++) { fs_inst *copy = MOV(orig_dst, tmp); copy->force_writemask_all = entry->generator->force_writemask_all; entry->generator->insert_after(copy); orig_dst.reg_offset++; tmp.reg_offset++; } } /* dest <- temp */ int written = inst->regs_written; assert(written == entry->generator->regs_written); assert(inst->dst.type == entry->tmp.type); fs_reg dst = inst->dst; fs_reg tmp = entry->tmp; fs_inst *copy = NULL; for (int i = 0; i < written; i++) { copy = MOV(dst, tmp); copy->force_writemask_all = inst->force_writemask_all; inst->insert_before(copy); dst.reg_offset++; tmp.reg_offset++; } inst->remove(); /* Appending an instruction may have changed our bblock end. */ if (inst == block->end) { block->end = copy; } /* Continue iteration with copy->next */ inst = copy; } }
static void hijack_xor_seq(reloc_seq_t *seq, hijacksection_t *hijacksection, pefile_t *pefile) { char *old_buf; char *new_buf; DWORD newMemoryAddress = 0; DWORD dwOperand = 0; DWORD xorInsnSize = 0; assert(seq != NULL); assert(hijacksection != NULL); assert(pefile != NULL); if (seq->relocated) return; if (seq->instructions->insn->Instruction.type != insn_xor || !operands_match(seq->instructions->insn)) { return; } xorInsnSize = seq->instructions->insn->InstructionSize; seq->instructions = seq->instructions->next; seq->length -= xorInsnSize; seq->start += xorInsnSize; // See if we have enough room to plant the 6 byte "JZ rel32" instruction if (seq->length < 6) return; old_buf = va_to_ptr(pefile, seq->start); if (old_buf == NULL) { old_buf = hijacksection_va_to_ptr(hijacksection, seq->start); if (old_buf == NULL) return; } new_buf = hijack_reserve(hijacksection, seq->length + 6, &newMemoryAddress); new_buf[0] = 0xEB; // 8-bit relative JMP prefix newMemoryAddress++; // lets bypass the fake 0xEB we put in for future reference. hijack(old_buf, seq->start, &new_buf[1], newMemoryAddress, seq); // finish off the new hijack area with a jmp back to the original. new_buf[seq->length + 1] = 0xE9; // 32-bit JMP prefix dwOperand = (seq->start + seq->length) - (newMemoryAddress + seq->length + 5); memcpy(&new_buf[(seq->length) + 2], &dwOperand, sizeof dwOperand); // Put in a jz prefix to the new "real" code chunk old_buf[0] = 0x0F; old_buf[1] = 0x84; dwOperand = newMemoryAddress - (seq->start + 6); memcpy(&old_buf[2], &dwOperand, sizeof dwOperand); // if we have enough room left, put in a fake jmp or call to before the "real" code // This will throw off disassembly, especially if we put a valid instruction prefix there. if (seq->length >= xorInsnSize + 6 + 5) { // call <offset> is 5 bytes old_buf[6] = 0xE8; // 32-bit relative CALL prefix dwOperand = (newMemoryAddress - 1) - (seq->start + 6 + 5); memcpy(&old_buf[7], &dwOperand, sizeof dwOperand); } //printf("XOR Hijack: %d bytes from 0x%08X to 0x%08X\n", seq->length, seq->start, newMemoryAddress+1); //debug_print_insn_list(seq->instructions); //printf("\n"); seq->relocated = TRUE; // make a new relocatable sequence out of what has been moved so that another algorithm // may play with it further... (evil laughter) // ...This could turn out to be a dumb idea... // if (seq->length > xorInsnSize) { // reloc_seq_t *new_seq; // DWORD dwSeqOffset = 0; // reloc_insn_list_t *insn; // new_seq = ecalloc(1, sizeof *new_seq); // new_seq->instructions = seq->instructions; // new_seq->length = seq->length; // new_seq->start = newMemoryAddress + 1; // Add 1 to bypass the fake prefix we added. // // // just in case it might bite us later on, lets adjust all the addresses for the instructions // for (insn = new_seq->instructions; insn != NULL; insn = insn->next) { // insn->insn->MemoryAddress = newMemoryAddress + dwSeqOffset + 1; // dwSeqOffset += insn->insn->InstructionSize; // } // // new_seq->next = seq->next; // seq->next = new_seq; //} }