This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [asan] Protection of stack vars
On Fri, Oct 12, 2012 at 11:10 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Fri, Oct 12, 2012 at 10:52:04AM -0700, Xinliang David Li wrote:
>> This is related to the way how you implement it. Emitting the stack
>> shadow initialization code in GIMPLE would solve the problem. I think
>> that would be cleaner.
>
> You'd need to duplicate all the stack slot sharing code, or adjust it so
> that it would be usable for both RTL and GIMPLE. IMHO much uglier.
I don't think you can have stack slot sharing with tsan, can you?
Unless the shadow initialization/clearing code is inserted at the
entry and exit of each lexical scope.
>
> I don't see how it would solve the problem where to put the cleanup
> sequence. Either you'd put it before tail calls and allow them to be
> tail call optimized (but you don't know at the GIMPLE level whether
> they will be or won't be tail call optimized), or you'd just put them
> after the calls, but then they wouldn't be tail call optimized ever.
Yes -- that is more natural way to disable tail call other than
checking the tsan flag :).
> It is really not a big deal to put the cleanup sequence somewhere,
> it is easy to disable tail call optimizations if var_end_seq is non-NULL,
> if we decide that is the way to go, or it is easy to put it before the
> calls.
> The reason I haven't implemented it is because I run out of hacking time for
> today.
>
>> > +static rtx
>> > +asan_shadow_cst (unsigned char shadow_bytes[4])
>>
>> Missing comments.
>
> Will add.
>>
>> > +{
>> > + int i;
>> > + unsigned HOST_WIDE_INT val = 0;
>> > + gcc_assert (WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN);
>> > + for (i = 0; i < 4; i++)
>> > + val |= (unsigned HOST_WIDE_INT) shadow_bytes[BYTES_BIG_ENDIAN ? 3 - i : i]
>> > + << (BITS_PER_UNIT * i);
>> > + return GEN_INT (trunc_int_for_mode (val, SImode));
>> > +}
>> > +
>> > +rtx
>> > +asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls,
>> > + int length)
>>
>> Missing comments.
>
> Likewise.
>
>> See my previous comment -- having this in rtl form makes the code less
>> readable and less maintainable.
>
> I disagree about that. I know in LLVM asan is implemented as a single pass
> transforming everything at once, but I don't think that is the best thing to
> do in GCC, actually I think it is better to let the instrumentation phase
> just emit an artificial builtin call instead of the shadow mem address
> computation, read, test, and conditional call (e.g. because then it won't
> prevent vectorization), and either lower it at some later point during
> GIMPLE, or just expand it to RTL directly.
The builtin idea sounds good. Without that, splitting the tsan
instrumentation code in two places sounds unreasonable to me --
especially for high level transformation like this.
thanks,
David
>
>> > /* A subroutine of expand_used_vars. Give each partition representative
>> > a unique location within the stack frame. Update each partition member
>> > with that location. */
>> >
>> > static void
>> > -expand_stack_vars (bool (*pred) (tree))
>> > +expand_stack_vars (bool (*pred) (tree), VEC(HOST_WIDE_INT, heap) **asan_vec,
>> > + VEC(tree, heap) **asan_decl_vec)
>>
>>
>> With the current implementation, the interface change can also be
>> avoided --- can the asan shadow var info be stashed into 'struct
>> stack_var' ?
>
> Yeah, sure, it can be groupped into a single struct. But it is just
> an interface between a helper function and the caller anyway, the reason
> for the separate expand_stack_vars function is that it needs to be called
> up to 3 times for -fstack-protector support.
>
> Jakub