The Canary mechanism imposes additional cost at two points in program execution:
We model this cost as a % overhead per function call. The % overhead is a function of the base cost of a function call, which varies depending on the number of arguments and the return type, so we studied a range of function types.
Increment | Standard | Canary | % |
Method | Run-Time | Run-Time | Overhead |
i++ | 15.1 | 15.1 | NA |
void inc() | 35.1 | 60.2 | 125% |
void inc(int *) | 47.7 | 70.2 | 69% |
int inc(int) | 40.1 | 60.2 | 80% |
The experiments seek to discover the % overhead of a function call imposed by StackGuard. We did this by writing a C program that increments a statically allocated integer 500,000,000 times. The base case is just ``i++'', and the experiments use various functions to increment the counter. The results are shown in Table 2. All experiments were performed on a 200 MHz Pentium-S with 512K of level 2 cache, and 128M of main memory.
The ``i++'' is the base case, and thus has no % overhead. The ``void inc()'' entry is a function that does i++ where i is a global variable; this shows the overhead of a zero-argument void function, and is the worst-possible case, showing a 125% overhead on function calls. The ``void inc(int *)'' entry is a function that takes an int * argument and increments it as a side-effect; this shows that there is 69% overhead on a one-argument void function. The ``int inc(int)'' entry is an applicative function that takes an int argument, and returns that value + 1; this shows that the overhead of a one-argument function returning an int is 80%.
Numerous other experiments are possible, but they all increase the base cost of function calls, while the cost of the Canary mechanism remains fixed at 7 instructions (see Figures 3 and 4), decreasing the Canary % overhead. Thus these overhead microbenchmarks can be considered an upper-bound on the cost of the Canary compiler.