API Subsets

In order to have a specific set of functions intercepted, libgreat introduces a concept of API Subsets. The intention is that the functions intercepted correspond to various sections of their respected standards, and that we may select subsets of these groups. Let's take a look at rand(), which is intercepted to return constants. You can see this in c99/stdlib_prng.c:

/* C99 7.20.2.1 The rand function */
int
rand(void)
{
    if (!great_subset("stdlib:prng:rand")
    && !great_subset("stdlib:prng:srand")) {
        return great_c99.rand();
    }

    /* guts of rand() here */
}

great_c99.rand is a pointer to the underlying system's rand(). So our implementation defaults to that if great_subset() says that our particular subset - named stdlib:prng:rand - is not selected for use.

Note also that we only default if srand is also not selected; it makes no sense to have one without the other, as the behaviour would break the standard semantics, since seeding would not produce the same sequence.

So, each function intercepted has a name selected from the list of active subsets. These names are fairly self-explanatory - for example, we have stdlib:memory:malloc, where "memory" is an arbitary group name intended to represent the structure within the C standard.

You can see the subset interface at shared/subset.h.

To select by these names, pass the environment variable $GREAT_SUBSETS, which takes a list of regular expressions. SelectingSubsets explains this from the user's perspective. The logs give a little insight into what's going on here:

clarion% LD_PRELOAD=libgreat_c99.so GREAT_SUBSETS='/:rand$' zsh -c 'echo $RANDOM $RANDOM $RANDOM'
Thu Mar 13 22:39:10 2008 libgreat_c99 GREAT_RANDOM_SEED INFO: Defaulting to 5489
Thu Mar 13 22:39:10 2008 libgreat_c99 GREAT_SUBSETS INFO: Registered subset: /:rand$/
Thu Mar 13 22:39:10 2008 libgreat_c99 stdlib:prng:srand DEFAULT
Thu Mar 13 22:39:10 2008 libgreat_c99 GREAT_PROBABILITY INFO: Defaulting to 0.5
Thu Mar 13 22:39:10 2008 libgreat_c99 stdlib:prng:rand DEFAULT
Thu Mar 13 22:39:10 2008 libgreat_c99 GREAT_PROBABILITY INFO: Defaulting to 0.5
Thu Mar 13 22:39:10 2008 libgreat_c99 stdlib:prng:rand [C99 7.20.2.1 P4] IB: Returning constant
Thu Mar 13 22:39:10 2008 libgreat_c99 GREAT_PROBABILITY INFO: Defaulting to 0.5
Thu Mar 13 22:39:10 2008 libgreat_c99 stdlib:prng:rand [C99 7.20.2.1 P4] IB: Returning constant
10962 7 7
clarion%

This overrides the default subset of /./, which matches everything. So in this example, zsh runs without incident, as things like malloc() are left as-is.