Extend -fstack-protector-strong to cover calls with return slot

Florian Weimer fweimer@redhat.com
Fri Jan 3 21:43:00 GMT 2014


On 01/03/2014 07:57 PM, Jakub Jelinek wrote:

>> +/* Check if the basic block has a call which uses a return slot.  */
>> +
>> +static bool
>> +call_with_return_slot_opt_p (basic_block bb)
>> +{
>> +  for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
>> +       !gsi_end_p (gsi); gsi_next (&gsi))
>> +    {
>> +      gimple stmt = gsi_stmt (gsi);
>> +      if (gimple_code (stmt) == GIMPLE_CALL
>
> That would be is_gimple_call (stmt) instead.

Ah, it's not used consistently everywhere, and I got it from of the 
leftover places.

> Also, I'd think the function is misnamed, given that it checks if there
> are any calls with return_slot_opt_p in a bb.  I think it would be
> better to move FOR_ALL_BB_FN (bb, cfun) loop also into the
> function and call it any_call_...

I should probably move both loops (the one for declarations and the one 
for basic blocks) into its own function.

> Lastly, I wonder if gimple_call_return_slot_opt_p is really what you are
> after, why does NRV matter here?

The C code we generate does not construct the returned value in place 
(presumably because the partial write would be visible with threads, 
longjmp etc.), unlike the C++ code.

That's why I'm interested in instrumenting NRV-able calls only.  But 
gimple_call_return_slot_opt_p doesn't actually give me that.  The GIMPLE 
from the C test case looks like this (before and after applying your 
proposal):

foo11 ()
{
   int D.2265;
   struct B D.2266;

   D.2266 = global3 (); [return slot optimization]
   D.2265 = D.2266.a1;
   return D.2265;
}

In both cases, SSP instrumentation is applied:

         .type   foo11, @function
foo11:
.LFB24:
         .cfi_startproc
         subq    $56, %rsp
         .cfi_def_cfa_offset 64
         movq    %rsp, %rdi
         movq    %fs:40, %rax
         movq    %rax, 40(%rsp)
         xorl    %eax, %eax
         call    global3
         movq    40(%rsp), %rdx
         xorq    %fs:40, %rdx
         movl    (%rsp), %eax
         jne     .L50
         addq    $56, %rsp
         .cfi_remember_state
         .cfi_def_cfa_offset 8
         ret
.L50:
         .cfi_restore_state
         call    __stack_chk_fail
         .cfi_endproc

> Isn't what you are looking for instead
> whether the called function returns value through invisible reference,
> because then you'll always have some (aggregate) addressable object
> in the caller's frame and supposedly you are after making sure that the
> callee doesn't overflow the return object.
>
> So, looking at tree-nrv.c, that check would be roughly:
>            if (is_gimple_call (stmt)
>                && gimple_call_lhs (stmt)
>                && aggregate_value_p (TREE_TYPE (gimple_call_lhs (stmt)),
>                                      gimple_call_fndecl (stmt)))

When I do that, I get SSP instrumentation even when the struct is small 
enough to be returned in registers.  gimple_call_return_slot_opt_p 
returns false in this case.  So gimple_call_return_slot_opt_p appears to 
be misnamed (it's an ABI thing, not really an optimization), but it's 
closer to what I want.

-- 
Florian Weimer / Red Hat Product Security Team



More information about the Gcc-patches mailing list