Serious Bug All Targets -- Please Read

Till Straumann strauman at slac.stanford.edu
Wed Mar 4 05:20:38 UTC 2009


Ralf Corsepius wrote:
> Till Straumann wrote:
>> Ralf Corsepius wrote:
>>> Till Straumann wrote:
>>>> Ralf Corsepius wrote:
>>>>> Till Straumann wrote:
>>>>>> Ralf Corsepius wrote:
>>>>>>> Till Straumann wrote:
>>>>>>>> Hmm - AFAIK, c99 doesn't specify the exact representation
>>>>>>>> of 'bool' / '_Bool'. It only says that
>>>>>>>>
>>>>>>>> "An object declared as type _Bool is large enough to store the 
>>>>>>>> values 0 and 1"
>>>>>>>>
>>>>>>>> Hence, there is no really safe way to access such
>>>>>>>> an object from assembly code.
>>>>>>> Exactly.
>>>>>>>
>>>>>>>> I wonder if it wouldn't be better to change the
>>>>>>>> type of _Context_Switch_necessary & friends
>>>>>>>> to a type of known width.
>>>>>>> IMO, no.
>>>>>>>
>>>>>>> We should change to code into something which doesn't need to 
>>>>>>> know the size of a type, rsp. automatically gets it right.
>>>>>> So how would you do that given the requirement
>>>>>> that these variables need to be available to
>>>>>> assembly code, maybe w/o a stack available?
>>>>> E.g. by rewriting the code in question in C
>>>> That's what the new PPC framework does.
>>>>> w/ inline asm. This isn't always possible, but is possible on many 
>>>>> occasions, even when  stack is not available.
>>>> w/o stack I'm not sure...
>>> You can do something like this (Pseudo-C code):
>>>
>>> extern bool var;
>>>
>>> int _foo_stub(....)
>>> {
>>>   asm( ENTRY_SYMBOL(foo) );
>>>   asm( PROCESS(var) );
>>>
>>>   asm( RETURN );
>>> }
>> You can't be serious.
>>
> What's your problem with this? This is all valid C  and is not any 
> dirtier than using asm.
Inline assembly is *much* trickier than straight assembly
in a separate compilation unit because of the interaction
with the C-compiler which doesn't 'understand' what
the inline assembly does but makes certain assumptions
for optimization purposes. We have been bitten quite
a few times by delicate inline-assembly issues in the
recent past (as gcc optimization gets more aggressive).

Just one (recently seen) example of a subtle problem:

outF()
{
char ch = 'F';
  asm( <magic assembly copying memory pointed to by
       'address-register' to console>
      ::"a"(&ch)) ;
}

doesn't  work correctly because gcc doesn't know that
the inline assembly accesses/uses the value at &ch
and optimizes storing ch='F' away.

Here are some things that could happen to your proposed
hack:

1)  gcc could generate prologue instructions and emit them
    interspersed with the  'asm' statements. (quoting the gcc manual:
    "Note that even a volatile 'asm' instruction can be moved
    relative to other code,...")
    Hence, in order to keep everything together you'd have
    to use a single 'asm' construct.

2)  The whole point of using inline assembly, I assume, was
    to let gcc take care of the type promotion -- however, the
    code it generates for that purpose may either not be
    executed (if you use a single asm and jump to the
    entry point) or it may clobber registers.

Consider (ppc)

extern char foovar;

__foo()
{
    asm ("   .global FOO\n"
         "FOO:          \n"
         "   mr 3, %0"::"r"(foovar):"3");
    asm ("   b  FOORETURN");
}

which translates into

00000000 <__foo>:
   0:    3d 20 00 00     lis     r9,0
            2: R_PPC_ADDR16_HA    foovar
   4:    88 09 00 00     lbz     r0,0(r9)
            6: R_PPC_ADDR16_LO    foovar

00000008 <FOO>:
   8:    7c 03 03 78     mr      r3,r0
   c:    48 00 00 00     b       c <FOO+0x4>
            c: R_PPC_REL24    FOORETURN
  10:    4e 80 00 20     blr


=> if you jump to FOO 'r0' is not loaded
   with 'foovar'
=> if you jump to __foo then registers 0 and 9
   are clobbered (the only safe way would be
   calling __foo as a regular C-subroutine
   which requires a stack and also requires
   observing the C ABI from the calling
   assembly code).

-- Till
>
> Ralf




More information about the users mailing list