static struct ptunit_result remove_by_asid(struct image_fixture *ifix) { uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; int status; status = pt_image_read(&ifix->image, buffer, 2, &ifix->asid[0], 0x1001ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], 0x01); ptu_uint_eq(buffer[1], 0x02); ptu_uint_eq(buffer[2], 0xcc); status = pt_image_remove_by_asid(&ifix->image, &ifix->asid[0]); ptu_int_eq(status, 1); ptu_int_ne(ifix->status[0].deleted, 0); ptu_int_eq(ifix->status[1].deleted, 0); status = pt_image_read(&ifix->image, buffer, sizeof(buffer), &ifix->asid[0], 0x1003ull); ptu_int_eq(status, -pte_nomap); ptu_uint_eq(buffer[0], 0x01); ptu_uint_eq(buffer[1], 0x02); ptu_uint_eq(buffer[2], 0xcc); status = pt_image_read(&ifix->image, buffer, 2, &ifix->asid[1], 0x2003ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], 0x03); ptu_uint_eq(buffer[1], 0x04); ptu_uint_eq(buffer[2], 0xcc); return ptu_passed(); }
static struct ptunit_result remove_none_by_filename(struct image_fixture *ifix) { uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; int status; status = pt_image_remove_by_filename(&ifix->image, "bad-name", &ifix->asid[0]); ptu_int_eq(status, 0); ptu_int_eq(ifix->status[0].deleted, 0); ptu_int_eq(ifix->status[1].deleted, 0); status = pt_image_read(&ifix->image, buffer, 2, &ifix->asid[0], 0x1003ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], 0x03); ptu_uint_eq(buffer[1], 0x04); ptu_uint_eq(buffer[2], 0xcc); status = pt_image_read(&ifix->image, buffer, 2, &ifix->asid[1], 0x2001ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], 0x01); ptu_uint_eq(buffer[1], 0x02); ptu_uint_eq(buffer[2], 0xcc); return ptu_passed(); }
static struct ptunit_result read_asid(struct image_fixture *ifix) { uint8_t buffer[] = { 0xcc, 0xcc }; int status; status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0], 0x1000ull); ptu_int_eq(status, 0); status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[1], 0x1008ull); ptu_int_eq(status, 0); status = pt_image_read(&ifix->image, buffer, 1, &ifix->asid[0], 0x1009ull); ptu_int_eq(status, 1); ptu_uint_eq(buffer[0], 0x09); ptu_uint_eq(buffer[1], 0xcc); status = pt_image_read(&ifix->image, buffer, 1, &ifix->asid[1], 0x1009ull); ptu_int_eq(status, 1); ptu_uint_eq(buffer[0], 0x01); ptu_uint_eq(buffer[1], 0xcc); return ptu_passed(); }
static struct ptunit_result remove_bad_asid(struct image_fixture *ifix) { uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; int status; status = pt_image_read(&ifix->image, buffer, 2, &ifix->asid[0], 0x1001ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], 0x01); ptu_uint_eq(buffer[1], 0x02); ptu_uint_eq(buffer[2], 0xcc); status = pt_image_remove(&ifix->image, &ifix->section[0], &ifix->asid[1], 0x1000ull); ptu_int_eq(status, -pte_bad_image); ptu_int_eq(ifix->status[0].deleted, 0); ptu_int_eq(ifix->status[1].deleted, 0); status = pt_image_read(&ifix->image, buffer, 2, &ifix->asid[0], 0x1003ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], 0x03); ptu_uint_eq(buffer[1], 0x04); ptu_uint_eq(buffer[2], 0xcc); status = pt_image_read(&ifix->image, buffer, 2, &ifix->asid[1], 0x2005ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], 0x05); ptu_uint_eq(buffer[1], 0x06); ptu_uint_eq(buffer[2], 0xcc); return ptu_passed(); }
static struct ptunit_result remove_all_by_filename(struct image_fixture *ifix) { uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; int status; ifix->section[0].filename = "same-name"; ifix->section[1].filename = "same-name"; status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0], 0x1000ull); ptu_int_eq(status, 0); status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[0], 0x2000ull); ptu_int_eq(status, 0); status = pt_image_read(&ifix->image, buffer, 2, &ifix->asid[0], 0x1001ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], 0x01); ptu_uint_eq(buffer[1], 0x02); ptu_uint_eq(buffer[2], 0xcc); status = pt_image_remove_by_filename(&ifix->image, "same-name", &ifix->asid[0]); ptu_int_eq(status, 2); ptu_int_ne(ifix->status[0].deleted, 0); ptu_int_ne(ifix->status[1].deleted, 0); status = pt_image_read(&ifix->image, buffer, sizeof(buffer), &ifix->asid[0], 0x1003ull); ptu_int_eq(status, -pte_nomap); ptu_uint_eq(buffer[0], 0x01); ptu_uint_eq(buffer[1], 0x02); ptu_uint_eq(buffer[2], 0xcc); status = pt_image_read(&ifix->image, buffer, sizeof(buffer), &ifix->asid[0], 0x2003ull); ptu_int_eq(status, -pte_nomap); ptu_uint_eq(buffer[0], 0x01); ptu_uint_eq(buffer[1], 0x02); ptu_uint_eq(buffer[2], 0xcc); return ptu_passed(); }
static struct ptunit_result read_null_asid(struct image_fixture *ifix) { uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; int status; status = pt_image_read(&ifix->image, buffer, 2, NULL, 0x2003ull); ptu_int_eq(status, -pte_internal); ptu_uint_eq(buffer[0], 0xcc); ptu_uint_eq(buffer[1], 0xcc); return ptu_passed(); }
static struct ptunit_result read_truncated(struct image_fixture *ifix) { uint8_t buffer[] = { 0xcc, 0xcc }; int status; status = pt_image_read(&ifix->image, buffer, sizeof(buffer), &ifix->asid[0], 0x100full); ptu_int_eq(status, 1); ptu_uint_eq(buffer[0], 0x0f); ptu_uint_eq(buffer[1], 0xcc); return ptu_passed(); }
static struct ptunit_result read_nomem(struct image_fixture *ifix) { uint8_t buffer[] = { 0xcc, 0xcc }; int status; status = pt_image_read(&ifix->image, buffer, sizeof(buffer), &ifix->asid[1], 0x1010ull); ptu_int_eq(status, -pte_nomap); ptu_uint_eq(buffer[0], 0xcc); ptu_uint_eq(buffer[1], 0xcc); return ptu_passed(); }
static struct ptunit_result adjacent(struct image_fixture *ifix) { uint8_t buffer[] = { 0xcc, 0xcc }; int status; status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0], 0x1000ull); ptu_int_eq(status, 0); status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[0], 0x1000ull - ifix->section[1].size); ptu_int_eq(status, 0); status = pt_image_add(&ifix->image, &ifix->section[2], &ifix->asid[0], 0x1000ull + ifix->section[0].size); ptu_int_eq(status, 0); status = pt_image_read(&ifix->image, buffer, 1, &ifix->asid[0], 0x1000ull); ptu_int_eq(status, 1); ptu_uint_eq(buffer[0], 0x00); ptu_uint_eq(buffer[1], 0xcc); status = pt_image_read(&ifix->image, buffer, 1, &ifix->asid[0], 0xfffull); ptu_int_eq(status, 1); ptu_uint_eq(buffer[0], ifix->mapping[1].content[ifix->mapping[1].size - 1]); ptu_uint_eq(buffer[1], 0xcc); status = pt_image_read(&ifix->image, buffer, 1, &ifix->asid[0], 0x1000ull + ifix->section[0].size); ptu_int_eq(status, 1); ptu_uint_eq(buffer[0], 0x00); ptu_uint_eq(buffer[1], 0xcc); return ptu_passed(); }
static struct ptunit_result read(struct image_fixture *ifix) { uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; int status; status = pt_image_read(&ifix->image, buffer, 2, &ifix->asid[1], 0x2003ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], 0x03); ptu_uint_eq(buffer[1], 0x04); ptu_uint_eq(buffer[2], 0xcc); 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; }
static struct ptunit_result read_empty(struct image_fixture *ifix) { struct pt_asid asid; uint8_t buffer[] = { 0xcc, 0xcc }; int status; pt_asid_init(&asid); status = pt_image_read(&ifix->image, buffer, sizeof(buffer), &asid, 0x1000ull); ptu_int_eq(status, -pte_nomap); ptu_uint_eq(buffer[0], 0xcc); ptu_uint_eq(buffer[1], 0xcc); return ptu_passed(); }
/* 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 struct ptunit_result read_callback(struct image_fixture *ifix) { uint8_t memory[] = { 0xdd, 0x01, 0x02, 0xdd }; uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; int status; status = pt_image_set_callback(&ifix->image, image_readmem_callback, memory); ptu_int_eq(status, 0); status = pt_image_read(&ifix->image, buffer, 2, &ifix->asid[0], 0x3001ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], 0x01); ptu_uint_eq(buffer[1], 0x02); ptu_uint_eq(buffer[2], 0xcc); return ptu_passed(); }
static struct ptunit_result copy_duplicate(struct image_fixture *ifix) { uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; int status; status = pt_image_add(&ifix->copy, &ifix->section[1], &ifix->asid[1], 0x2000ull); ptu_int_eq(status, 0); status = pt_image_copy(&ifix->copy, &ifix->image); ptu_int_eq(status, 1); status = pt_image_read(&ifix->copy, buffer, 2, &ifix->asid[1], 0x2003ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], 0x03); ptu_uint_eq(buffer[1], 0x04); ptu_uint_eq(buffer[2], 0xcc); return ptu_passed(); }
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; } }