libipt, insn: check packet-to-instruction bindings using insn_ext
Instead of using struct pt_ild directly in pt_insn_binds_to_pip() and
pt_insn_binds_to_vmcs(), we use pt_insn and pt_insn_ext objects passed as
arguments. They replace the current pt_ild argument.
Move those functions to pt_insn.c.
Change-Id: Ic9b83a8eaf81d47ba115923bcc8db51cccfd5285
Signed-off-by: Markus Metzger <markus.t.metzger@intel.com>
diff --git a/libipt/internal/include/pt_insn.h b/libipt/internal/include/pt_insn.h
index 771f046..177326a 100644
--- a/libipt/internal/include/pt_insn.h
+++ b/libipt/internal/include/pt_insn.h
@@ -126,4 +126,25 @@
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 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);
+
#endif /* PT_INSN_H */
diff --git a/libipt/src/pt_insn.c b/libipt/src/pt_insn.c
index 52d6026..1989d6c 100644
--- a/libipt/src/pt_insn.c
+++ b/libipt/src/pt_insn.c
@@ -28,6 +28,8 @@
#include "pt_insn.h"
+#include "intel-pt.h"
+
int pt_insn_changes_cpl(const struct pt_insn *insn,
const struct pt_insn_ext *iext)
@@ -70,3 +72,56 @@
return 1;
}
}
+
+int pt_insn_is_far_branch(const struct pt_insn *insn,
+ const struct pt_insn_ext *iext)
+{
+ (void) iext;
+
+ if (!insn)
+ return 0;
+
+ switch (insn->iclass) {
+ default:
+ return 0;
+
+ case ptic_far_call:
+ case ptic_far_return:
+ case ptic_far_jump:
+ return 1;
+ }
+}
+
+int pt_insn_binds_to_pip(const struct pt_insn *insn,
+ const struct pt_insn_ext *iext)
+{
+ if (!iext)
+ return 0;
+
+ switch (iext->iclass) {
+ default:
+ return pt_insn_is_far_branch(insn, iext);
+
+ case PTI_INST_MOV_CR3:
+ case PTI_INST_VMLAUNCH:
+ case PTI_INST_VMRESUME:
+ return 1;
+ }
+}
+
+int pt_insn_binds_to_vmcs(const struct pt_insn *insn,
+ const struct pt_insn_ext *iext)
+{
+ if (!iext)
+ return 0;
+
+ switch (iext->iclass) {
+ default:
+ return pt_insn_is_far_branch(insn, iext);
+
+ case PTI_INST_VMPTRLD:
+ case PTI_INST_VMLAUNCH:
+ case PTI_INST_VMRESUME:
+ return 1;
+ }
+}
diff --git a/libipt/src/pt_insn_decoder.c b/libipt/src/pt_insn_decoder.c
index 2cc3997..9321d75 100644
--- a/libipt/src/pt_insn_decoder.c
+++ b/libipt/src/pt_insn_decoder.c
@@ -249,50 +249,6 @@
return ild->u.s.branch_far ? ptic_far_jump : ptic_jump;
}
-static int pt_insn_is_far_branch(const struct pt_ild *ild)
-{
- if (!ild)
- return 0;
-
- return ild->u.s.branch_far;
-}
-
-static int pt_insn_binds_to_pip(const struct pt_ild *ild)
-{
- if (!ild)
- return 0;
-
- switch (ild->iclass) {
- default:
- break;
-
- case PTI_INST_MOV_CR3:
- case PTI_INST_VMLAUNCH:
- case PTI_INST_VMRESUME:
- return 1;
- }
-
- return pt_insn_is_far_branch(ild);
-}
-
-static int pt_insn_binds_to_vmcs(const struct pt_ild *ild)
-{
- if (!ild)
- return 0;
-
- switch (ild->iclass) {
- default:
- break;
-
- case PTI_INST_VMPTRLD:
- case PTI_INST_VMLAUNCH:
- case PTI_INST_VMRESUME:
- return 1;
- }
-
- return pt_insn_is_far_branch(ild);
-}
-
/* Try to determine the next IP for @ild without using Intel PT.
*
* If @ip is not NULL, provides the determined IP on success.
@@ -1002,7 +958,7 @@
return 0;
case ptev_paging:
- if (pt_insn_binds_to_pip(&decoder->ild) &&
+ if (pt_insn_binds_to_pip(insn, iext) &&
!decoder->paging_event_bound) {
/* Each instruction only binds to one paging event. */
decoder->paging_event_bound = 1;
@@ -1013,7 +969,7 @@
return 0;
case ptev_vmcs:
- if (pt_insn_binds_to_vmcs(&decoder->ild) &&
+ if (pt_insn_binds_to_vmcs(insn, iext) &&
!decoder->vmcs_event_bound) {
/* Each instruction only binds to one vmcs event. */
decoder->vmcs_event_bound = 1;