-
Notifications
You must be signed in to change notification settings - Fork 32
Description
Currently, we do an intraprocedural analysis of the flow of 'sizeofness', so that e.g. in the following example we can infer that p points to a struct Foo.
size_t s = sizeof (struct Foo);
unsigned t = 2 * s;
void *p = malloc(t);
However, sizeofness is not tracked interprocedurally. A consequence is that it's necessary to declare a wrapper such as in this variation:
void *p = mymalloc(t);
and also a 'helper' such as in this variation:
unsigned t = get_size_of_struct_foo();
and some seen-in-the-wild cases are just not supported, such as (the 'perlbench case'):
struct blah {
...
size_t size_of_a_struct_foo;
...
} the_blah = { ..., sizeof (struct Foo), ...};
The 'helper' case is handled by a hack, where helpers can be declared much like a malloc wrapper, and we grossly assume that the preceding helper call executed in a given thread is the one that a given otherwise-unclassified malloc call should be associated with. This allows a simple implementation using a thread-local variable, but is easily foiled e.g. by computing two sizes but doing the allocations in the other order.
One idea for doing better: we can easily make 'sizeofness-returningness' an annotation whose completeness we check by a simple static analysis, i.e. warn if you return an expression having sizeofness but are not marked as a helper. Then instead of the thread-local hack, generate sizeofness at calls to helpers, just as we generate it at 'sizeof' itself... that's if helpers always generate same-type sizeofness.
To handle the perlbench case, use a link-time map for the case of static-constant values with sizeofness.