CCTLib
Calling-context and data-object attribution library for Intel Pin
deadspy_cmpxchg_tn.c
Go to the documentation of this file.
1 // Deadspy ISA edge case: LOCK CMPXCHG.
2 //
3 // This is a TRUE-NEGATIVE test. cmpxchg is a read-modify-write: it always
4 // reads the memory operand (to compare against RAX). Even when the second
5 // cmpxchg's compare succeeds (both stores happen), the intervening READ
6 // by the second cmpxchg CLEARS the shadow "was written" bit that the
7 // first cmpxchg set -- so deadspy should NOT report the first write as
8 // dead.
9 //
10 // Contrast this with XCHG (deadspy_xchg_tp.c): Pin classifies XCHG's
11 // memory operand as write-only (empirically), so deadspy sees two
12 // consecutive writes with no intervening read -> DOES report dead.
13 //
14 // The test that consumes this victim asserts the delta over baseline is
15 // SMALL (bounded above), verifying deadspy correctly does NOT
16 // false-positive on RMW instructions that read before they write.
17 #include <stdint.h>
18 #define WORK_COUNT 10000
19 static volatile uint64_t sink;
20 static uint64_t buf[WORK_COUNT];
21 int main(int argc, char** argv) {
22  (void)argc; (void)argv;
23  for (int i = 0; i < WORK_COUNT; ++i) buf[i] = 0xAAAAAAAAULL;
24 
25  for (int i = 0; i < WORK_COUNT; ++i) {
26  uint64_t expected = 0xAAAAAAAAULL;
27  uint64_t desired = 0xBBBBBBBBULL;
28  uint64_t desired2 = 0xCCCCCCCCULL;
29  __asm__ __volatile__(
30  "movq %[e], %%rax\n\t"
31  "lock cmpxchgq %[d], (%[p])\n\t" // rmw: read+write
32  "movq %[d], %%rax\n\t"
33  "lock cmpxchgq %[d2], (%[p])\n\t" // rmw: read (clears dead) + write
34  :
35  : [p] "r"(&buf[i]), [e] "r"(expected), [d] "r"(desired), [d2] "r"(desired2)
36  : "memory", "cc", "rax");
37  }
38  sink = buf[0];
39  return 0;
40 }
#define WORK_COUNT
int main(int argc, char **argv)
static uint64_t buf[WORK_COUNT]
static volatile uint64_t sink