mirror of
https://github.com/opnsense/src.git
synced 2026-02-27 03:40:37 -05:00
Its latest version merged from: ^/vendor/processor-trace/892e12c5a27bda5806d1e63269986bb4171b5a8b Sponsored by: DARPA, AFRL
212 lines
6.5 KiB
C
212 lines
6.5 KiB
C
/*
|
|
* Copyright (c) 2016-2019, Intel Corporation
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
* * Neither the name of Intel Corporation nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef PT_INSN_H
|
|
#define PT_INSN_H
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include "intel-pt.h"
|
|
|
|
struct pt_insn_ext;
|
|
|
|
|
|
/* A finer-grain classification of instructions used internally. */
|
|
typedef enum {
|
|
PTI_INST_INVALID,
|
|
|
|
PTI_INST_CALL_9A,
|
|
PTI_INST_CALL_FFr3,
|
|
PTI_INST_CALL_FFr2,
|
|
PTI_INST_CALL_E8,
|
|
PTI_INST_INT,
|
|
|
|
PTI_INST_INT3,
|
|
PTI_INST_INT1,
|
|
PTI_INST_INTO,
|
|
PTI_INST_IRET, /* includes IRETD and IRETQ (EOSZ determines) */
|
|
|
|
PTI_INST_JMP_E9,
|
|
PTI_INST_JMP_EB,
|
|
PTI_INST_JMP_EA,
|
|
PTI_INST_JMP_FFr5, /* REXW? */
|
|
PTI_INST_JMP_FFr4,
|
|
PTI_INST_JCC,
|
|
PTI_INST_JrCXZ,
|
|
PTI_INST_LOOP,
|
|
PTI_INST_LOOPE, /* aka Z */
|
|
PTI_INST_LOOPNE, /* aka NE */
|
|
|
|
PTI_INST_MOV_CR3,
|
|
|
|
PTI_INST_RET_C3,
|
|
PTI_INST_RET_C2,
|
|
PTI_INST_RET_CB,
|
|
PTI_INST_RET_CA,
|
|
|
|
PTI_INST_SYSCALL,
|
|
PTI_INST_SYSENTER,
|
|
PTI_INST_SYSEXIT,
|
|
PTI_INST_SYSRET,
|
|
|
|
PTI_INST_VMLAUNCH,
|
|
PTI_INST_VMRESUME,
|
|
PTI_INST_VMCALL,
|
|
PTI_INST_VMPTRLD,
|
|
|
|
PTI_INST_PTWRITE,
|
|
|
|
PTI_INST_LAST
|
|
} pti_inst_enum_t;
|
|
|
|
/* Information about an instruction we need internally in addition to the
|
|
* information provided in struct pt_insn.
|
|
*/
|
|
struct pt_insn_ext {
|
|
/* A more detailed instruction class. */
|
|
pti_inst_enum_t iclass;
|
|
|
|
/* Instruction-specific information. */
|
|
union {
|
|
/* For branch instructions. */
|
|
struct {
|
|
/* The branch displacement.
|
|
*
|
|
* This is only valid for direct calls/jumps.
|
|
*
|
|
* The displacement is applied to the address of the
|
|
* instruction following the branch.
|
|
*/
|
|
int32_t displacement;
|
|
|
|
/* A flag saying whether the branch is direct.
|
|
*
|
|
* non-zero: direct
|
|
* zero: indirect
|
|
*
|
|
* This is expected to go away someday when we extend
|
|
* enum pt_insn_class to distinguish direct and indirect
|
|
* branches.
|
|
*/
|
|
uint8_t is_direct;
|
|
} branch;
|
|
} variant;
|
|
};
|
|
|
|
|
|
/* Check if the instruction @insn/@iext changes the current privilege level.
|
|
*
|
|
* Returns non-zero if it does, zero if it doesn't (or @insn/@iext is NULL).
|
|
*/
|
|
extern int pt_insn_changes_cpl(const struct pt_insn *insn,
|
|
const struct pt_insn_ext *iext);
|
|
|
|
/* Check if the instruction @insn/@iext changes CR3.
|
|
*
|
|
* Returns non-zero if it does, zero if it doesn't (or @insn/@iext is NULL).
|
|
*/
|
|
extern int pt_insn_changes_cr3(const struct pt_insn *insn,
|
|
const struct pt_insn_ext *iext);
|
|
|
|
/* Check if the instruction @insn/@iext is a (near or far) branch.
|
|
*
|
|
* Returns non-zero if it is, zero if it isn't (or @insn/@iext is NULL).
|
|
*/
|
|
extern int pt_insn_is_branch(const struct pt_insn *insn,
|
|
const struct pt_insn_ext *iext);
|
|
|
|
/* Check if the instruction @insn/@iext is a far branch.
|
|
*
|
|
* Returns non-zero if it is, zero if it isn't (or @insn/@iext is NULL).
|
|
*/
|
|
extern int pt_insn_is_far_branch(const struct pt_insn *insn,
|
|
const struct pt_insn_ext *iext);
|
|
|
|
/* Check if the instruction @insn/@iext binds to a PIP packet.
|
|
*
|
|
* Returns non-zero if it does, zero if it doesn't (or @insn/@iext is NULL).
|
|
*/
|
|
extern int pt_insn_binds_to_pip(const struct pt_insn *insn,
|
|
const struct pt_insn_ext *iext);
|
|
|
|
/* Check if the instruction @insn/@iext binds to a VMCS packet.
|
|
*
|
|
* Returns non-zero if it does, zero if it doesn't (or @insn/@iext is NULL).
|
|
*/
|
|
extern int pt_insn_binds_to_vmcs(const struct pt_insn *insn,
|
|
const struct pt_insn_ext *iext);
|
|
|
|
/* Check if the instruction @insn/@iext is a ptwrite instruction.
|
|
*
|
|
* Returns non-zero if it is, zero if it isn't (or @insn/@iext is NULL).
|
|
*/
|
|
extern int pt_insn_is_ptwrite(const struct pt_insn *insn,
|
|
const struct pt_insn_ext *iext);
|
|
|
|
/* Determine the IP of the next instruction.
|
|
*
|
|
* Tries to determine the IP of the next instruction without using trace and
|
|
* provides it in @ip unless @ip is NULL.
|
|
*
|
|
* Returns zero on success, a negative error code otherwise.
|
|
* Returns -pte_bad_query if the IP can't be determined.
|
|
* Returns -pte_internal if @insn or @iext is NULL.
|
|
*/
|
|
extern int pt_insn_next_ip(uint64_t *ip, const struct pt_insn *insn,
|
|
const struct pt_insn_ext *iext);
|
|
|
|
/* Decode and analyze one instruction.
|
|
*
|
|
* Decodes the instructruction at @insn->ip in @insn->mode into @insn and @iext.
|
|
*
|
|
* If the instruction can not be decoded using a single memory read in a single
|
|
* section, sets @insn->truncated and reads the missing bytes from one or more
|
|
* other sections until either the instruction can be decoded or we're sure it
|
|
* is invalid.
|
|
*
|
|
* Returns the size in bytes on success, a negative error code otherwise.
|
|
* Returns -pte_bad_insn if the instruction could not be decoded.
|
|
*/
|
|
extern int pt_insn_decode(struct pt_insn *insn, struct pt_insn_ext *iext,
|
|
struct pt_image *image, const struct pt_asid *asid);
|
|
|
|
/* Determine if a range of instructions is contiguous.
|
|
*
|
|
* Try to proceed from IP @begin to IP @end in @asid without using trace.
|
|
*
|
|
* Returns a positive integer if we reach @end from @begin.
|
|
* Returns zero if we couldn't reach @end within @nsteps steps.
|
|
* Returns a negative error code otherwise.
|
|
*/
|
|
extern int pt_insn_range_is_contiguous(uint64_t begin, uint64_t end,
|
|
enum pt_exec_mode mode,
|
|
struct pt_image *image,
|
|
const struct pt_asid *asid,
|
|
size_t nsteps);
|
|
|
|
#endif /* PT_INSN_H */
|