CCTLib
Calling-context and data-object attribution library for Intel Pin
pin_isa_compat.H
Go to the documentation of this file.
1 // @COPYRIGHT@
2 // Licensed under MIT license.
3 // See LICENSE.TXT file in the project root for more information.
4 // ==============================================================
5 //
6 // pin_isa_compat.H
7 // -----------------
8 // Shims for a handful of Pin-2.x/3.x APIs that were removed or renamed in
9 // Pin 4.x. Included by CCTLib client tools so that the source can keep
10 // using the pre-Pin-4 names without runtime cost.
11 //
12 // All shims are inline / #define; they cost nothing at analysis time.
13 // The two helpers that must scan operands (MemoryReadSize/MemoryWriteSize)
14 // are only ever invoked from instrumentation callbacks (BBL_/TRACE_ once
15 // per instruction), NOT from per-access analysis routines, so a small
16 // loop over operands is fine.
17 //
18 // Reference: Pin 4.x README "Breaking Changes Between Pin 3 and Pin 4"
19 // and "Recent Changes" sections list the removed APIs.
20 //
21 #ifndef CCTLIB_PIN_ISA_COMPAT_H
22 #define CCTLIB_PIN_ISA_COMPAT_H
23 
24 #include "pin.H"
25 // PINTOOL_REGISTER is a wide union (up to 1024B) that fills the same role
26 // as the old PIN_REGISTER union. Same field names (byte/word/dword/qword/
27 // s_byte/s_word/s_dword/s_qword/flt/dbl), so source code that read fields
28 // off a PIN_REGISTER* keeps compiling unchanged after the typedef below.
29 #include "regvalue_utils.h"
30 
31 // -----------------------------------------------------------------------
32 // Type / register renames
33 // -----------------------------------------------------------------------
34 // Pin 4.x replaced the PIN_REGISTER union with the wider PINTOOL_REGISTER
35 // (see $PIN_ROOT/source/tools/Utils/regvalue_utils.h). The union has the
36 // same field names, so a plain typedef is safe and callback signatures
37 // keep matching IARG_REG_REFERENCE / IARG_REG_CONST_REFERENCE.
38 using PIN_REGISTER = PINTOOL_REGISTER;
39 
40 // REG_is_in_X87(reg) -> REG_is_st(reg). Same semantics: true iff `reg` is
41 // one of the x87 stack registers ST0..ST7 (REG_CLASS_ST).
42 static inline BOOL REG_is_in_X87(REG reg) {
43  return REG_is_st(reg);
44 }
45 
46 // -----------------------------------------------------------------------
47 // Instruction predicates
48 // -----------------------------------------------------------------------
49 // INS_IsIndirectBranchOrCall(ins) -> INS_IsIndirectControlFlow(ins).
50 // The new name is broader (also matches indirect JMP FAR), but for the
51 // filtering these clients do it is a strict superset with the same intent.
52 static inline BOOL INS_IsIndirectBranchOrCall(INS ins) {
53  return INS_IsIndirectControlFlow(ins);
54 }
55 
56 // INS_IsMaskedJump(ins) was removed in Pin 4. In older Pin releases it
57 // returned true for the "predicated" jumps that always execute but whose
58 // target is determined by a register/state test: JECXZ, JCXZ, JRCXZ, and
59 // the LOOP family. CCTLib clients call it (together with INS_IsFarJump/
60 // INS_IsDirectFarJump) purely to *skip* these edge-case control-flow
61 // instructions from redundancy analysis. Reproducing the same set is
62 // therefore safe and matches the historical semantics.
63 static inline BOOL INS_IsMaskedJump(INS ins) {
64  switch (INS_Opcode(ins)) {
65  case XED_ICLASS_JECXZ:
66  case XED_ICLASS_JCXZ:
67  case XED_ICLASS_JRCXZ:
68  case XED_ICLASS_LOOP:
69  case XED_ICLASS_LOOPE:
70  case XED_ICLASS_LOOPNE:
71  return TRUE;
72  default:
73  return FALSE;
74  }
75 }
76 
77 // -----------------------------------------------------------------------
78 // Memory operand sizes
79 // -----------------------------------------------------------------------
80 // INS_MemoryReadSize(ins) == sum over read operands of INS_MemoryOperandSize
81 // INS_MemoryWriteSize(ins) == sum over write operands of INS_MemoryOperandSize
82 //
83 // The vast majority of x86 instructions have exactly one memory operand,
84 // so this reduces to a single conditional load. We keep the loop generic
85 // so vector gathers/scatters, XCHG-with-memory, MOVS, etc. are handled
86 // correctly. Only used at instrumentation time; not on the analysis hot
87 // path.
88 static inline USIZE INS_MemoryReadSize(INS ins) {
89  USIZE total = 0;
90  const UINT32 n = INS_MemoryOperandCount(ins);
91  for (UINT32 i = 0; i < n; ++i) {
92  if (INS_MemoryOperandIsRead(ins, i))
93  total += INS_MemoryOperandSize(ins, i);
94  }
95  return total;
96 }
97 
98 static inline USIZE INS_MemoryWriteSize(INS ins) {
99  USIZE total = 0;
100  const UINT32 n = INS_MemoryOperandCount(ins);
101  for (UINT32 i = 0; i < n; ++i) {
102  if (INS_MemoryOperandIsWritten(ins, i))
103  total += INS_MemoryOperandSize(ins, i);
104  }
105  return total;
106 }
107 
108 #endif // CCTLIB_PIN_ISA_COMPAT_H
static USIZE INS_MemoryReadSize(INS ins)
static BOOL INS_IsMaskedJump(INS ins)
static BOOL INS_IsIndirectBranchOrCall(INS ins)
static USIZE INS_MemoryWriteSize(INS ins)
PINTOOL_REGISTER PIN_REGISTER
static BOOL REG_is_in_X87(REG reg)