static struct ptunit_result unknown_ext2(struct packet_fixture *pfix, int exp) { int size; pfix->buffer[0] = pt_opc_ext; pfix->buffer[1] = pt_ext_ext2; pfix->buffer[2] = pt_ext2_bad; pfix->unknown = exp; size = pt_pkt_next(&pfix->decoder, &pfix->packet[1], sizeof(pfix->packet[1])); ptu_int_eq(size, exp); if (exp >= 0) { ptu_int_eq(pfix->packet[1].type, ppt_unknown); ptu_uint_eq(pfix->packet[1].size, (uint8_t) size); ptu_ptr_eq(pfix->packet[1].payload.unknown.packet, pfix->buffer); ptu_ptr_eq(pfix->packet[1].payload.unknown.priv, pfix); } return ptu_passed(); }
/* Check that an instruction is decoded correctly. */ static struct ptunit_result ptunit_ild_decode(uint8_t *raw, uint8_t size, enum pt_exec_mode mode) { struct pt_insn_ext iext; struct pt_insn insn; int errcode; memset(&iext, 0, sizeof(iext)); memset(&insn, 0, sizeof(insn)); memcpy(insn.raw, raw, size); insn.size = size; insn.mode = mode; errcode = pt_ild_decode(&insn, &iext); ptu_int_eq(errcode, 0); ptu_uint_eq(insn.size, size); ptu_int_eq(insn.iclass, ptic_other); ptu_int_eq(iext.iclass, PTI_INST_INVALID); return ptu_passed(); }
static struct ptunit_result read_offset(struct section_fixture *sfix) { uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; int status; status = pt_msec_read(&sfix->msec, buffer, 2, &sfix->asid, sfix->vaddr + 3); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], sfix->mapping.content[3]); ptu_uint_eq(buffer[1], sfix->mapping.content[4]); ptu_uint_eq(buffer[2], 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(); }
static struct ptunit_result fini(void) { struct ifix_mapping mapping; struct ifix_status status; struct pt_section section; struct pt_image image; struct pt_asid asid; int errcode; pt_asid_init(&asid); pt_init_section(§ion, NULL, &status, &mapping); pt_image_init(&image, NULL); errcode = pt_image_add(&image, §ion, &asid, 0x0ull); ptu_int_eq(errcode, 0); pt_image_fini(&image); ptu_int_eq(section.ucount, 0); ptu_int_eq(section.mcount, 0); ptu_int_eq(status.deleted, 1); return ptu_passed(); }
static struct ptunit_result read_overflow_32bit(struct section_fixture *sfix) { uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc }; int status; sfix_write(sfix, bytes); sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); ptu_ptr(sfix->section); status = pt_section_map(sfix->section); ptu_int_eq(status, 0); status = pt_section_read(sfix->section, buffer, 1, 0xff00000000ull); ptu_int_eq(status, -pte_nomap); ptu_uint_eq(buffer[0], 0xcc); status = pt_section_unmap(sfix->section); ptu_int_eq(status, 0); return ptu_passed(); }
static struct ptunit_result read_from_truncated(struct section_fixture *sfix) { uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc, 0xcc }; int status; sfix_write(sfix, bytes); sfix->section = pt_mk_section(sfix->name, 0x2ull, 0x10ull); ptu_ptr(sfix->section); status = pt_section_map(sfix->section); ptu_int_eq(status, 0); status = pt_section_read(sfix->section, buffer, 2, 0x1ull); ptu_int_eq(status, 1); ptu_uint_eq(buffer[0], bytes[3]); ptu_uint_eq(buffer[1], 0xcc); status = pt_section_unmap(sfix->section); ptu_int_eq(status, 0); return ptu_passed(); }
static struct ptunit_result query_not_taken(void) { struct pt_tnt_cache tnt_cache; int status; tnt_cache.tnt = 0ull; tnt_cache.index = 1ull; status = pt_tnt_cache_query(&tnt_cache); ptu_int_eq(status, 0); ptu_uint_eq(tnt_cache.index, 0); return ptu_passed(); }
/* Check that an instruction is decoded and classified correctly. */ static struct ptunit_result ptunit_ild_classify(uint8_t *raw, uint8_t size, enum pt_exec_mode mode, pti_inst_enum_t iclass) { struct pt_insn_ext iext; struct pt_insn insn; int errcode; memset(&iext, 0, sizeof(iext)); memset(&insn, 0, sizeof(insn)); memcpy(insn.raw, raw, size); insn.size = size; insn.mode = mode; errcode = pt_ild_decode(&insn, &iext); ptu_int_eq(errcode, 0); ptu_uint_eq(insn.size, size); ptu_int_eq(iext.iclass, iclass); return ptu_passed(); }
static struct ptunit_result read_nomem_asid(struct section_fixture *sfix) { struct pt_asid asid; uint8_t buffer[] = { 0xcc }; int status; pt_asid_init(&asid); asid.cr3 = 0xcece00ull; status = pt_msec_read(&sfix->msec, buffer, 2, &asid, sfix->vaddr); ptu_int_eq(status, -pte_nomap); ptu_uint_eq(buffer[0], 0xcc); return ptu_passed(); }
static struct ptunit_result map_unmap(struct section_fixture *sfix) { uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; int errcode; sfix_write(sfix, bytes); sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); ptu_ptr(sfix->section); errcode = pt_section_map(sfix->section); ptu_int_eq(errcode, 0); errcode = pt_section_map(sfix->section); ptu_int_eq(errcode, 0); errcode = pt_section_unmap(sfix->section); ptu_int_eq(errcode, 0); errcode = pt_section_unmap(sfix->section); ptu_int_eq(errcode, 0); return ptu_passed(); }
static struct ptunit_result sync_bwd_cutoff(struct sync_fixture *sfix) { const uint8_t *sync; int errcode; sfix_encode_psb(sfix->config.begin); sfix_encode_psb(sfix->config.end - ptps_psb); sfix->config.begin += 1; sfix->config.end -= 1; errcode = pt_sync_backward(&sync, sfix->config.end, &sfix->config); ptu_int_eq(errcode, -pte_eos); return ptu_passed(); }
static struct ptunit_result from_user_small(void) { struct pt_asid asid, user; int errcode; user.size = sizeof(user.size); errcode = pt_asid_from_user(&asid, &user); ptu_int_eq(errcode, 0); ptu_uint_eq(asid.size, sizeof(asid)); ptu_uint_eq(asid.cr3, pt_asid_no_cr3); ptu_uint_eq(asid.vmcs, pt_asid_no_vmcs); return ptu_passed(); }
static struct ptunit_result update_tnt_null_packet(void) { struct pt_tnt_cache tnt_cache; int errcode; tnt_cache.tnt = 42ull; tnt_cache.index = 12ull; errcode = pt_tnt_cache_update_tnt(&tnt_cache, NULL, NULL); ptu_int_eq(errcode, -pte_invalid); ptu_uint_eq(tnt_cache.tnt, 42ull); ptu_uint_eq(tnt_cache.index, 12ull); return ptu_passed(); }
static struct ptunit_result fetch_unknown_ext2(struct fetch_fixture *ffix) { const struct pt_decoder_function *dfun; int errcode; ffix->config.begin[0] = pt_opc_ext; ffix->config.begin[1] = pt_ext_ext2; ffix->config.begin[2] = pt_ext2_bad; errcode = pt_df_fetch(&dfun, ffix->config.begin, &ffix->config); ptu_int_eq(errcode, 0); ptu_ptr_eq(dfun, &pt_decode_unknown); return ptu_passed(); }
static struct ptunit_result remove_by_filename(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_filename(&ifix->image, ifix->section[0].filename, &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 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(); }
static struct ptunit_result read_default_asid(struct section_fixture *sfix) { struct pt_asid asid; uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; int status; pt_asid_init(&asid); status = pt_msec_read(&sfix->msec, buffer, 2, &asid, sfix->vaddr); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], sfix->mapping.content[0]); ptu_uint_eq(buffer[1], sfix->mapping.content[1]); ptu_uint_eq(buffer[2], 0xcc); return ptu_passed(); }
static struct ptunit_result update_tnt_not_empty(void) { struct pt_tnt_cache tnt_cache; struct pt_packet_tnt packet; int errcode; tnt_cache.tnt = 42ull; tnt_cache.index = 12ull; errcode = pt_tnt_cache_update_tnt(&tnt_cache, &packet, NULL); ptu_int_eq(errcode, -pte_bad_context); ptu_uint_eq(tnt_cache.tnt, 42ull); ptu_uint_eq(tnt_cache.index, 12ull); return ptu_passed(); }
static struct ptunit_result fetch_packet(struct fetch_fixture *ffix, const struct pt_packet *packet, const struct pt_decoder_function *df) { const struct pt_decoder_function *dfun; int errcode; errcode = pt_enc_next(&ffix->encoder, packet); ptu_int_ge(errcode, 0); errcode = pt_df_fetch(&dfun, ffix->config.begin, &ffix->config); ptu_int_eq(errcode, 0); ptu_ptr_eq(dfun, df); return ptu_passed(); }
static struct ptunit_result match_vmcs_false(void) { struct pt_asid lhs, rhs; int errcode; pt_asid_init(&lhs); pt_asid_init(&rhs); lhs.vmcs = 0x42000ull; rhs.vmcs = 0x23000ull; errcode = pt_asid_match(&lhs, &rhs); ptu_int_eq(errcode, 0); return ptu_passed(); }
static struct ptunit_result match_cr3(void) { struct pt_asid lhs, rhs; int errcode; pt_asid_init(&lhs); pt_asid_init(&rhs); lhs.cr3 = 0x2300ull; rhs.cr3 = 0x2300ull; errcode = pt_asid_match(&lhs, &rhs); ptu_int_eq(errcode, 1); return ptu_passed(); }
static struct ptunit_result from_user_big(void) { struct pt_asid asid, user; int errcode; user.size = sizeof(user) + 4; user.cr3 = 0x4200ull; user.vmcs = 0x23000ull; errcode = pt_asid_from_user(&asid, &user); ptu_int_eq(errcode, 0); ptu_uint_eq(asid.size, sizeof(asid)); ptu_uint_eq(asid.cr3, 0x4200ull); ptu_uint_eq(asid.vmcs, 0x23000ull); return ptu_passed(); }
static struct ptunit_result cutoff(struct packet_fixture *pfix, enum pt_packet_type type) { int size; pfix->packet[0].type = type; size = pt_enc_next(&pfix->encoder, &pfix->packet[0]); ptu_int_gt(size, 0); pfix->decoder.config.end = pfix->encoder.pos - 1; size = pt_pkt_next(&pfix->decoder, &pfix->packet[1], sizeof(pfix->packet[1])); ptu_int_eq(size, -pte_eos); return ptu_passed(); }
static struct ptunit_result cutoff_cyc(struct packet_fixture *pfix) { int size; pfix->packet[0].type = ppt_cyc; pfix->packet[0].payload.cyc.value = 0xa8; size = pt_enc_next(&pfix->encoder, &pfix->packet[0]); ptu_int_gt(size, 0); pfix->decoder.config.end = pfix->encoder.pos - 1; size = pt_pkt_next(&pfix->decoder, &pfix->packet[1], sizeof(pfix->packet[1])); ptu_int_eq(size, -pte_eos); return ptu_passed(); }
static struct ptunit_result update_tnt(void) { struct pt_tnt_cache tnt_cache; struct pt_packet_tnt packet; int errcode; pt_tnt_cache_init(&tnt_cache); packet.bit_size = 4ull; packet.payload = 8ull; errcode = pt_tnt_cache_update_tnt(&tnt_cache, &packet, NULL); ptu_int_eq(errcode, 0); ptu_uint_eq(tnt_cache.tnt, 8ull); ptu_uint_eq(tnt_cache.index, 1ull << 3); return ptu_passed(); }
static struct ptunit_result cutoff_mode(struct packet_fixture *pfix, enum pt_mode_leaf leaf) { int size; pfix->packet[0].type = ppt_mode; pfix->packet[0].payload.mode.leaf = leaf; size = pt_enc_next(&pfix->encoder, &pfix->packet[0]); ptu_int_gt(size, 0); pfix->decoder.config.end = pfix->encoder.pos - 1; size = pt_pkt_next(&pfix->decoder, &pfix->packet[1], sizeof(pfix->packet[1])); ptu_int_eq(size, -pte_eos); return ptu_passed(); }
/* Check that an invalid instruction is detected correctly. * * Note that we intentionally do not detect all invalid instructions. This test * therefore only covers some that we care about. */ static struct ptunit_result ptunit_ild_invalid(uint8_t *raw, uint8_t size, enum pt_exec_mode mode) { struct pt_insn_ext iext; struct pt_insn insn; int errcode; memset(&iext, 0, sizeof(iext)); memset(&insn, 0, sizeof(insn)); memcpy(insn.raw, raw, size); insn.size = size; insn.mode = mode; errcode = pt_ild_decode(&insn, &iext); ptu_int_eq(errcode, -pte_bad_insn); return ptu_passed(); }
static struct ptunit_result map_overflow(struct section_fixture *sfix) { uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; int errcode; sfix_write(sfix, bytes); sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); ptu_ptr(sfix->section); sfix->section->mcount = UINT16_MAX; errcode = pt_section_map(sfix->section); ptu_int_eq(errcode, -pte_internal); sfix->section->mcount = 0; return ptu_passed(); }
static struct ptunit_result read_unmap_map(struct section_fixture *sfix) { uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; int status; sfix_write(sfix, bytes); sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); ptu_ptr(sfix->section); status = pt_section_map(sfix->section); ptu_int_eq(status, 0); status = pt_section_read(sfix->section, buffer, 2, 0x0ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], bytes[1]); ptu_uint_eq(buffer[1], bytes[2]); ptu_uint_eq(buffer[2], 0xcc); memset(buffer, 0xcc, sizeof(buffer)); status = pt_section_unmap(sfix->section); ptu_int_eq(status, 0); status = pt_section_read(sfix->section, buffer, 2, 0x0ull); ptu_int_eq(status, -pte_nomap); ptu_uint_eq(buffer[0], 0xcc); ptu_uint_eq(buffer[1], 0xcc); ptu_uint_eq(buffer[2], 0xcc); status = pt_section_map(sfix->section); ptu_int_eq(status, 0); status = pt_section_read(sfix->section, buffer, 2, 0x0ull); ptu_int_eq(status, 2); ptu_uint_eq(buffer[0], bytes[1]); ptu_uint_eq(buffer[1], bytes[2]); ptu_uint_eq(buffer[2], 0xcc); status = pt_section_unmap(sfix->section); ptu_int_eq(status, 0); return ptu_passed(); }