/* java_encode */ static int _java_encode(AsmArchPlugin * plugin, AsmArchInstruction const * instruction, AsmArchInstructionCall * call) { AsmArchPluginHelper * helper = plugin->helper; size_t i; AsmArchOperandDefinition definitions[3]; AsmArchOperand * ao; uint8_t u8; uint16_t u16; uint32_t u32; if((helper->write(helper->arch, &instruction->opcode, 1)) != 1) return -1; /* FIXME tableswitch may need some padding */ definitions[0] = instruction->op1; definitions[1] = instruction->op2; definitions[2] = instruction->op3; for(i = 0; i < call->operands_cnt; i++) { ao = &call->operands[i]; if(AO_GET_TYPE(ao->definition) != AOT_IMMEDIATE) return -error_set_code(1, "%s", "Not implemented"); if(AO_GET_SIZE(definitions[i]) == 8) { u8 = ao->value.immediate.value; if(helper->write(helper->arch, &u8, 1) != 1) return -1; } else if(AO_GET_SIZE(definitions[i]) == 16) { u16 = _htob16(ao->value.immediate.value); if(helper->write(helper->arch, &u16, 2) != 2) return -1; } else if(AO_GET_SIZE(definitions[i]) == 32) { u32 = _htob32(ao->value.immediate.value); if(helper->write(helper->arch, &u32, 4) != 4) return -1; } else return -error_set_code(1, "%s", "Size not implemented"); } return 0; }
static int _call_operands_immediate(AsmArchOperandDefinition opdefinition, AsmArchOperand * operand) { uint64_t value; uint32_t size; /* check if the size fits */ value = operand->value.immediate.value; #if 0 /* XXX ignore for now */ if((size = AO_GET_SIZE(opdefinition)) > 0 && AO_GET_FLAGS(opdefinition) & AOF_SIGNED) size--; #else size = AO_GET_SIZE(opdefinition); #endif value >>= size; if(value > 0) return -1; /* check if it is signed */ if(operand->value.immediate.negative && !(AO_GET_FLAGS(opdefinition) & AOF_SIGNED)) return -1; return 0; }
/* arch_get_instruction_by_opcode */ AsmArchInstruction const * arch_get_instruction_by_opcode(AsmArch * arch, uint8_t size, uint32_t opcode) { size_t i; AsmArchInstruction const * ai; #ifdef DEBUG fprintf(stderr, "DEBUG: %s(arch, %u, 0x%x)\n", __func__, size, opcode); #endif for(i = 0; i < arch->instructions_cnt; i++) { ai = &arch->definition->instructions[i]; if(AO_GET_SIZE(ai->flags) != size) continue; if(ai->opcode == opcode) return ai; } return NULL; }
static int _call_operands_register(AsmArch * arch, AsmArchOperandDefinition opdefinition, AsmArchOperand * operand) { char const * name = operand->value._register.name; AsmArchDefinition const * definition; uint32_t size; AsmArchRegister const * ar; /* obtain the size */ if((definition = arch->definition->definition) != NULL && definition->instruction_size != 0) size = definition->instruction_size; else size = AO_GET_SIZE(opdefinition); /* check if it exists */ if((ar = arch_get_register_by_name_size(arch, name, size)) == NULL) return -1; /* for implicit instructions it must match */ if(AO_GET_FLAGS(opdefinition) & AOF_IMPLICIT && AO_GET_VALUE(opdefinition) != ar->id) return -1; return 0; }
/* java_decode */ static int _java_decode(AsmArchPlugin * plugin, AsmArchInstructionCall * call) { AsmArchPluginHelper * helper = plugin->helper; uint8_t u8; AsmArchInstruction const * ai; size_t i; AsmArchOperand * ao; uint16_t u16; uint32_t u32; AsmString * as; uint32_t begin; uint32_t end; if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8)) return -1; if((ai = helper->get_instruction_by_opcode(helper->arch, 8, u8)) == NULL) { call->name = "db"; call->operands[0].definition = AO_IMMEDIATE(0, 8, 0); call->operands[0].value.immediate.name = NULL; call->operands[0].value.immediate.value = u8; call->operands[0].value.immediate.negative = 0; call->operands_cnt = 1; return 0; } call->name = ai->name; /* tableswitch may be followed by padding */ if(ai->opcode == 0xaa && (i = call->offset % 4) > 0 && helper->read(helper->arch, &u32, i) != i) return -1; call->operands[0].definition = ai->op1; call->operands[1].definition = ai->op2; call->operands[2].definition = ai->op3; for(i = 0; i < 3 && AO_GET_TYPE(call->operands[i].definition) != AOT_NONE; i++) { ao = &call->operands[i]; if(AO_GET_TYPE(ao->definition) != AOT_IMMEDIATE) /* XXX should there be more types? */ return -error_set_code(1, "%s", "Not implemented"); if(AO_GET_SIZE(ao->definition) == 8) { if(helper->read(helper->arch, &u8, 1) != 1) return -1; ao->value.immediate.value = u8; } else if(AO_GET_SIZE(ao->definition) == 16) { if(helper->read(helper->arch, &u16, 2) != 2) return -1; u16 = _htob16(u16); ao->value.immediate.value = u16; } else if(AO_GET_SIZE(ao->definition) == 32) { if(helper->read(helper->arch, &u32, 4) != 4) return -1; u32 = _htob32(u32); ao->value.immediate.value = u32; } else return -error_set_code(1, "%s", "Size not implemented"); ao->value.immediate.name = NULL; ao->value.immediate.negative = 0; switch(AO_GET_VALUE(ao->definition)) { case AOI_REFERS_FUNCTION: case AOI_REFERS_STRING: as = helper->get_string_by_id(helper->arch, ao->value.immediate.value); if(as != NULL) ao->value.immediate.name = as->name; ao->value.immediate.negative = 0; break; } } call->operands_cnt = i; /* tableswitch may be followed by offsets */ if(ai->opcode == 0xaa) { for(begin = call->operands[1].value.immediate.value, end = call->operands[2].value.immediate.value; begin <= end; begin++) if(helper->read(helper->arch, &u32, sizeof(u32)) != (ssize_t)sizeof(u32)) return -1; } return 0; }