/* Check that an instruction * - can be length-decoded * - is correctly length-decoded * - can be classified * - is corectly diagnosed as interesting/boring * * Does not check whether the classification is correct. * This is left to the calling test. */ static struct ptunit_result ptunit_ild_decode(struct pt_ild *ild, int interest, uint8_t size) { int lret, dret; lret = pt_instruction_length_decode(ild); ptu_int_eq(lret, 1); ptu_uint_eq(ild->length, size); dret = pt_instruction_decode(ild); ptu_int_eq(dret, interest); return ptu_passed(); }
/* Decode and analyze one instruction. * * Decodes the instructruction at @decoder->ip into @insn and updates * @decoder->ip. * * Returns a negative error code on failure. * Returns zero on success if the instruction is not relevant for our purposes. * Returns a positive number on success if the instruction is relevant. * Returns -pte_bad_insn if the instruction could not be decoded. */ static int decode_insn(struct pt_insn *insn, struct pt_insn_decoder *decoder) { struct pt_ild *ild; int errcode, relevant; int size; if (!insn || !decoder) return -pte_internal; /* Fill in as much as we can as early as we can so we have the * information available in case of errors. */ if (decoder->speculative) insn->speculative = 1; insn->ip = decoder->ip; insn->mode = decoder->mode; /* Read the memory at the current IP in the current address space. */ size = pt_image_read(decoder->image, insn->raw, sizeof(insn->raw), &decoder->asid, decoder->ip); if (size < 0) return size; /* Decode the instruction. */ ild = &decoder->ild; ild->itext = insn->raw; ild->max_bytes = (uint8_t) size; ild->mode = decoder->mode; ild->runtime_address = decoder->ip; errcode = pt_instruction_length_decode(ild); if (errcode < 0) return errcode; insn->size = ild->length; relevant = pt_instruction_decode(ild); if (!relevant) insn->iclass = ptic_other; else { if (relevant < 0) return relevant; insn->iclass = pt_insn_classify(ild); } return relevant; }
/* Check whether @ip is ahead of us. * * Tries to reach @ip from @decoder->ip in @decoder->mode without Intel PT for * at most @steps steps. * * Does not update @decoder except for its image LRU cache. * * Returns non-zero if @ip can be reached, zero otherwise. */ static int pt_ip_is_ahead(struct pt_insn_decoder *decoder, uint64_t ip, size_t steps) { struct pt_ild ild; uint8_t raw[pt_max_insn_size]; if (!decoder) return 0; /* We do not expect execution mode changes. */ ild.mode = decoder->mode; ild.itext = raw; ild.runtime_address = decoder->ip; while (ild.runtime_address != ip) { int size, errcode; if (!steps--) return 0; /* If we can't read the memory for the instruction, we can't * reach it. */ size = pt_image_read(decoder->image, raw, sizeof(raw), &decoder->asid, ild.runtime_address); if (size < 0) return 0; ild.max_bytes = (uint8_t) size; errcode = pt_instruction_length_decode(&ild); if (errcode < 0) return 0; errcode = pt_instruction_decode(&ild); if (errcode < 0) return 0; errcode = pt_insn_next_ip(&ild.runtime_address, &ild); if (errcode < 0) return 0; } return 1; }
static int check_erratum_skd022(struct pt_insn_decoder *decoder) { struct pt_ild ild; uint8_t raw[pt_max_insn_size]; int size, errcode; if (!decoder) return -pte_internal; size = pt_image_read(decoder->image, raw, sizeof(raw), &decoder->asid, decoder->ip); if (size < 0) return 0; memset(&ild, 0, sizeof(ild)); ild.mode = decoder->mode; ild.max_bytes = (uint8_t) size; ild.itext = raw; ild.runtime_address = decoder->ip; errcode = pt_instruction_length_decode(&ild); if (errcode < 0) return 0; errcode = pt_instruction_decode(&ild); if (errcode < 0) return 0; switch (ild.iclass) { default: return 0; case PTI_INST_VMLAUNCH: case PTI_INST_VMRESUME: return 1; } }