CCTLib
Calling-context and data-object attribution library for Intel Pin
exc_deep_unwind.cpp
Go to the documentation of this file.
1 // Deep-stack exception unwind. Recurses to depth D, then throws.
2 // cctlib must correctly walk up the CCT past D frames when the exception
3 // handler resets tlsCurrentTraceNode.
4 //
5 // D and ITERS are picked so that the total CCT size (roughly D*ITERS
6 // trace nodes) fits under Pin's own C-stack budget for the recursive
7 // CCTLibFini/VisitAllNodesOfSplayTree walker. Deeper/wider is a
8 // separate stress that hits a Pin-side limit, not a cctlib exception
9 // bug.
10 //
11 // deep_try_marker / deep_catch_marker verify that the try-body call and
12 // the catch-body call are direct children of main and NOT descendants
13 // of __cxa_throw.
14 #include <cstdint>
15 #include <cstdio>
16 #define D 32
17 #define ITERS 200
18 static volatile uint64_t sink;
19 static uint64_t buf[ITERS];
20 
21 extern "C" __attribute__((noinline)) void deep_try_marker(int i) {
22  __asm__ __volatile__("" ::: "memory");
23  sink ^= (uint64_t)i;
24 }
25 extern "C" __attribute__((noinline)) void deep_catch_marker(int i) {
26  __asm__ __volatile__("" ::: "memory");
27  sink ^= (uint64_t)i << 8;
28 }
29 
30 static void recurse(int depth, int iter) {
31  // Force a stack write so each frame is materialized.
32  volatile uint64_t local = depth * 0x1010101ULL;
33  if (depth == 0) {
34  buf[iter] = local;
35  throw local;
36  }
37  recurse(depth - 1, iter);
38  // Never reached; keeps compiler from tail-call-optimizing away frames.
39  buf[iter] += local;
40 }
41 
42 int main(int argc, char** argv) {
43  (void)argc; (void)argv;
44  int ok = 0;
45  for (int i = 0; i < ITERS; ++i) {
46  try {
47  deep_try_marker(i);
48  recurse(D, i);
49  } catch (uint64_t v) {
50  deep_catch_marker(i);
51  (void)v;
52  ++ok;
53  }
54  }
55  for (int i = 0; i < ITERS; ++i) sink ^= buf[i];
56  fprintf(stderr, "exc_deep_unwind: depth=%d iters=%d ok=%d sink=%llx\n",
57  D, ITERS, ok, (unsigned long long)sink);
58  return ok == ITERS ? 0 : 1;
59 }
#define ITERS
int main(int argc, char **argv)
static uint64_t buf[ITERS]
__attribute__((noinline)) void deep_try_marker(int i)
static void recurse(int depth, int iter)
static volatile uint64_t sink
#define D