CCTLib
Calling-context and data-object attribution library for Intel Pin
exc_rethrow.cpp
Go to the documentation of this file.
1 // Rethrow: catch an exception, do some work, then re-raise via `throw;`.
2 // The outer handler then catches it. Two _Unwind_SetIP call chains per
3 // iteration.
4 //
5 // Four markers so both catch blocks are testable:
6 // rethrow_outer_try_marker inner-try body in main
7 // rethrow_inner_try_marker inner-try body in inner()
8 // rethrow_inner_catch_marker inner's catch body (before the re-throw)
9 // rethrow_outer_catch_marker main's catch body
10 // The shape checks assert each marker is a direct child of its enclosing
11 // function (main / inner), not descended from __cxa_throw.
12 #include <cstdint>
13 #include <cstdio>
14 #include <stdexcept>
15 #define ITERS 2000
16 static volatile uint64_t sink;
17 static uint64_t buf[ITERS];
18 
19 extern "C" __attribute__((noinline)) void rethrow_outer_try_marker(int i) {
20  __asm__ __volatile__("" ::: "memory"); sink ^= (uint64_t)i;
21 }
22 extern "C" __attribute__((noinline)) void rethrow_inner_try_marker(int i) {
23  __asm__ __volatile__("" ::: "memory"); sink ^= (uint64_t)i << 4;
24 }
25 extern "C" __attribute__((noinline)) void rethrow_inner_catch_marker(int i) {
26  __asm__ __volatile__("" ::: "memory"); sink ^= (uint64_t)i << 8;
27 }
28 extern "C" __attribute__((noinline)) void rethrow_outer_catch_marker(int i) {
29  __asm__ __volatile__("" ::: "memory"); sink ^= (uint64_t)i << 12;
30 }
31 
32 static void raise_it(int i) {
33  buf[i] = 0xA1;
34  throw std::runtime_error("first");
35 }
36 
37 static void inner(int i) {
38  try {
39  rethrow_inner_try_marker(i);
40  raise_it(i);
41  } catch (const std::exception& e) {
42  rethrow_inner_catch_marker(i);
43  (void)e;
44  buf[i] ^= 0xF0;
45  throw; // rethrow
46  }
47  buf[i] = 0xEE; // never reached
48 }
49 
50 int main(int argc, char** argv) {
51  (void)argc; (void)argv;
52  int caught = 0;
53  for (int i = 0; i < ITERS; ++i) buf[i] = 0x22;
54  for (int i = 0; i < ITERS; ++i) {
55  try {
56  rethrow_outer_try_marker(i);
57  inner(i);
58  } catch (const std::exception&) {
59  rethrow_outer_catch_marker(i);
60  buf[i] ^= 0x0F;
61  ++caught;
62  }
63  }
64  for (int i = 0; i < ITERS; ++i) sink ^= buf[i];
65  fprintf(stderr, "exc_rethrow: caught=%d iters=%d sink=%llx\n",
66  caught, ITERS, (unsigned long long)sink);
67  return caught == ITERS ? 0 : 1;
68 }
#define ITERS
Definition: exc_rethrow.cpp:15
int main(int argc, char **argv)
Definition: exc_rethrow.cpp:50
static uint64_t buf[ITERS]
Definition: exc_rethrow.cpp:17
static void raise_it(int i)
Definition: exc_rethrow.cpp:32
static void inner(int i)
Definition: exc_rethrow.cpp:37
__attribute__((noinline)) void rethrow_outer_try_marker(int i)
Definition: exc_rethrow.cpp:19
static volatile uint64_t sink
Definition: exc_rethrow.cpp:16