[llvm-commits] Specification for Run-time Checks

John Criswell criswell at illinois.edu
Fri May 11 07:38:36 PDT 2012


On 5/11/12 3:47 AM, Alexander Potapenko wrote:
> John,
>
> What if one needs to ensure that his load or store is within an object
> of unknown size (think polymorphism)?

The lscheck (which will be split into loadcheck and storecheck) is 
responsible for determining the bounds of the memory object into which 
the pointer points if that information is needed to perform the run-time 
check.  The bounds information is recorded by 
pool_register_heap/stack/global() if necessary.

In the case of SAFECode, pool_register_*() records the bounds 
information in a splay tree, and lscheck consults that splay tree to see 
if the pointer it is checking falls within the bounds of a valid object 
and, if so, whether the last byte of the memory access is within the 
same object.

Polymorphic code shouldn't be a problem.

> Will such a situation be emulated with a fastgepcheck(src, dest, base, 0)?
> (BTW what is |base| and isn't it the same as |src|?)

No.   If you're checking a GEP %r = gep %q, x, y, ..., then the result 
%r is dest and %q is source (i.e., %r is computed as an offset from 
%q).  The base argument is the first address of the memory object into 
which src and dest should point, and the length argument is the size of 
that memory allocation.  Remember that fastgepcheck is used when static 
analysis can determine which memory allocation site generate the memory 
object into which the pointer should point.

The parameters to a fastgepcheck/fastlscheck can be dynamically 
computed.  If you did something like:

%i = <some dynamically computed value>
%p = alloc char, %i // Allocate an array of 5 chars
%q = gep %p, 0, 3
%r = gep %q, 0, 2

..., then if you wanted a dynamic check on %r, you could do:

fastgepcheck (%q, %r, %p, %i)

which would check that the result of %q points into the same memory 
object as %q.  The optimization that changes gepcheck to fastgepcheck 
would have concluded that %r should be pointing into the alloca 
referenced by %p and that the number of bytes allocated by the alloca is %i.


>
> I also think that it may be useful to pass an additional argument that
> defines the pool being used to pool_[un]register_heap.
> On some systems several allocators may be present in the program, and
> it might be a good idea to distinguish between them.

First, I'm realizing that I should probably rename those functions so 
that they don't have the "pool" name.  That's a left-over from basing 
them off of the versions used in SAFECode.

Second, you're right that we need a tag argument to identify the type of 
allocator if multiple allocators are recognized (we did that in SVA for 
Linux).  That said, I'm not sure if we want to support non-malloc 
allocators in the initial design.

What we could do is replace the _stack, _heap, and _global versions of 
pool_register with a single version that takes an "allocator type" 
parameter.  The allocator type 0 would be global, 1 would be heap, 2 
would be malloc, and anything else could be reserved for future 
allocator support.

I'll go ahead and make the above change to the design document.

-- John T.




More information about the llvm-commits mailing list