public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* RE: [PATCH] C undefined behavior fix
@ 2002-01-03 10:05 Bernard Dautrevaux
  2002-01-03 10:49 ` Paul Mackerras
  0 siblings, 1 reply; 202+ messages in thread
From: Bernard Dautrevaux @ 2002-01-03 10:05 UTC (permalink / raw)
  To: 'Tom Rini', jtv
  Cc: Richard Henderson, Momchil Velikov, linux-kernel, gcc,
	linuxppc-dev, Franz Sirl, Paul Mackerras, Benjamin Herrenschmidt,
	Corey Minyard

> -----Original Message-----
> From: Tom Rini [mailto:trini@kernel.crashing.org]
> Sent: Thursday, January 03, 2002 12:13 AM
> To: jtv
> Cc: Richard Henderson; Momchil Velikov; linux-kernel@vger.kernel.org;
> gcc@gcc.gnu.org; linuxppc-dev@lists.linuxppc.org; Franz Sirl; Paul
> Mackerras; Benjamin Herrenschmidt; Corey Minyard
> Subject: Re: [PATCH] C undefined behavior fix
> 
> 
> On Wed, Jan 02, 2002 at 11:23:21PM +0100, jtv wrote:
> > On Wed, Jan 02, 2002 at 03:05:48PM -0700, Tom Rini wrote:
> > > 
> > > Well, the problem is that we aren't running where the 
> compiler thinks we
> > > are yet.  So what would the right fix be for this?
> > 
> > Obviously -ffreestanding isn't, because this problem could 
> crop up pretty
> > much anywhere.  The involvement of standard library 
> functions is almost
> > coincidence and so -ffreestanding would only fix the 
> current symptom.
> 
> After thinking about this a bit more, why wouldn't this be 
> the fix?  The
> problem is that gcc is assuming that this is a 'normal' program (or in
> this case, part of a program) and that it, and that the standard rules
> apply, so it optimizes the strcpy into a memcpy.  But in this 
> small bit
> of the kernel, it's not.  It's not even using the 'standard library
> functions', but what the kernel provides.  This problem can 
> only crop up
> in the time before we finish moving ourself around.

OH... are you saying that the Linux kernel is not writtent in ANSI C? AFAICR
the standard *requires* that the standard library functions have their
standard meaning. So if the Linux kernel expects them to have some special
meaning it is *non-conforming* and then you need a *special* compiler,
understanding this.

OTOH if you only says that the Linux kernel is built with versions of
strcpy/memcpy that have the exact meaning required by the standard but are
not found in th ecompiler's library, then the program is still OK, but the
compiler is *allowed* to use the optimisations it wants to, regarding the
semantics of strcpy/memcpy. And anyway, in this case the "-ffreestanding"
option is *required* as this is what warn the compiler to use an
strcpy/memcpy/... implementation that *the program" provides instead of the
one that the compiler choose to provide (either by inlining or linking
against the library).

But tho whoel point here is that the RELOC macro has an undefined behaviour;
even if -ffreestanding solves the *current* problem, it's unsafe to build
*any* program on undefined behaviour (and particularly such for the kernel
itself...).

	Bernard

--------------------------------------------
Bernard Dautrevaux
Microprocess Ingenierie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-10 19:01 Bernard Dautrevaux
  0 siblings, 0 replies; 202+ messages in thread
From: Bernard Dautrevaux @ 2002-01-10 19:01 UTC (permalink / raw)
  To: 'dewar@gnat.com', Bernard Dautrevaux, pkoning
  Cc: gcc, linux-kernel, mrs

> -----Original Message-----
> From: dewar@gnat.com [mailto:dewar@gnat.com]
> Sent: Thursday, January 10, 2002 1:19 PM
> To: Dautrevaux@microprocess.com; dewar@gnat.com; 
> pkoning@equallogic.com
> Cc: gcc@gcc.gnu.org; linux-kernel@vger.kernel.org; mrs@windriver.com
> Subject: RE: [PATCH] C undefined behavior fix
> 
> 
> <<Note that this is not too much of a problem for system 
> programming, as you
> have a way to be sure they are not combined: just use 
> intermediate variables
> and set them separately; the nice thing there is that as you use these
> intermediate variables just once, the compiler will eliminate 
> them. But be
> careful: the sequence point MUST BE RETAINED, and then the 
> two loads cannot
> be combined (in case 1 of course).
> >>
> 
> Of course we all understand that sequence points myust be 
> retained, but this
> is a weak condition compared to the rule that all loads and stores for
> volatile variables must not be resequenced, and in 
> particular, you seem to
> agree that two loads *can* be combined if they both appear between two
> sequence points. I think that's unfortunate, and it is why in Ada we
> adopted a stricter point of view that avoids the notion of 
> sequence points.

What I said was that the C standard seems to allow two accesses to two
adjacent volatile variable with no intervening sequence point to be replaced
by one access to both variables together; and I think I was clear that,
IMHO, this should be avoided for volatile to be useful for system
programming.

My other remark was that by inserting a sequence point you solve this
possible problem without the need for any extension or specific
implementation defined behaviour.

Note that IMO volatile should be obeyed in C about like Volatile/Atomic is
in Ada; that is do exactly the access requested, no more, no less, with the
requested size.

> 
> It even seems that if you have two stores between two 
> sequence points then
> the compiler is free to omit one, and again that seems the 
> wrong decision
> for the case of volatile variables. If it can omit a store in 
> this way, can
> it omit a load, i.e. if we have:
> 
>    x := v - v;
> 
> can someone read the sequence point rule to mean that the compiler is
> free to do only one load here? I hope not, but we have 
> already seen how
> much confusion there is on this point.

Oh no; you would omit one side effect on v. What i said is that if we have
something like:

   union {
	struct {
	   volatile unsigned char x1;
	   volatile unsigned char x2;
	} X;
	volatile unsigned short Y;
   } u;

the compiler could be allowed to handle ((u.X.x1 << 256) | u.X.x2) as if
we've written (u.Y), on a big-endian architecture of course. However saying
that it seems standard-compliant does not mean we should do it in GCC; in
fact my all argument is that I would like we explicitely decide NOT to do
this or any other kind of wider/shorter access to volatile variable, as the
compiler does for now. 

Note that in fact it seems as while larger loads may be standard compilant
if the compiler ensures it is not reading another volatile object, shorter
writes, as those that gcc-3.95.3 generates, seems to be a genuine bug. I
would submit a bug-report if anybody can confirm the problem I already
mentioned here is there in 3.0 (or when I have time to install 3.0 and
test).

	Bernard

PS: perhaps as someone suggested this thread could be limited to gcc ML
instead of both GCC (which I subscribe to) and LKML (which I don't).

--------------------------------------------
Bernard Dautrevaux
Microprocess Ingenierie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-10 12:18 dewar
  2002-01-10 12:37 ` Erik Trulsson
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-10 12:18 UTC (permalink / raw)
  To: Dautrevaux, dewar, pkoning; +Cc: gcc, linux-kernel, mrs

<<Note that this is not too much of a problem for system programming, as you
have a way to be sure they are not combined: just use intermediate variables
and set them separately; the nice thing there is that as you use these
intermediate variables just once, the compiler will eliminate them. But be
careful: the sequence point MUST BE RETAINED, and then the two loads cannot
be combined (in case 1 of course).
>>

Of course we all understand that sequence points myust be retained, but this
is a weak condition compared to the rule that all loads and stores for
volatile variables must not be resequenced, and in particular, you seem to
agree that two loads *can* be combined if they both appear between two
sequence points. I think that's unfortunate, and it is why in Ada we
adopted a stricter point of view that avoids the notion of sequence points.

It even seems that if you have two stores between two sequence points then
the compiler is free to omit one, and again that seems the wrong decision
for the case of volatile variables. If it can omit a store in this way, can
it omit a load, i.e. if we have:

   x := v - v;

can someone read the sequence point rule to mean that the compiler is
free to do only one load here? I hope not, but we have already seen how
much confusion there is on this point.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-10  9:03 Bernard Dautrevaux
  2002-01-10 10:40 ` David Weinehall
  0 siblings, 1 reply; 202+ messages in thread
From: Bernard Dautrevaux @ 2002-01-10  9:03 UTC (permalink / raw)
  To: 'Paul Koning', dewar; +Cc: mrs, gcc, linux-kernel

> -----Original Message-----
> From: Paul Koning [mailto:pkoning@equallogic.com]
> Sent: Wednesday, January 09, 2002 10:44 PM
> To: dewar@gnat.com
> Cc: mrs@windriver.com; gcc@gcc.gnu.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH] C undefined behavior fix
> 
> 
> >>>>> "dewar" == dewar  <dewar@gnat.com> writes:
> 
> > <<Ah... so (paraphrasing) -- if you have two byte size
> > volatile objects, and they happen to end up adjacent in
> > memory, the compiler is explicitly forbidden from turning an
> > access to one of them into a wider access -- because that
> > would be an access to both of them, which is a *different*
> > side effect.  (Certainly that exactly matches the
> > hardware-centric view of why "volatile" exists.)  And the
> > compiler isn't allowed to change side effects, including
> > causing them when the source code didn't ask you to cause
> > them.
> 
>  dewar> Right, and as you see that is covered by the language on
>  dewar> external effects in the Ada standard (remember the intent in
>  dewar> Ada was to exactly match the C rules :-)
> 
>  dewar> But one thing in the Ada world that we consider left open is
>  dewar> whether a compiler is free to combine two volatile loads into
>  dewar> a single load. Probably the answer should be no, but the
>  dewar> language at least in the Ada standard does not seem strong
>  dewar> enough to say this.
> 
> Would ordering rules help answer that?  If you write two separate
> loads you have two separate side effects that are ordered in time,
> while for a single big load they occur concurrently.  If the construct
> where those two loads occur does not allow for side effects to be
> interleaved, then the "as if" principle seems to say you cannot
> legally merge the loads.


Of course ordering rules must be obeyed, and side effects cannot be moved
across sequence points. Thus if the two volatile loads are in separate
instructions, as in:

	int x1, x2;
	volatile unsigned char x1, x2;
	x1 = v1;
	x2 = v2;

Then you're NOT allowed to combined them. However if there is no sequence
points between them the compiler is free to do it (although I'm not sure it
will...) as in e.g.:

	x1 = v1 << 8 + v2;

Note that this is not too much of a problem for system programming, as you
have a way to be sure they are not combined: just use intermediate variables
and set them separately; the nice thing there is that as you use these
intermediate variables just once, the compiler will eliminate them. But be
careful: the sequence point MUST BE RETAINED, and then the two loads cannot
be combined (in case 1 of course).

	Bernard

--------------------------------------------
Bernard Dautrevaux
Microprocess Ingenierie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-10  4:33 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-10  4:33 UTC (permalink / raw)
  To: dewar, tim
  Cc: Dautrevaux, gcc, groudier, jamagallon, jtv, linux-kernel, paulus,
	trini, velco

a; b = 1;

yes, that's a permissible transformation, and it is interesting to note
that the normally useless C statement

 a;

has a useful meaning for volatile variables :-)

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-10  2:16 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-10  2:16 UTC (permalink / raw)
  To: fjh, pbarada; +Cc: gcc, linux-kernel

<< |        [#5] The least requirements on a  conforming  implementation
 |        are:
 |
 |          -- At  sequence points, volatile objects are stable in the
 |             sense  that  previous   accesses   are   complete   and
 |             subsequent accesses have not yet occurred.
>>

Note that this particular requirement is much laxer than that in the 
Ada standard, since it is specialized to sequence points, and would
appear to allow reordering of accesses between sequence points)

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-10  1:22 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-10  1:22 UTC (permalink / raw)
  To: jamagallon, pbarada
  Cc: Dautrevaux, dewar, gcc, groudier, jtv, linux-kernel, paulus, tim,
	trini, velco

Peter said

<<Then the code can be optimized to 'b = 0;' since nowhere in the scope
of 'a' does anyone take its address(which would allow it to be changed).
Of course if 'a' is external then another function can access its
address.
>>

Well if nothing else this shows that there is still significant disagreement.
I consider Peter's statement to be 100% wrong here, optimizing away the
access to b would be a clear violation of the standard. I thought that
the argument had been made in a clear and convincing manner, but apparently
some people completely refuse to be convinced!

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-10  1:21 dewar
  2002-01-10  4:37 ` Tim Hollebeek
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-10  1:21 UTC (permalink / raw)
  To: groudier, jamagallon
  Cc: Dautrevaux, dewar, gcc, jtv, linux-kernel, paulus, tim, trini,
	velco

<<Grrr. I really do not know why people is making so noise about volatile.
Don't look for esoteric meanings, it is just 'don't suppose ANYTHING
about this memory location, it CAN CNAHGE apart from anything you can
see or guess'.
>>

Nope, that's not enough, it's not that simple. Yes your
example of a-a is of course straightforward but what about

    b = (a & 1) | (b & 1);

if a is volatile and b is known to be odd, can the read of a be eliminated?
The answer should be no (and I think the standard guarantees this), but the
reasoning is completely different from thinking about the fact that a may
change unexpectedly, since obviously no matter what value comes from
reading a, b will be set to 1 if b is known to be odd.

Of course you can provide a pragmatic justification, think of a as a hardware
counter that counts the number of times it is referenced, then this should
count as a reference, even though on an as-if basis b would have the same
value.

The Ada standard says it clearly: a read or write of a volatile variable
is an external effect. period.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-09 21:54 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-09 21:54 UTC (permalink / raw)
  To: dewar, pkoning; +Cc: gcc, linux-kernel, mrs

<<Would ordering rules help answer that?  If you write two separate
loads you have two separate side effects that are ordered in time,
while for a single big load they occur concurrently.  If the construct
where those two loads occur does not allow for side effects to be
interleaved, then the "as if" principle seems to say you cannot
legally merge the loads.
>>

Yes maybe, but it's not air tight :-)

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-09 20:32 dewar
  2002-01-09 21:43 ` Paul Koning
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-09 20:32 UTC (permalink / raw)
  To: mrs, pkoning; +Cc: gcc, linux-kernel

<<Ah... so (paraphrasing) -- if you have two byte size volatile objects,
and they happen to end up adjacent in memory, the compiler is
explicitly forbidden from turning an access to one of them into a
wider access -- because that would be an access to both of them, which
is a *different* side effect.  (Certainly that exactly matches the
hardware-centric view of why "volatile" exists.)  And the compiler
isn't allowed to change side effects, including causing them when the
source code didn't ask you to cause them.
>>

Right, and as you see that is covered by the language on external effects
in the Ada standard (remember the intent in Ada was to exactly match the
C rules :-)

But one thing in the Ada world that we consider left open is whether a
compiler is free to combine two volatile loads into a single load. Probably
the answer should be no, but the language at least in the Ada standard does
not seem strong enough to say this.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-09 20:08 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-09 20:08 UTC (permalink / raw)
  To: dewar, mrs, paulus; +Cc: gcc, linux-kernel, trini, velco

<<So, I would claim that the case is symetric with writing volatiles.
If the standard doesn't make a distinction for write v read, then you
can't and claim that distinction is based in the standard.  If you
claim the standard does make a distinction, please point it out, I am
unaware of it.
>>

Well obviously you do not go writing to other variables, but if you have
three variables IN ONE PROGRAM

a
b
c

adjacently allocated, and b is volatile, and a/c are not, then your
argument *so far* would appear to allow a compiler to do an "over-wide"
load for b. If you think otherwise, please prove from standard.

Of course a write is generally not at all symmetrical, since you don't
want a write to be to clobber a and c (yes yes, I know you could still
construct a far out case in which a and b might be stored together, and
indeed that is a legitimate separate discussion).

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-09 19:53 mike stump
  2002-01-09 20:12 ` Paul Koning
  0 siblings, 1 reply; 202+ messages in thread
From: mike stump @ 2002-01-09 19:53 UTC (permalink / raw)
  To: dewar, paulus; +Cc: gcc, linux-kernel, trini, velco

> From: dewar@gnat.com
> To: dewar@gnat.com, mrs@windriver.com, paulus@samba.org
> Cc: gcc@gcc.gnu.org, linux-kernel@vger.kernel.org, trini@kernel.crashing.org,
>         velco@fadata.bg
> Date: Tue,  8 Jan 2002 21:13:43 -0500 (EST)

> Yes, of course! No one disagrees. I am talking about *LOADS* not
> stores, your example is 100% irrelevant to my point, since it does
> stores.

Ok, in the bodies of those, put in

j1=c1;

j2=c2;

j3=c3;

With new definitions for j1, j2 and k3 as being volatile.  Accesses are volatile:

       [#2] Accessing  a  volatile  object,  modifying  an  object,
       modifying  a  file,  or  calling a function that does any of
       those operations are all side effects

So, I would claim that the case is symetric with writing volatiles.
If the standard doesn't make a distinction for write v read, then you
can't and claim that distinction is based in the standard.  If you
claim the standard does make a distinction, please point it out, I am
unaware of it.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-09 10:42 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-09 10:42 UTC (permalink / raw)
  To: bernd, gcc, linux-kernel

<<Especially if there are cases were this optimization yields a slower =

access (or even worse indirect bugs).
E.g. if the referenced "volatile short" is a hardware register and the
access is multiplexed over a slow 8 bit bus.  There are embedded systems
around where this is the case and the (cross-)compiler has no way to
know this (except it can be told by the programmer).
>>

Well that of course is a situation where the compiler is being deliberately
misinformed as to the relative costs of various machine instructions, and
that is definitely a problem. One can even imagine hardware (not such a hard
feat, one of our customers had such hardware) where a word access works, but
a byte access fails due to hardware shortcuts, 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-09 10:41 Bernard Dautrevaux
  2002-01-09 21:59 ` Gérard Roudier
  0 siblings, 1 reply; 202+ messages in thread
From: Bernard Dautrevaux @ 2002-01-09 10:41 UTC (permalink / raw)
  To: 'dewar@gnat.com', bernd, gcc, linux-kernel

> -----Original Message-----
> From: dewar@gnat.com [mailto:dewar@gnat.com]
> Sent: Wednesday, January 09, 2002 11:42 AM
> To: bernd@gams.at; gcc@gcc.gnu.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH] C undefined behavior fix
> 
> 
> <<Especially if there are cases were this optimization yields 
> a slower =
> 
> access (or even worse indirect bugs).
> E.g. if the referenced "volatile short" is a hardware register and the
> access is multiplexed over a slow 8 bit bus.  There are 
> embedded systems
> around where this is the case and the (cross-)compiler has no way to
> know this (except it can be told by the programmer).
> >>
> 
> Well that of course is a situation where the compiler is 
> being deliberately
> misinformed as to the relative costs of various machine 
> instructions, and
> that is definitely a problem. One can even imagine hardware 
> (not such a hard
> feat, one of our customers had such hardware) where a word 
> access works, but
> a byte access fails due to hardware shortcuts, 

Tht's quite often the case with MMIO, and the only portable way to give a
hint to the compiler that it should refrain from optimizing is "volatile";
that's why I think the compiler should not do this optimization on volatile
objects at all.

	Bernard

--------------------------------------------
Bernard Dautrevaux
Microprocess Ingenierie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-09 10:40 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-09 10:40 UTC (permalink / raw)
  To: Dautrevaux, dewar, mrs, paulus; +Cc: gcc, linux-kernel, trini, velco

<<This is especially true as it is a nuisance for some uses of "volatile" that
were intended by the standard (as is clear in notes refering to the use of
volatile for memory mapped IO) and are broken by this optimization.
>>

Right, of course this optimization should only be done if the compiler can
prove that no other volatile objects are accessed (that would also violate
the corresponding rule in the Ada standard).

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-09  9:06 Bernard Dautrevaux
  2002-01-09  9:25 ` Bernd Petrovitsch
  0 siblings, 1 reply; 202+ messages in thread
From: Bernard Dautrevaux @ 2002-01-09  9:06 UTC (permalink / raw)
  To: 'dewar@gnat.com', mrs, paulus; +Cc: gcc, linux-kernel, trini, velco

> -----Original Message-----
> From: dewar@gnat.com [mailto:dewar@gnat.com]
> Sent: Wednesday, January 09, 2002 1:52 AM
> To: dewar@gnat.com; mrs@windriver.com; paulus@samba.org
> Cc: gcc@gcc.gnu.org; linux-kernel@vger.kernel.org;
> trini@kernel.crashing.org; velco@fadata.bg
> Subject: Re: [PATCH] C undefined behavior fix
> 
> 
> <<Hum, where in that standard does it say that the compiler won't
> scribble all over memory?  If it doesn't, does that mean that within
> the confines of the language standard that the compiler can?  If you
> produce an Ada compiler that did, do you think your users would feel
> better when you told them you were allowed to by the language
> standard?
> >>
> 
> YOu are appealing to the "intent" of the C standard to say that when
> referencing volatile memory, ONLY the volatile variable can be
> referenced and nothing else. OK, but where do you find this intent?
> Or do we just have to take Mike's word for it? If so, that's not
> very helpful (i.e. to consider that there is an implicit clause
> in the standard that says to consult Mike to learn the intent of
> anything not spelled out).
> 
> Seriously, I just don't see the requirement stated or implied in the
> standard. Perhaps I am missing some language, that's 
> certainly possible,
> it is not a document that I know by heart beginning to end.
> 
> As to your question above, the external effects of an Ada 
> program are very
> carefully stated in the standard, and no one is allowed to 
> try to extend
> this set of effects by appealing to "intent". Of course 
> marketing requirements
> say many things, e.g. you can obviously compute A+B by 
> recursive incrementing,
> and of course that satisfies the standard, but it is 
> obviously useless.
> 
> Now if you are claiming that generating efficient code to 
> access a 16-bit
> volatile quantity (by loading 32 bits) is in the same 
> category, I absolutely
> do not buy that at all.

I agree that in some cases reading a 32-bit word when needing a 16-bit
volatile short may be allowed by the standard. HOWEVER that suppose that gcc
makes a careful examination of all the memory layout for the program so that
to be sure that the 16 unneeded bits it reads for efficiency do NOT come
from some volatile object(s), or gcc will then BREAK the volatile semantics
for these objects.

So in any case this is not allowed in a lot of cases such as accessing
accessing an external "volatile short" (only the linker knwos for sure what
is near this short) or reading memory through a "volatile short*" (only GOD
knows if you can). And in fact it's WRONG to access in such a way if you
know that near this object you have other objects (such as is the case in a
volatile struct...). So even if it *may* be legal in some cases, such an
optimization that *may* be more efficient is not at all very interesting.

This is especially true as it is a nuisance for some uses of "volatile" that
were intended by the standard (as is clear in notes refering to the use of
volatile for memory mapped IO) and are broken by this optimization.

Regards,

	Bernard

PS: Note also that we have (at least on 2.95.3) the opposite "optimization"
or reading only 8-bits out of a 32-bit "volatile unsigned", something that
may be argued to be plain wrong (after all you are omitting reads that were
requested by the program). I've send a message about that earlier in this
thread but have no way right now to test what 3.0.3 will do about it so I
don't want to file a PR if this was already corrected. The program
generating an (incorrect?) byte load is:

	void f(volatile unsigned char* p, volatile unsigned short* q) {
		*p = *q;
	}

Perhaps I should start a new thread about this? this one is quite overlong
:-)

--------------------------------------------
Bernard Dautrevaux
Microprocess Ingenierie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-09  2:18 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-09  2:18 UTC (permalink / raw)
  To: dewar, mrs, paulus; +Cc: gcc, linux-kernel, trini, velco

<<I noticed you failed to answer my question.  Why's that?  The answer
is, the standard is not a formal document.  If it were, you would be
able to point at the line that had the requirement that said it would
not scribble all over memory.  It is just that simple.
>>

Sorry, it *is* a formal document. Your question was with respect to Ada,
so if you are really interested here is the quote:

8   The external effect of the execution of an Ada program is defined in
terms of its interactions with its external environment.  The following are
defined as external interactions:

    9  Any interaction with an external file (see A.7);

   10  The execution of certain code_statements (see 13.8); which code_
       statements cause external interactions is implementation defined.

   11  Any call on an imported subprogram (see Annex B), including any
       parameters passed to it;

   12  Any result returned or exception propagated from a main
       subprogram (see 10.2) or an exported subprogram (see Annex B) to
       an external caller;

   13  Any read or update of an atomic or volatile object (see C.6);

   14  The values of imported and exported objects (see Annex B) at the
       time of any other interaction with the external environment.

Now the question is: does scribbling come under any of these definitions.
One would have to look at the particular definition of scribbling to know.
In particular, the compiler has to prove that such scribbling does not
violate 13 or 14. Rather hard, if you give me a specific example of a
an action performed by a scribbling compiler. I will tell you whether
it is conforming or not.

Note that the Ada standard also has the concept of implementation advice.
So one should also look there. It is not strictly normative, but in practice
has some semi-normative force.

The standard is most certainly a formal document in the legal sense. If
you are complaining that it is not mathematicaly precise, OK, but such
precision comes with other costs, so the intention of both the C and
Ada standards is that they are at an appropriate level of formality.

Of *course* it is the case that a conforming compiler that meets all the
requirements of the standards, and, in the case of Ada, also passes the
ISO approved validation suite (there is no such for C), may still be
complete junk for a given purpose (the original Ada-Ed compiler which
compiled Ada, and then executed it at the rate of about 1 statement 
per second was hardly useful for Mil-Aero applications :-)

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-09  2:13 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-09  2:13 UTC (permalink / raw)
  To: dewar, mrs, paulus; +Cc: gcc, linux-kernel, trini, velco

<<and we load each one into our app, and place c1, c2 and c3 immediately
next to each other, and then run foo1, then foo2, then foo3, and then
check the side effects, c1, c2 and c3, I would claim we _must_ get
write 1 c1, write 2 c2, write 3 c3, and at the end, c1, c2 c3 should
be 1,2,3.  I find it obvious.
>>

Yes, of course! No one disagrees. I am talking about *LOADS* not stores,
your example is 100% irrelevant to my point, since it does stores.

If you think I was talking about stores (look back in the thread, you
will see that is your misconception), then no WONDER you are puzzled
by what you *thought* I said :-)

<<In part, it is because gcc has adopted this model of independent
translation units, that makes it a hard requirement in the case above,
for the accesses to be byte based.  Because if it had not, gcc would
not be able to implement the intended required semantics of each of
the units.  The requirements of the standard forced this because of
the implementation choice.
>>

All this is true, but totally irrelevant to the point I was making, which
was about loads, not stores.

>>Welcome to the world of programming.

If you feel that I need a welcome to the world of programming (in which
I have lived for 38 years, producing several million lines of delivered
commercial code), then it is likely you are misunderstanding what I
am saying :-)

Robert

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-09  1:51 mike stump
  0 siblings, 0 replies; 202+ messages in thread
From: mike stump @ 2002-01-09  1:51 UTC (permalink / raw)
  To: dewar, paulus; +Cc: gcc, linux-kernel, trini, velco

> From: dewar@gnat.com
> To: dewar@gnat.com, mrs@windriver.com, paulus@samba.org
> Date: Tue,  8 Jan 2002 19:51:35 -0500 (EST)

I noticed you failed to answer my question.  Why's that?  The answer
is, the standard is not a formal document.  If it were, you would be
able to point at the line that had the requirement that said it would
not scribble all over memory.  It is just that simple.

The intent is to not.  We (they people that write the standard) expect
you to just know.  Personally, I find it rather obvious.  I suspect
most all people do, at least for the scribbling case.

> OK, but where do you find this intent?

The C standard is set in a historical context, and in the context of
existing implementations, and existing expectations.  A setting with
experts that know what the intent is to some varying degree.  A
setting with an installed base of users, and an installed base of
code.  Using all that as a backdrop, some types of experts I think can
discern the intent fairly well.  Somethings are contentious.
Somethings are so trivially true that even a beginner could know
you're violating the intent.

Some things hinge on specific choices an implementor might make.  For,
for example, on UNIX, with separate compilation without the compilers
ability to talk across the boundary, on a byte addressable machine, if
we have three translation units:

unit 1:

volatile char c1;

void foo1() {
     c1 = 1;
}

unit 2:

volatile char c2;

void foo2() {
     c2 = 2;
}

unit 3:

volatile char c3;

void foo3() {
     c3 = 3;
}

and we load each one into our app, and place c1, c2 and c3 immediately
next to each other, and then run foo1, then foo2, then foo3, and then
check the side effects, c1, c2 and c3, I would claim we _must_ get
write 1 c1, write 2 c2, write 3 c3, and at the end, c1, c2 c3 should
be 1,2,3.  I find it obvious.

One cure, is a completely formal language.  Do you know of any real
languages that are?  By real, I mean a real language that is used to
code real programs and used in the real world.  I don't.

So yes, sometimes, from time to time, people might have to be told
what the intent is, if they don't get it.

In part, it is because gcc has adopted this model of independent
translation units, that makes it a hard requirement in the case above,
for the accesses to be byte based.  Because if it had not, gcc would
not be able to implement the intended required semantics of each of
the units.  The requirements of the standard forced this because of
the implementation choice.


Welcome to the world of programming.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-09  1:19 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-09  1:19 UTC (permalink / raw)
  To: jamagallon, jtv
  Cc: Dautrevaux, dewar, gcc, linux-kernel, paulus, tim, trini, velco

<<Yes, thank you, that part was obvious already.  The question pertained
to the fact that nobody outside compiler-visible code was being handed
an address for b, and so the compiler could (if it wanted to) prove
under pretty broad assumptions that nobody could *find* b to make the
change in the first place.
>>

Suppose that a hardware emulator is used to change the value of b (IT
knows the address) at the point of:

>     >>>>>>>>> here b changes

The reason was precisely to test a different value for b. This should
work if b is volatile. So the compiler's proof is flawed. The whole
point of volatile is that ALL such proofs are forbidden for volatile
objects.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-09  0:51 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-09  0:51 UTC (permalink / raw)
  To: dewar, mrs, paulus; +Cc: gcc, linux-kernel, trini, velco

<<Hum, where in that standard does it say that the compiler won't
scribble all over memory?  If it doesn't, does that mean that within
the confines of the language standard that the compiler can?  If you
produce an Ada compiler that did, do you think your users would feel
better when you told them you were allowed to by the language
standard?
>>

YOu are appealing to the "intent" of the C standard to say that when
referencing volatile memory, ONLY the volatile variable can be
referenced and nothing else. OK, but where do you find this intent?
Or do we just have to take Mike's word for it? If so, that's not
very helpful (i.e. to consider that there is an implicit clause
in the standard that says to consult Mike to learn the intent of
anything not spelled out).

Seriously, I just don't see the requirement stated or implied in the
standard. Perhaps I am missing some language, that's certainly possible,
it is not a document that I know by heart beginning to end.

As to your question above, the external effects of an Ada program are very
carefully stated in the standard, and no one is allowed to try to extend
this set of effects by appealing to "intent". Of course marketing requirements
say many things, e.g. you can obviously compute A+B by recursive incrementing,
and of course that satisfies the standard, but it is obviously useless.

Now if you are claiming that generating efficient code to access a 16-bit
volatile quantity (by loading 32 bits) is in the same category, I absolutely
do not buy that at all.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-08 11:12 Bernard Dautrevaux
  2002-01-11  9:52 ` Horst von Brand
  0 siblings, 1 reply; 202+ messages in thread
From: Bernard Dautrevaux @ 2002-01-08 11:12 UTC (permalink / raw)
  To: 'Rogelio M. Serrano Jr.', Bernard Dautrevaux
  Cc: 'gcc@gcc.gnu.org', 'linux-kernel@vger.kernel.org'

> -----Original Message-----
> From: Rogelio M. Serrano Jr. [mailto:rogelio@evoserve.com]
> Sent: Tuesday, January 08, 2002 1:15 AM
> To: Bernard Dautrevaux
> Subject: Re: [PATCH] C undefined behavior fix 
> 
> 
> I tried the same thing using gcc 3.1
> the file test.c contains:
> 
> struct x{
>     volatile unsigned int x1:8;
> };
> 
> unsigned char f1(struct x* p)
> {
>     return p->x1;
> }
> 
> unsigned char f(unsigned int* p, unsigned char* q)
> {
>     *p = *q;

Note that in my case, the problem is caused by
	*q = *p;
as this request 8-bits from a 32-bits volatile, and gcc-2.95.3 generates a
byte load ;-(

> }
>  
> compiling with gcc -O2 -S test.c yields:
> 
> 	.file	"test.c"
> 	.text
> 	.align 2
> 	.p2align 4,,15
> .globl f1
> 	.type	f1,@function
> f1:
> 	pushl	%ebp
> 	movl	%esp, %ebp
> 	movl	8(%ebp), %eax
> 	movb	(%eax), %al

So here we get the (correct but annoying) byte access to an 8-bit field
taken from a 32-bit integer. That's exactly what we had to change for
volatile to be useful, so that this access is in fact a 32-bit access.

> 	andl	$255, %eax
> 	popl	%ebp
> 	ret
> .Lfe1:
> 	.size	f1,.Lfe1-f1
> 	.align 2
> 	.p2align 4,,15
> .globl f
> 	.type	f,@function
> f:
> 	pushl	%ebp
> 	movl	%esp, %ebp
> 	movl	12(%ebp), %eax
> 	xorl	%edx, %edx
> 	movb	(%eax), %dl	

This is correct as you read *q, which is a byte

> 	movl	8(%ebp), %eax
> 	movl	%edx, (%eax)

And hopefully, this is correct also as you write all the 32-bits of *p, as
requested.

> 	popl	%ebp
> 	ret
> .Lfe2:
> 	.size	f,.Lfe2-f
> 	.ident	"GCC: (GNU) 3.1 20011231 (experimental)"
> 

So at least for the first test, gcc-3.1 generates the same (anoying) code as
2.95.3. I'm quite sure this is legal, as I can't see in the standard if when
writing:

	volatile unsigned int x:8;

I define:
	1) a volatile 8-bit field to be interpreted as an unsigned int.
	2) an 8-bit field which is part of a volatile unsigned int.

It seems to me that the choice between these two interpretation is
implementation defined; what bothers me is that the GCC choice (1) is not
the more useful in my case (system programming), nor the more natural IMHO.

The second problem I had on 2.95.3 is more anoying, and may well be a GCC
bug; clearly I ask to read a volatile unsigned int, and to forget 24bits out
of it, but GCC only read th e8 interesting bits. It seems that this violate
the 'side effect preserve' definition of volatile (although in a way
coherent with choice 1 above).

So it would seem more coherent to correct the second problem (if it exists
in 3.0) and switch to model (2) above... but that has to be discussed and
documented (although that is what we made in our own compiler).

Regards,

	Bernard


--------------------------------------------
Bernard Dautrevaux
Microprocess Ingenierie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-08  9:44 Bernard Dautrevaux
  2002-01-08 11:44 ` 'jtv'
  0 siblings, 1 reply; 202+ messages in thread
From: Bernard Dautrevaux @ 2002-01-08  9:44 UTC (permalink / raw)
  To: 'jtv', Bernard Dautrevaux
  Cc: 'dewar@gnat.com', paulus, gcc, linux-kernel, trini, velco

> -----Original Message-----
> From: jtv [mailto:jtv@xs4all.nl]
> Sent: Monday, January 07, 2002 10:49 PM
> To: Bernard Dautrevaux
> Cc: 'dewar@gnat.com'; paulus@samba.org; gcc@gcc.gnu.org;
> linux-kernel@vger.kernel.org; trini@kernel.crashing.org; 
> velco@fadata.bg
> Subject: Re: [PATCH] C undefined behavior fix
> 
> 
> On Mon, Jan 07, 2002 at 02:24:35PM +0100, Bernard Dautrevaux wrote:
> > 
> > Note however that some may not have noticed, in the 
> volatile-using examples,
> > that there is a difference between a "pointer to volatile 
> char" and a
> > "volatile pointer to char"; the former, defined as 
> "volatile char*" does not
> > help in the case of the RELOC macro, while the latter, written "char
> > *volatile" (note that volatile is now AFTER the '*', not 
> before) is a sure
> > fix as the semantics of "volatile" ensure that the compiler 
> will NO MORE use
> > the value it PREVIOUSLY knows was the one of the pointer. 
> 
> One problem I ran into considering 'char *volatile' was this one: the
> compiler is supposed to disable certain optimizations involving
> registerization and such, but isn't it still allowed to do constant
> folding?  That would eliminate the pointer from the intermediate code
> altogether, and so the volatile qualifier would be quickly 
> forgotten.  
> No fixo breako.
> 
> Nothing's taking the pointer's address, so the compiler 
> _will_ be able 
> to prove that (in a sensible universe) no other thread, interrupt, 
> kernel code or Angered Rain God will be able to find our 
> pointer--much 
> less change it.

NO; the standard here is clear: any access to a volatile object is a side
effect (see , and optimization is NOT allowed to eliminate side effects, and
must do them respecting sequence points, even if it determines that the code
will in fact do nothing (see 5.1.2.3, at least in the document I have which
one of the last draft, dated 18th January 1999). That's the whole point of
the volatile specifier.

	Bernard

--------------------------------------------
Bernard Dautrevaux
Microprocess Ingenierie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-08  0:16 mike stump
  2002-01-08 11:33 ` jtv
  0 siblings, 1 reply; 202+ messages in thread
From: mike stump @ 2002-01-08  0:16 UTC (permalink / raw)
  To: Dautrevaux, jtv; +Cc: dewar, gcc, linux-kernel, paulus, trini, velco

> Date: Mon, 7 Jan 2002 22:49:07 +0100
> From: jtv <jtv@xs4all.nl>
> To: Bernard Dautrevaux <Dautrevaux@microprocess.com>

> One problem I ran into considering 'char *volatile' was this one:
> the compiler is supposed to disable certain optimizations involving
> registerization and such, but isn't it still allowed to do constant
> folding?

No.  That would be a bug.  gcc used to have volatile bugs, most of
them are now gone.  Please submit a bug report, if you can discover it
again.

I assume you meant something like this:

char * volatile cp;

main() {
  return cp - cp;
}

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-07 23:46 mike stump
  0 siblings, 0 replies; 202+ messages in thread
From: mike stump @ 2002-01-07 23:46 UTC (permalink / raw)
  To: dewar, paulus; +Cc: gcc, linux-kernel, trini, velco

> From: dewar@gnat.com
> To: dewar@gnat.com, mrs@windriver.com, paulus@samba.org
> Date: Sun,  6 Jan 2002 14:29:01 -0500 (EST)

> > Do you have an example where this fails?  Do you not consider it a bug?

> I don't see the obligation on the compiler here.

I think you mean that if one pedantically misreads the C standard and
its intent to the widest extent possible just within the confines of
the langauge document that the standard doesn't compell it.  If so, we
might be able to agree.

> Now if you are saying that this is a reasonable expectation, nothing
> to do with the standard, then that's another matter, but my example
> of a tradeoff with efficiency is an interesting one.

Pragmatically, not really.

Hum, where in that standard does it say that the compiler won't
scribble all over memory?  If it doesn't, does that mean that within
the confines of the language standard that the compiler can?  If you
produce an Ada compiler that did, do you think your users would feel
better when you told them you were allowed to by the language
standard?

The point can only be extreme misreading of a standard.

Just because you can invent some nonsensical mapping for C onto our
machines, doesn't mean we should.  Nor should we confuse users with
the notion that we could have a nonsensical compiler, if we wanted.

For example, it is perfectly within the rights of an implementor of C
to say that all volatile access will be 32 bus cycles that are 4 byte
aligned.  In this case, trivially we see that promoting your short
read to a 32 read is perfectly fine.  If a chip required it, it would
be reasonable (to the user).

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-07 23:20 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-07 23:20 UTC (permalink / raw)
  To: Dautrevaux, dewar, guerby, mrs; +Cc: gcc, linux-kernel, paulus, trini, velco

>>That is just broken and wrong

According to the gcc docs right? certainly not according to the standard!

<<If you want/need the gcc doc to expound on this, write it up, and
we'll add it.
>>

I think we should add this, since this is the source of the rule, not the
standard (as far as I can  tell)

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-07 23:15 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-07 23:15 UTC (permalink / raw)
  To: jtv, tim.mcdaniel, tim
  Cc: Dautrevaux, dewar, gcc, linux-kernel, paulus, trini, velco

<<In the above case it is unlikely that folding would present a problem,
but volatile was created because hardware, or even seemingly unrelated
software, can modify even the most unlikely memory locations.   If you
want to break device drivers, go ahead and optimize your compiler. =20
>>

No, I think that is the wrong domain of discourse here. We are not talking
about compilers being friendly, but rather correct. Most cetainly volatile
in Ada would not permit this optimzation (i.e. it would not be an optimization
it would be a miscompilation), and I certainly thought that in this respect
C was identical to Ada in semantics of volatile.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-07 23:12 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-07 23:12 UTC (permalink / raw)
  To: jtv, tim; +Cc: Dautrevaux, dewar, gcc, linux-kernel, paulus, trini, velco

<<Is there really language in the Standard preventing the compiler from
constant-folding this code to "int a = 13;"?
>>

If there is no such language (I do not have my copy with me)< then the
standard is most certainly broken :-)

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-07 23:11 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-07 23:11 UTC (permalink / raw)
  To: jtv, tim; +Cc: Dautrevaux, dewar, gcc, linux-kernel, paulus, trini, velco

<<You're not allowed to be that smart wrt volatile.  If the programmer
says the value might change unpredictably and should not be optimized,
then It Is So and the compiler must respect that even if it determines
It Cannot Possibly Happen.
>>

Indeed, this is the case, for example, you may have a hardware monitor
on the bus, and you are looking for this address, or some external
process may be modifying the location. Or you may legitimately use
volatile so that your debugger works as expected on this location.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-07 22:56 mike stump
  0 siblings, 0 replies; 202+ messages in thread
From: mike stump @ 2002-01-07 22:56 UTC (permalink / raw)
  To: Dautrevaux, dewar, guerby; +Cc: gcc, linux-kernel, paulus, trini, velco

> From: Bernard Dautrevaux <Dautrevaux@microprocess.com>
> To: "'Laurent Guerby'" <guerby@acm.org>, dewar@gnat.com
> Date: Mon, 7 Jan 2002 14:29:15 +0100 

> It seems to me that you are right,

That's unfortunate.

> but there is other cases; for example:
> 	X := T(0)*256 + T(1);
> compiled on a big endian architecture may well generate just one
> 16-bit word read...

Not in my word, not in gcc's world.  That is just broken and wrong.

If you want/need the gcc doc to expound on this, write it up, and
we'll add it.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-07 22:26 Tim McDaniel
  0 siblings, 0 replies; 202+ messages in thread
From: Tim McDaniel @ 2002-01-07 22:26 UTC (permalink / raw)
  To: jtv, Tim Hollebeek
  Cc: Bernard Dautrevaux, dewar, paulus, gcc, linux-kernel, trini,
	velco


-----Original Message-----
From: jtv [mailto:jtv@xs4all.nl]
Sent: Monday, January 07, 2002 4:16 PM
To: Tim Hollebeek
Cc: Bernard Dautrevaux; 'dewar@gnat.com'; paulus@samba.org;
gcc@gcc.gnu.org; linux-kernel@vger.kernel.org;
trini@kernel.crashing.org; velco@fadata.bg
Subject: Re: [PATCH] C undefined behavior fix


On Mon, Jan 07, 2002 at 05:28:32PM -0500, Tim Hollebeek wrote:
> 
> You're not allowed to be that smart wrt volatile.  If the programmer
> says the value might change unpredictably and should not be optimized,
> then It Is So and the compiler must respect that even if it determines
> It Cannot Possibly Happen.

Naturally I hope you're right.  But how does that follow from the
Standard?
I have to admit I don't have a copy handy.  :(

Let's say we have this simplified version of the problem:

	int a = 3;
	{
		volatile int b = 10;
		a += b;
	}

Is there really language in the Standard preventing the compiler from
constant-folding this code to "int a = 13;"?




Jeroen


In the above case it is unlikely that folding would present a problem,
but volatile was created because hardware, or even seemingly unrelated
software, can modify even the most unlikely memory locations.   If you
want to break device drivers, go ahead and optimize your compiler.  



 

Tim

The only thing dummer than a cow is a man who thinks he's smarter than a
cow.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel"
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-07 19:36 mike stump
  2002-01-07 21:21 ` Theodore Tso
  2002-01-08  0:19 ` Paul Mackerras
  0 siblings, 2 replies; 202+ messages in thread
From: mike stump @ 2002-01-07 19:36 UTC (permalink / raw)
  To: gdr, paulus; +Cc: dewar, gcc, linux-kernel, trini, velco

> From: Paul Mackerras <paulus@samba.org>
> Date: Mon, 7 Jan 2002 08:59:47 +1100 (EST)
> To: Gabriel Dos Reis <gdr@codesourcery.com>

> > Personnally, I don't have any sentiment against the assembler
> > solution.  Dewar said it was unnecessarily un-portable, but that the
> > construct by itself *is* already unportable. 

> I assume that what we're talking about is using an asm statement like:

> 	asm("" : "=r" (x) : "0" (y));

Ick!  No, that's horrible.

char buf[1024];

#define hide(x) ({ void *vp = x; asm ("" : "+r" (vp)); vp; })

main() {
  strcpy(buf, hide("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeelksdlkjasdlkjasdlkjasdaaaaaaaaaa"+20));
}

Perfectly clear, simple, doesn't burn regs and so on.  In fact, even
the assembly file doesn't have any extraneous output, cool.

> My main problem with this is that it doesn't actually solve the
> problem AFAICS.

It does for now.  It will for the next 10 years, my guess.  volatile
will solve it longer, at some performance penalty, if you prefer.

> Dereferencing x is still undefined according to the rules in the gcc
> manual.

?  So what?  Pragmatically, for now, it does what the user wants.  By
the time we break it, we'll probably have enough intelligence in the
compiler to figure out what they were doing and still not break it.

> I would prefer a solution that will last, rather than one which
> relies on details of the current gcc implementation.

Then move the bits to the right address before you execute the C code
and code the thing that moves the bits in assembly.

> - it is hard to read; it wouldn't be obvious to someone who doesn't
>   know the details of gcc asm syntax what it is doing or why

See the comment just above.

> - it is a statement, which makes it less convenient to use than an
>   expression

? In my example, it is an expression.

> - it requires an extra dummy variable declaration.

Mine doesn't.

> But my main objection is that I don't have any assurance that it
> actually solves the problem in a lasting way.

The code only in that subset of C that is well defined and only use
semantics that have mandated behavior.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-07 19:18 mike stump
  0 siblings, 0 replies; 202+ messages in thread
From: mike stump @ 2002-01-07 19:18 UTC (permalink / raw)
  To: dewar, guerby; +Cc: gcc, linux-kernel, paulus, trini, velco

> From: dewar@gnat.com
> To: dewar@gnat.com, guerby@acm.org, mrs@windriver.com
> Date: Sun,  6 Jan 2002 14:32:01 -0500 (EST)

> Ah ha! But then look again at my 16-bit example, an expert assembly
> langauge programmer will use a 32 bit load if efficiency is not an
> issue (and it does not matter if there are extra bits around), but a
> 16-bit load if the hardware for some reason requires it. How is the
> poort C compiler to distinguish these cases automatically?

When you give the compiler as much information to it as your expert
apparently has, then it will produce the same code, until then,
imagine you told you expert that you want to do a 16 bit fetch for
something that might care if it were not a 16 bit access...  If you so
tie your experts hands, as you tie gcc hands, then should produce
similar code.

Now, if you want to invent gcc extensions so that it can know as much
as a domain expert, start proposing those language extensions...

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-07 19:17 Bernard Dautrevaux
  0 siblings, 0 replies; 202+ messages in thread
From: Bernard Dautrevaux @ 2002-01-07 19:17 UTC (permalink / raw)
  To: 'mike stump', Bernard Dautrevaux, dewar, paulus
  Cc: gcc, linux-kernel, trini, velco

> -----Original Message-----
> From: mike stump [mailto:mrs@windriver.com]
> Sent: Monday, January 07, 2002 7:39 PM
> To: Dautrevaux@microprocess.com; dewar@gnat.com; paulus@samba.org
> Cc: gcc@gcc.gnu.org; linux-kernel@vger.kernel.org;
> trini@kernel.crashing.org; velco@fadata.bg
> Subject: RE: [PATCH] C undefined behavior fix
> 
> 
> > From: Bernard Dautrevaux <Dautrevaux@microprocess.com>
> > To: "'dewar@gnat.com'" <dewar@gnat.com>, paulus@samba.org
> > Cc: gcc@gcc.gnu.org, linux-kernel@vger.kernel.org, 
> trini@kernel.crashing.org,
> >         velco@fadata.bg
> > Date: Mon, 7 Jan 2002 14:24:35 +0100 
> 
> > Truly sure; In fact when writiong our Real Time Kernel in C++ we
> > just had this problem, and had to "hack" GCC C and C++ compilers so
> > that volatile acesses are guaranteed to be done with the right size,
> > even in case of bit fields in fact.
> 
> Did your case include more than bitfields?  I recognize that bitfields
> have two possible semantics, and that you and gcc may have different
> opinions about the semantics of them.  I discount the alternative
> choice of semantic as being an example of this problem.  Roughly
> speaking, as I recall...  The two semantics are, the base type of the
> bitfield defines the mode in which memory is accessed and the smallest
> size supported that contains the bitfield defines the access.
> 
> struct { unsigned int field:8; };
> 
> would be a 32 bit access, versus
> 
> struct { unsigned int field:8; };
> 
> would be an 8 bit access.

AFAIR, we'd got an 8 bit access there, which was wrong in view of the fact
we use this to access memory mapped registers that only accept word
accesses. Also this was quite long ago (on gcc-2.95.3); we're in the process
of migrating to 3.0 but that takes some time as we have to make other
changes in the compiler.

Also note that even with the volatile keyword, it seems legal (although I
doubt that GCC does it) to access two adjacent, properly aligned, volatile
char as one word, especially if the result is placed in one resulting
variable as if you have:

	struct { unsigned short a; volatile unsigned char x; volatile
unsigned char y; } *p; 
	unsigned short z = x << 8 | y;

Here it seems that all the C standard requirements for volatile are
fulfilled if the compiler just read a word in z (and that's a big win on a
big-endian architecture); however from a system programmer point of view
this could cause headaches if the memory mapped register only accept byte
accesses... (hopefully this is quite rare; the opposite is more frequent:
only accept word access and get byte access due to bitfields or masking).

> 
> If gcc doesn't do one of them, it truly is broken (if the machine
> supports the access of course).  I would like to know if gcc is truly
> broken.

gcc obvioulsy does one of those; but using the smallest size access is a
nuisance for system programming and a very small win (if any) for standard
applications (who anyway seldom use the volatile keyword, except in
multithreaded code, but then often read/write from the cache).

> 
> > Using volatile (and expanding its semantics to mean: read and write
> > with the requested size) was a great help.
> 
> In gcc, it already means that.  If you think otherwise, I'd like to
> see the example that shows it.

I don't have access right now to a gcc-3.0 compiler, but I try it just now
on 2.95.3 (i386), compiling by "gcc -S -O2 test.c" (a quite common set of
options isn't-it?).

First case: 
===========

reading an 8-bits bitfield declared as unsigned int (32 bit mmio register),
GCC generate 8-bit access to the memory:

struct x {
 volatile unsigned int x1:8;
};

unsigned char f1(struct x* p) {
 return p->x1;
}

yields:
 .file "tst1.c"
 .version "01.01"
gcc2_compiled.:
.text
 .align 4
.globl f1
 .type  f1,@function
f1:
 pushl %ebp
 movl %esp,%ebp
 movl 8(%ebp),%eax
 movl %ebp,%esp
 popl %ebp
 movb (%eax),%al
 movzbl %al,%eax
 ret
.Lfe1:
 .size  f1,.Lfe1-f1
 .ident "GCC: (GNU) 2.95.3-5 (cygwin special)"


Second case:
============

Reading part of a volatile unsigned int (32 bits) with an 8-bit access:

void f(unsigned int* p, unsigned char* q) {
 *q = *p;
}

yields:

 .file "test2.c"
 .version "01.01"
gcc2_compiled.:
.text
 .align 4
.globl f
 .type  f,@function
f:
 pushl %ebp
 movl %esp,%ebp
 movl 8(%ebp),%eax
 movl 12(%ebp),%edx
 movl %ebp,%esp
 movb (%eax),%al
 movb %al,(%edx)
 popl %ebp
 ret
.Lfe1:
 .size  f,.Lfe1-f
 .ident "GCC: (GNU) 2.95.3-5 (cygwin special)"

Maybe 3.0 is avoiding the byte accesses? that would be fine, at least for me
:-)

Note that I were not able to cause gcc to collapse two byte accesses as one
16-bit one but I may not have tried hard enough...

Clearly the code generated by gcc above IS FULLY ANSI-C conforming.
Obviously when writing system code, one would like a bit more strict
interpretation of volatile.

Regards

	Bernard

--------------------------------------------
Bernard Dautrevaux
Microprocess Ingenierie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-07 18:38 mike stump
  0 siblings, 0 replies; 202+ messages in thread
From: mike stump @ 2002-01-07 18:38 UTC (permalink / raw)
  To: Dautrevaux, dewar, paulus; +Cc: gcc, linux-kernel, trini, velco

> From: Bernard Dautrevaux <Dautrevaux@microprocess.com>
> To: "'dewar@gnat.com'" <dewar@gnat.com>, paulus@samba.org
> Cc: gcc@gcc.gnu.org, linux-kernel@vger.kernel.org, trini@kernel.crashing.org,
>         velco@fadata.bg
> Date: Mon, 7 Jan 2002 14:24:35 +0100 

> Truly sure; In fact when writiong our Real Time Kernel in C++ we
> just had this problem, and had to "hack" GCC C and C++ compilers so
> that volatile acesses are guaranteed to be done with the right size,
> even in case of bit fields in fact.

Did your case include more than bitfields?  I recognize that bitfields
have two possible semantics, and that you and gcc may have different
opinions about the semantics of them.  I discount the alternative
choice of semantic as being an example of this problem.  Roughly
speaking, as I recall...  The two semantics are, the base type of the
bitfield defines the mode in which memory is accessed and the smallest
size supported that contains the bitfield defines the access.

struct { unsigned int field:8; };

would be a 32 bit access, versus

struct { unsigned int field:8; };

would be an 8 bit access.

If gcc doesn't do one of them, it truly is broken (if the machine
supports the access of course).  I would like to know if gcc is truly
broken.

> Using volatile (and expanding its semantics to mean: read and write
> with the requested size) was a great help.

In gcc, it already means that.  If you think otherwise, I'd like to
see the example that shows it.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-07 13:29 Bernard Dautrevaux
  0 siblings, 0 replies; 202+ messages in thread
From: Bernard Dautrevaux @ 2002-01-07 13:29 UTC (permalink / raw)
  To: 'Laurent Guerby', dewar; +Cc: paulus, gcc, linux-kernel, trini, velco

> -----Original Message-----
> From: Laurent Guerby [mailto:guerby@acm.org]
> Sent: Sunday, January 06, 2002 2:41 PM
> To: dewar@gnat.com
> Cc: paulus@samba.org; gcc@gcc.gnu.org; linux-kernel@vger.kernel.org;
> trini@kernel.crashing.org; velco@fadata.bg
> Subject: Re: [PATCH] C undefined behavior fix
> 
> 
> dewar@gnat.com wrote:
> 
> > pragma Atomic in Ada (volatile gets close in C, but is not 
> close enough) will
> > ensure a byte store in practice, but may not ensure byte reads.
> 
> 
> I see no distinction between read and write in the text of 
> the Ada standard.
> 
> Also I think if you declare a byte array with Atomic_Component
> and Volatile_Component and that the compiler accepts it for its
> target architecture, then the compiler is required to generate
> a byte read and store for each occurence in the text source.
>  From C.6:
> 
> 15    For an atomic object (including an atomic component) 
> all reads and
> updates of the object as a whole are indivisible.
> 
> 16    For a volatile object all reads and updates of the object as a 
> whole are
> performed directly to memory.
> 
> 20    {external effect (volatile/atomic objects) [partial]} 
> The external
> effect of a program (see 1.1.3) is defined to include each read and 
> update of
> a volatile or atomic object. The implementation shall not 
> generate any 
> memory
> reads or updates of atomic or volatile objects other than 
> those specified by
> the program.
> 
> In my exemple byte array, if I say X := T (I) I don't see how 
> a conformant
> compiler accepting the declaration could generate anything other than
> one and exactly one byte read. Per 20 it has no right to read 
> T (I+1) or 
> T(I-1)
> since they are "other" objects (components to be pedantic).

It seems to me that you are right, but there is other cases; for example:
	X := T(0)*256 + T(1);
compiled on a big endian architecture may well generate just one 16-bit word
read... 

	Bernard

--------------------------------------------
Bernard Dautrevaux
Microprocess Ingenierie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-07 13:24 Bernard Dautrevaux
  2002-01-07 21:49 ` jtv
  0 siblings, 1 reply; 202+ messages in thread
From: Bernard Dautrevaux @ 2002-01-07 13:24 UTC (permalink / raw)
  To: 'dewar@gnat.com', paulus; +Cc: gcc, linux-kernel, trini, velco

> -----Original Message-----
> From: dewar@gnat.com [mailto:dewar@gnat.com]
> Sent: Sunday, January 06, 2002 2:06 PM
> To: dewar@gnat.com; paulus@samba.org
> Cc: gcc@gcc.gnu.org; linux-kernel@vger.kernel.org;
> trini@kernel.crashing.org; velco@fadata.bg
> Subject: Re: [PATCH] C undefined behavior fix
> 
> 
> <<* Given a pointer, I need a way to determine the address 
> (as an int of
>   the appropriate size) that the CPU will present to the MMU when I
>   dereference that pointer.
> >>
> 
> This is in general ill-defined, a compiler might generate 
> code that sometimes
> does byte access to a particular byte, anmd sometimes gets 
> the entire word
> in which the byte resides.
> 
> This is often a nasty issue, and is one of the few things in 
> this area that
> Ada does not properly address.
> 
> If you have a memory mapped byte, you really want a way of saying
> 
> "when I read this byte, do a byte read, it will not work to 
> do a word read"
> 
> pragma Atomic in Ada (volatile gets close in C, but is not 
> close enough) will
> ensure a byte store in practice, but may not ensure byte reads.
> 

Truly sure; In fact when writiong our Real Time Kernel in C++ we just had
this problem, and had to "hack" GCC C and C++ compilers so that volatile
acesses are guaranteed to be done with the right size, even in case of bit
fields in fact.

Anyway volatile is probably a solution for most of these kind of problems,
and adding some more implementation-defined semantics to volatile may
provide a sure fix for most problems. 

Note however that some may not have noticed, in the volatile-using examples,
that there is a difference between a "pointer to volatile char" and a
"volatile pointer to char"; the former, defined as "volatile char*" does not
help in the case of the RELOC macro, while the latter, written "char
*volatile" (note that volatile is now AFTER the '*', not before) is a sure
fix as the semantics of "volatile" ensure that the compiler will NO MORE use
the value it PREVIOUSLY knows was the one of the pointer. 

One of the lessons we learn while writing our C++ kernel was that you NEED
to be both a kernel-expert AND a compiler-expert to be successful, as some
parts of the kernel need to play some nasty tricks that the compiler may
misunderstand; so you must be able to find the proper way to inform the
compiler that you are playing these tricks and forget what it knows. Using
volatile (and expanding its semantics to mean: read and write with the
requested size) was a great help.

Just my .02euro

	Bernard

--------------------------------------------
Bernard Dautrevaux
Microprocess Ingenierie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06 19:32 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-06 19:32 UTC (permalink / raw)
  To: dewar, guerby, mrs; +Cc: gcc, linux-kernel, paulus, trini, velco

<<I think the goal and intent, for Ada and C as well, is to say that the
compiler will generate what is possible from assembly code written by
an expert on the platform, using the best fitting access that is
possible.
>>

Ah ha! But then look again  at my 16-bit example, an expert assembly
langauge programmer will use a 32 bit load if efficiency is not an
issue (and it does not matter if there are extra bits around), but
a 16-bit load if the hardware for some reason requires it. How is
the poort C compiler to distinguish these cases automatically?

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06 19:29 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-06 19:29 UTC (permalink / raw)
  To: dewar, gdr, mrs; +Cc: gcc, linux-kernel, paulus, trini, velco

perhaps the right construct is an attribute on a pointer variable that
says essentially: use the bits, forget the provenance.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06 19:29 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-06 19:29 UTC (permalink / raw)
  To: dewar, mrs, paulus; +Cc: gcc, linux-kernel, trini, velco

<<?  Do you have an example where this fails?  Do you not consider it a
bug?  Now, I would place a fair amount of buren on the compiler to get
it right, though, this isn't absolute.  For example, eieieio or
>>

I don't see the obligation on the compiler here. For instance spupose
you are on an architecture where a word read is faster than a byte read.
Let's make it specific, suppose you are on a 386 and the item is 16-bits.
Now it is quicker to read 32-bits, because no prefix is required. Do you
see anything in the C standard (or the Ada standard :-) which requires a
16-bit read here? I don't, but perhaps I am missing something.

Now if you are saying that this is a reasonable expectation, nothing to do
with the standard, then that's another matter, but my example of a tradeoff
with efficiency is an interesting one.


^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06 18:37 mike stump
  0 siblings, 0 replies; 202+ messages in thread
From: mike stump @ 2002-01-06 18:37 UTC (permalink / raw)
  To: dewar, guerby; +Cc: gcc, linux-kernel, paulus, trini, velco

> From: dewar@gnat.com
> To: dewar@gnat.com, guerby@acm.org
> Date: Sun,  6 Jan 2002 08:43:53 -0500 (EST)

> The point is that the implementation of a write has, given your
> quote from the RM, pretty much no choice but to do an exactly
> "correct" write, but for a read, there is nothing to stop reading
> MORE than the minimum, the requirement of atomicity is still
> met.

Ok, we can agree the wording in the standard sucks.  Though, I think
we might be able to agree on the intent and goal of the wording.  It
isn't allowed to mandate the byte read/write, as the machine may not
support it, and that would artificially constrain the machine from
being implementable on the platform, and this would be a bad idea.

I think the goal and intent, for Ada and C as well, is to say that the
compiler will generate what is possible from assembly code written by
an expert on the platform, using the best fitting access that is
possible.

Once we understand the standard and the motivation behind it, and what
it is trying to provide our users, and how our users might reasonably
use it, we can mandate for ourselves as a quality of implementation
issue, if you would like to call it that, those reasonable semantics.
Should we fail to provide them, and should users want them, then it is
finally up to the users to more completely describe the language they
want, and refine the language standards to include it.  But, in spite
of that, we don't have to go out of our way to do stupid things, nor
should be brow beat our users with, your code isn't conformant
needlessly.  It is all to easy to do that, we should resist the
temptation.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06 18:24 mike stump
  2002-01-06 20:37 ` Gabriel Dos Reis
  0 siblings, 1 reply; 202+ messages in thread
From: mike stump @ 2002-01-06 18:24 UTC (permalink / raw)
  To: dewar, gdr; +Cc: gcc, linux-kernel, paulus, trini, velco

> From: Gabriel Dos Reis <gdr@codesourcery.com>
> Date: 06 Jan 2002 14:22:45 +0100

> Isn't the incriminated construct already outside of C and non-portable?

That has been established and agreed upon.  What we are now into is
pragmatics.  You now have to argue why we should not provide this
feature in some form to users that ask for it.  Love to hear your
ideas.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06 18:20 mike stump
  0 siblings, 0 replies; 202+ messages in thread
From: mike stump @ 2002-01-06 18:20 UTC (permalink / raw)
  To: dewar, paulus; +Cc: gcc, linux-kernel, trini, velco

> From: dewar@gnat.com
> To: dewar@gnat.com, paulus@samba.org
> Date: Sun,  6 Jan 2002 08:05:56 -0500 (EST)

> If you have a memory mapped byte, you really want a way of saying
> "when I read this byte, do a byte read, it will not work to do a
> word read"

> (volatile gets close in C, but is not close enough) will ensure a
> byte store in practice, but may not ensure byte reads.

?  Do you have an example where this fails?  Do you not consider it a
bug?  Now, I would place a fair amount of buren on the compiler to get
it right, though, this isn't absolute.  For example, eieieio or
whatever it is called on the powerpc.  I think the chip/OS/MMU must
bear some responsibility for meeting its obligations to the compiler,
and if it doesn't, then that chip/OS/MMU fails to provide a reasonable
base on which to provide the compiler.  Did you have this case in
mind?

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06 16:22 dewar
  2002-01-06 16:39 ` Alan Cox
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-06 16:22 UTC (permalink / raw)
  To: dewar, guerby; +Cc: gcc, linux-kernel, paulus, trini, velco

<<But even in the case of the compiler reading more (and writing anyway),
I think it  is the compiler burden to prove that the extra stuff
"read" is not observable (in the sense of external
effect) at execution. In a memory-mapped I/O architecture
where there is a distinction on external effects between a byte read
and a word read (eg: a crash :),  the compiler can't get very far IMHO
(if it accepts the declaration of course).
>>

External effects are well defined in Ada, see 1.1.3(8) of the RM. The
case you mention is not explicitly listed here, so is not an external
effect in the Ada sense. The rule is not that anything observable be
unaffected (after all performance is observable), but that the 
six explicit items in section 1.1.3(8) are not observable. Here they
are for those who do not have the Ada RM at hand (it is not that
Ada is so significant here, as that perhaps we can get some clues
for the desirable behavior in GNU C)

    9  Any interaction with an external file (see A.7);

   10  The execution of certain code_statements (see 13.8); which code_
       statements cause external interactions is implementation defined.

   11  Any call on an imported subprogram (see Annex B), including any
       parameters passed to it;

   12  Any result returned or exception propagated from a main
       subprogram (see 10.2) or an exported subprogram (see Annex B) to
       an external caller;

   13  Any read or update of an atomic or volatile object (see C.6);

   14  The values of imported and exported objects (see Annex B) at the
       time of any other interaction with the external environment.


^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06 13:43 dewar
  2002-01-06 13:55 ` Laurent Guerby
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-06 13:43 UTC (permalink / raw)
  To: dewar, guerby; +Cc: gcc, linux-kernel, paulus, trini, velco

<<I see no distinction between read and write in the text of the Ada standard.
>>

The point is that the implementation of a write has, given your quote from the
RM, pretty much no choice but to do an exactly "correct" write, but for a
read, there is nothing to stop reading MORE than the minimum, the requirement
of atomicity is still met. Now of course in your array example, you are
exactly right, so you could rig up an array with elements surrounding the
one you really want. A bit heavy, but yes, that's a trick that will work.


^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06 13:41 dewar
  2002-01-06 16:58 ` Gabriel Dos Reis
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-06 13:41 UTC (permalink / raw)
  To: dewar, gdr; +Cc: gcc, linux-kernel, paulus, trini, velco

>>Isn't the incriminated construct already outside of C and non-portable?

The issue is not whether it is outside standard-C here, which of course
it is, but rather whether there is some extension to GNU-C (either an
interpretation of undefined or implementation defined, or an attribute etc)
which wuld make it inside GNU-C even if outside C, and therefore portable
to GNU-C, which is good enough for this purpose.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06 13:16 dewar
  2002-01-06 13:22 ` Gabriel Dos Reis
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-06 13:16 UTC (permalink / raw)
  To: paulus, velco; +Cc: dewar, gcc, linux-kernel, trini

<<Number of people suggested using assembly for this, why you keep
ignoring it and insist instead on changing the compiler, changing the
C standard, switching to another compiler and similar unproductive
ideas put forward solely for the sake of argument ?
>>

Maybe people will jump on me for saying this, but one objection I have to
using assembly is that the assembly language feature on gcc seems

a) awfully complicated, requiring more detailed knowledge of how the compiler
works than most programmers have.

b) certainly more complicated than comparable features in other compilers,
e.g. Borland C.

c) not that well documented

We find in the Ada world (where we have duplicated the C assembly language
feature more or less 100% exactly), that our customers almost always have to
ask us for help in getting asm inserts correct.

The GNU-C feature here is very powerful, but really not very easy to use!

I also find that introducing asm for this purpose is unnecessarily non-portable.
Yes in some cases, we are talking about very target specific code, but in other
cases the code is not so target specific, and it is desirable to stay within
C if possible.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06 13:07 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-06 13:07 UTC (permalink / raw)
  To: dewar, paulus; +Cc: gcc, linux-kernel, trini, velco

<<* Given an address as an int (of the appropriate size), I need a way
  to construct a pointer, which when dereferenced, will result in the
  CPU presenting that address to the MMU.

* I need a way to tell the compiler not to make any assumptions about
  what objects that such a pointer might or might not point to, so
  that the effect of dereferencing the pointer is simply to access the
  memory at the address I gave, and is not considered "undefined"
  regardless of how I might have constructed the address.
>>

So that seems reasonable as a statement of need (i.e. a high level
requirement), so what is needed now is to craft a well defined way
in GNU C, preferably other than ASM inserts, to achieve this very
reasonable goal.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06 13:05 dewar
  2002-01-06 13:41 ` Laurent Guerby
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-06 13:05 UTC (permalink / raw)
  To: dewar, paulus; +Cc: gcc, linux-kernel, trini, velco

<<* Given a pointer, I need a way to determine the address (as an int of
  the appropriate size) that the CPU will present to the MMU when I
  dereference that pointer.
>>

This is in general ill-defined, a compiler might generate code that sometimes
does byte access to a particular byte, anmd sometimes gets the entire word
in which the byte resides.

This is often a nasty issue, and is one of the few things in this area that
Ada does not properly address.

If you have a memory mapped byte, you really want a way of saying

"when I read this byte, do a byte read, it will not work to do a word read"

pragma Atomic in Ada (volatile gets close in C, but is not close enough) will
ensure a byte store in practice, but may not ensure byte reads.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06  7:56 mike stump
  0 siblings, 0 replies; 202+ messages in thread
From: mike stump @ 2002-01-06  7:56 UTC (permalink / raw)
  To: dewar, paulus; +Cc: gcc, linux-kernel, trini, velco

> From: Paul Mackerras <paulus@samba.org>
> Date: Sun, 6 Jan 2002 16:32:05 +1100 (EST)

> * I need a way to tell the compiler not to make any assumptions about
>   what objects that such a pointer might or might not point to, so
>   that the effect of dereferencing the pointer is simply to access the
>   memory at the address I gave, and is not considered "undefined"
>   regardless of how I might have constructed the address.

> GCC already does the first and third, but there doesn't seem to be a
> clean and reliable way to do the second.

I gave such a snippet of code in my previous posting.  Please show me
when it doesn't work.  I am unaware.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06  4:26 dewar
  2002-01-06  5:32 ` Paul Mackerras
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-06  4:26 UTC (permalink / raw)
  To: dewar, paulus; +Cc: gcc, linux-kernel, trini, velco

<<There are some C compilers that are useful for implementing a kernel,
that's true.  But when the maintainers of such a compiler say things
that imply that they feel they are constrained only by the standard
and not by the needs of their users, it is very discouraging.
>>

What is important is for these users to *clearly* and at least 
semi-formally, state their needs. Saying general things about the need
to be useful is hardly helpful!

You quote Florian:

> You cannot manipulate machine addresses in C because C is
> defined as a high-level language, without backdoors to such low-level
> concepts as machine addresses.

Unfortunately Florian is right. The ability in C to manipulate low-level
concepts such as machine addresses is NOT part of the language, but rather
comes from exploiting aspects that are deliberately left implementation
dependent. This is why it is so important to formally state the requirements
that are being depended on.

I don't think anyone seriously objects to trying to formulate solutions
to what is indeed a very important problem.

But it is hardly helpful for people to take the attitude "we wrote this
kernel, and it worked, and any change to the compiler that stops it from
working is unacceptable".

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-06  0:52 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-06  0:52 UTC (permalink / raw)
  To: jkl, jsm28
  Cc: Dautrevaux, Franz.Sirl-kernel, benh, dewar, fw, gcc, jtv,
	linux-kernel, linuxppc-dev, minyard, paulus, rth, trini, velco

<<Or to put it another way: The Linux kernel developers NEED an
implementation defined way to build a pointer from an address.  If
arithmatic on byte pointers isn't it (which is perfectly understandable)
and casting a pointer from an integer isn't it, then can someone please
tell us (not just "that will work for now" or "that will probably work")
how do we do that?
>>

Now that's a very reasonable question. Note that it is not just
kernel developers who need this, anyone doing memory mapped I/O
needs similar capabilities. They are present explicitly in Ada
(with address clauses), but not in C, so you do indeed need to
decide how to provide this capability in a reasonable manner.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-04 22:43 dewar
  2002-01-06  3:40 ` Paul Mackerras
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-04 22:43 UTC (permalink / raw)
  To: fw, paulus; +Cc: gcc, linux-kernel, linuxppc-dev, trini, velco

<<Sorry, you are correct.  I should have written "One of the reasons why
C used to be a good language for writing operating system kernels ..."
>>

C is perfectly well suited for writing operating system kernels, but you
absolutely HAVE to know what you are doing, and that includes knowing the
C standard accurately, and clearly identifying any implementation dependent
behavior that you are counting on.

The "used to be" is bogus. The (base + offset) memory model of C has been
there since the earliest days of the definition of C. The only thing that
"used to be" the case is that people ignored these rules freely and since
compilers were fairly stupid, they got away with this rash behavior.


^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-04 12:15 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-04 12:15 UTC (permalink / raw)
  To: fw, paulus; +Cc: gcc, linux-kernel, linuxppc-dev, trini, velco

<<But this is not the memory model of C!  Adding an offset to a pointer
is an operation involving objects defined by the C language, and not
machine registers.  Sometimes, this makes a noticeable difference.
>>

Indeed Alex Stepanov notes that Ada unlike C, *does* have general pointer
arithmetic, assuming a linear address space, and finds the lack of this in
C a problem :-) :-)

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-04 12:14 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-04 12:14 UTC (permalink / raw)
  To: dewar, fw
  Cc: Dautrevaux, Franz.Sirl-kernel, benh, gcc, jtv, linux-kernel,
	linuxppc-dev, minyard, paulus, rth, trini, velco

<<We have seen much trouble in this area before, but I doubt we can
avoid all of them by proper documentation.  Quite a few people seem to
write some C code, check that it works, look at the generated machine
code, and if it seems to be correct, the C code is considered to be
correct.
>>

We can't avoid people writing wrong code, but we can avoid debate as to
whether the code is right or wrong :-)

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-03 13:28 dewar
  2002-01-04  8:38 ` Florian Weimer
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-03 13:28 UTC (permalink / raw)
  To: Dautrevaux, paulus
  Cc: Franz.Sirl-kernel, benh, gcc, jtv, linux-kernel, linuxppc-dev,
	minyard, rth, trini, velco

<<No, in fact the kernel isn't written in ANSI C. :)
If nothing else, the fact that it uses a lot of gcc-specific
extensions rules that out.  And it assumes that you can freely cast
pointers to unsigned longs and back again.  I'm sure others can add to
this list.
>>

Most certainly this list should exist in precise defined form. It is not
unreasonable to have a specific list of features that

a) significant programs rely on, and are allowed to rely on
b) gcc promises to implement as specified, regardless of the standard

What is not reasonable is to have various people informally guess at things
that "obviously" can be expected to work in any "reasonable" C implementation.
It is this kind of informality that is asking for trouble.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-03 12:51 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-03 12:51 UTC (permalink / raw)
  To: law, paulus; +Cc: gcc, linux-kernel, linuxppc-dev, trini, velco

<<And before anyone says the PA is unbelievably strange and nobody else would
make the same mistakes -- the mn10300 (for which a linux port does exist)
has the same failings.
>>

Not clear these are failings, at least with respect to C, since the
addressing models are completely consistent with the C language, just
not consistent with some abuses of it.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-03 10:35 Bernard Dautrevaux
  0 siblings, 0 replies; 202+ messages in thread
From: Bernard Dautrevaux @ 2002-01-03 10:35 UTC (permalink / raw)
  To: 'paulus@samba.org', Joe Buck
  Cc: dewar, velco, gcc, linux-kernel, linuxppc-dev, trini

> -----Original Message-----
> From: Paul Mackerras [mailto:paulus@samba.org]
> Sent: Thursday, January 03, 2002 4:12 AM
> To: Joe Buck
> Cc: dewar@gnat.com; velco@fadata.bg; gcc@gcc.gnu.org;
> linux-kernel@vger.kernel.org; linuxppc-dev@lists.linuxppc.org;
> trini@kernel.crashing.org
> Subject: Re: [PATCH] C undefined behavior fix
> 
> 
> Joe Buck writes:
> 
> > There is already such a project under development: see
> > 
> > http://gcc.gnu.org/projects/bp/main.html
> > 
> > This is a modification to gcc that implements pointers as triples.
> > While there is a performance penalty for doing this, it can 
> completely
> > eliminate the problem of exploitable buffer overflows.  
> However, programs
> > that violate the rules of ISO C by generating out-of-range 
> pointers will
> > fail.
> 
> What will it do if I cast a pointer to unsigned long?  Or if I cast an
> unsigned long to a pointer?  The kernel does both of these things, and
> in a lot of places.
> 
> Part of my beef with what gcc-3 is doing is that I take a pointer,
> cast it to unsigned long, do something to it, cast it back to a
> pointer, and gcc _still_ thinks it's knows what I am doing.  It
> doesn't.

So say it to him: the problem is that the C language gives a quite precise
meaning to the RELOC macro code: When writing RELOC("some string") you say
to the C compiler: look, I want a pointer *in the string* at offset
0xC0000000. The GCC does exactly that. Afterwards it use this for optimizing
strcpy, but you fooled it before and it may be fooled for other cases (e.g.
if you do strlen(RELOC("xxx")) or RELOC("0123456789ABCDEF")[x] in a
"print_hexadecimal" function...).

There is ways in GCC to be sure the compiler forgets what it knows about a
value and use it as you provide it; one of the cleaner is using assembly
language. Note that someone proposed the use of a no-operation asm
instruction that just pretend to change the value returned. If the asm
instruction is furthermore declared "volatile" (I don't remember if it was)
then GCC guarantees that the instruction will not be optimzed away in any
case and so, as the kernel *knows* that RELOC("some string") is effectively
yielding the proper bit-level representation for a valid pointer to the
string th eprogrammer wants, GCC will trust the code and all will be OK.

And all this is just fixing ONE line in the kernel. Is that too much of a
job to do witout discussing it at will in several dozen messages?

Just my .02 euros

	Bernard

--------------------------------------------
Bernard Dautrevaux
Microprocess Ingenierie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-03  0:49 dewar
  0 siblings, 0 replies; 202+ messages in thread
From: dewar @ 2002-01-03  0:49 UTC (permalink / raw)
  To: dewar, jtv; +Cc: gcc, jbuck, linux-kernel, linuxppc-dev, paulus, trini, velco

<<At the risk of going off topic, you can take the non-element's address but
you can't actually touch it.  So provided your architecture supports
pointer arithmetic beyond the end of the segment, your only remaining
worries are (1) that you don't stumble into the NULL address (which need
not be zero), and (2) that the address isn't reused as a valid element of
something else.  I'm not so sure the latter is even a requirement.
>>

Ah! But you can compare it, and on a segmented architecture like the 286,
the address just past the end of the array can wrap to zero if the array
is allocated right up to the end of the segment. This is not theory, at
least one C compiler on the 286 had this bug!

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-03  0:12 dewar
  2002-01-03  0:32 ` jtv
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-03  0:12 UTC (permalink / raw)
  To: dewar, jbuck; +Cc: gcc, linux-kernel, linuxppc-dev, paulus, trini, velco

<<This is a modification to gcc that implements pointers as triples.
While there is a performance penalty for doing this, it can completely
eliminate the problem of exploitable buffer overflows.  However, programs
that violate the rules of ISO C by generating out-of-range pointers will
fail.
>>

Note incidentally that the C rules that allow referencing the address just
past the end of an array (an irregularity that recognizes the infeasibility
of declaring the common idiom for (a=b;a<&b[10];a++)) has an interesting
consequence on a segmented machine, namely that you cannot allocate an
array too near the end of the segment.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-02 23:53 dewar
  2002-01-02 23:59 ` Joe Buck
  0 siblings, 1 reply; 202+ messages in thread
From: dewar @ 2002-01-02 23:53 UTC (permalink / raw)
  To: paulus, velco; +Cc: gcc, linux-kernel, linuxppc-dev, trini

<<One of the reasons why C is a good language for the kernel is that its
memory model is a good match to the memory organization used by the
processors that linux runs on.  Thus, for these processors, adding an
offset to a pointer is in fact simply an arithmetic addition.  Combine
that with the fact that the kernel is far more aware of how stuff is
laid out in its virtual memory space than most C programs, and you can
see that it is reasonable for the kernel to do pointer arithmetic
which might be undefined according to the strict letter of the law,
but which in fact works correctly on the class of processors that
Linux runs on, for all reasonable compiler implementations.
>>

The concept of "all reasonable compiler implementations" is a very dubious
one. There is nothing to stop a valid C compiler from building assertions
based on the quoted paragraph from the C standard, e.g. it could derive
valid range information from knowing that an offset was constrained to
certain limits. So writing bogus C like this is risky, and as compilers
get more sophisticated, one is likely to hear screams, but they are not
justified in my opinion. There is no excuse for such abuse.

^ permalink raw reply	[flat|nested] 202+ messages in thread
* Re: [PATCH] C undefined behavior fix
@ 2002-01-02 17:40 Petr Vandrovec
  2002-01-02 22:24 ` David Woodhouse
  0 siblings, 1 reply; 202+ messages in thread
From: Petr Vandrovec @ 2002-01-02 17:40 UTC (permalink / raw)
  To: Paul Koning; +Cc: trini, velco, linux-kernel, gcc, linuxppc-dev

On  2 Jan 02 at 11:45, Paul Koning wrote:
> 
> It might be interesting for the compiler to warn about this coding
> error (since it presumably can detect it).  But "fixing" the behavior
> of undefined code seems like a strange thing to do.

It is even worse (gcc 2.95.4 20011223 (Debian prerelease), i386).
Test code:

#include <string.h>
char* dst;
void main(void) {
   strcpy(dst, "test"+CONSTANT);
}

# gcc -O2 -S test.c -DCONSTANT=10
test.c: In function `main':
test.c:4: warning: offset outside bounds of constant string
...
and compiler generated correct code (call to strcpy with "test"+10).

But:
# gcc -O2 -S test.c -DCONSTANT=0x80000000
test.c: In function `main':
test.c:4: warning: offset outside bounds of constant string
gcc: Internal compiler error: program cc1 got fatal signal 11

(and for CONSTANT < 5 it of course generated correct code to fill
dst with string contents; and yes, I know that code will sigsegv on
run because of dst is not initialized - but it should die at runtime,
not at compile time).

So we should definitely change RELOC(), or sooner or later gcc will
die on such code :-(

Debian's gcc 3.0.3-1 generates:
0 <= CONSTANT <= 4: fills dst directly with constant
5 <= CONSTANT <= 0x7FFFFFFF: emit warnings + use strcpy()
0x80000000U <= CONSTANT <= 0xFFFFFFFFU: use strcpy() silently
... and it does not die.
                                            Best regards,
                                                Petr Vandrovec
                                                vandrove@vc.cvut.cz
                                                

^ permalink raw reply	[flat|nested] 202+ messages in thread
* RE: [PATCH] C undefined behavior fix
@ 2002-01-02 10:02 Bernard Dautrevaux
  2002-01-02 23:02 ` Paul Mackerras
  0 siblings, 1 reply; 202+ messages in thread
From: Bernard Dautrevaux @ 2002-01-02 10:02 UTC (permalink / raw)
  To: 'Tom Rini', Momchil Velikov; +Cc: linux-kernel, gcc, linuxppc-dev

> -----Original Message-----
> From: Tom Rini [mailto:trini@kernel.crashing.org]
> Sent: Wednesday, January 02, 2002 12:44 AM
> To: Momchil Velikov
> Cc: linux-kernel@vger.kernel.org; gcc@gcc.gnu.org;
> linuxppc-dev@lists.linuxppc.org
> Subject: Re: [PATCH] C undefined behavior fix
> 
> 
> On Wed, Jan 02, 2002 at 01:03:25AM +0200, Momchil Velikov wrote:
> 
> > The appended patch fix incorrect code, which interferes badly with
> > optimizations in GCC 3.0.4 and GCC 3.1.
> > 
> > The GCC tries to replace the strcpy from a constant string 
> source with
> > a memcpy, since the length is know at compile time.
> 
> Check the linuxppc-dev archives, but this has been discussed 
> before, and
> it came down to a few things.
> 1) gcc shouldn't be making this optimization, and Paulus (who 
> wrote the
> code) disliked this new feature.  

Why? If memcpy can then be expanded in line, and the string is short, this
can be a *huge* win...

> As a subnote, what you sent was sent
> to Linus with a comment about working around a gcc-3.0 
> bug/feature, and
> was rejected because of this.
> 2) We could modify the RELOC macro, and not have this problem.  The
> patch was posted, but not acted upon.

I think we MUST modify the RELOC macro. Currently the code has an undefined
meaning WRT th eC standard, so is allowed to do almost anything from working
as expected (quite bad in fact: it may suddenly fail when sth is modified
elsewhere), to triggering the 3rd World War :-)

> 3) We could also try turning off this particular optimization
> (-fno-builtin perhaps) on this file, and not worry about it.

That's a compiler dependant way to fix the problem that creates a constraint
on the compiler: it MUST then from now continue to have a given behaviour to
some undefined feature (that is in fact not even documented...) 

Note that the RELOC macro triggers an UNDEFINED behaviour, not an
IMPLEMENTATION DEFINED one, so the compiler writer is free of any constraint
and that would be a genuine extension the the C language to fix the
behaviour.

	Bernard

--------------------------------------------
Bernard Dautrevaux
Microprocess Ingenierie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

^ permalink raw reply	[flat|nested] 202+ messages in thread
* [PATCH] C undefined behavior fix
@ 2002-01-01 23:03 Momchil Velikov
  2002-01-01 23:43 ` Tom Rini
                   ` (3 more replies)
  0 siblings, 4 replies; 202+ messages in thread
From: Momchil Velikov @ 2002-01-01 23:03 UTC (permalink / raw)
  To: linux-kernel; +Cc: gcc, linuxppc-dev

[Cc: to gcc list, in case someone wants to argue about standards]

The appended patch fix incorrect code, which interferes badly with
optimizations in GCC 3.0.4 and GCC 3.1.

The GCC tries to replace the strcpy from a constant string source with
a memcpy, since the length is know at compile time.

Thus 
   strcpy (dst, "abcdef" + 2)
gives
   memcpy (dst, "abcdef" + 2, 5)

However, GCC does not handle the case, when the above offset (2) is
not within the bounds of the string, which result in undefined
behavior according to ANSI/ISO C99.

The error is that
   strcpy (namep, "linux,phandle" + 0xc0000000);
gets emitted as
   memcpy (namep, "linux,phandle" + 0xc0000000, 14 - 0xc0000000);

Regards,
-velco

--- 1.3/arch/ppc/kernel/prom.c	Wed Dec 26 18:27:54 2001
+++ edited/arch/ppc/kernel/prom.c	Tue Jan  1 22:53:23 2002
@@ -997,7 +997,7 @@
 		prev_propp = &pp->next;
 		namep = (char *) (pp + 1);
 		pp->name = PTRUNRELOC(namep);
-		strcpy(namep, RELOC("linux,phandle"));
+		memcpy (namep, RELOC("linux,phandle"), sizeof("linux,phandle"));
 		mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1);
 		pp->value = (unsigned char *) PTRUNRELOC(&np->node);
 		pp->length = sizeof(np->node);

^ permalink raw reply	[flat|nested] 202+ messages in thread

end of thread, other threads:[~2002-01-11  9:52 UTC | newest]

Thread overview: 202+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-01-03 10:05 [PATCH] C undefined behavior fix Bernard Dautrevaux
2002-01-03 10:49 ` Paul Mackerras
2002-01-03 11:59   ` Lars Brinkhoff
2002-01-03 23:53     ` Paul Mackerras
2002-01-04  9:52       ` Lars Brinkhoff
2002-01-05  6:45         ` Paul Mackerras
2002-01-06  0:20           ` Lars Brinkhoff
2002-01-09  9:28   ` Fergus Henderson
2002-01-09 10:58     ` Gabriel Dos Reis
  -- strict thread matches above, loose matches on Subject: below --
2002-01-10 19:01 Bernard Dautrevaux
2002-01-10 12:18 dewar
2002-01-10 12:37 ` Erik Trulsson
2002-01-10 15:27   ` Florian Weimer
2002-01-10  9:03 Bernard Dautrevaux
2002-01-10 10:40 ` David Weinehall
2002-01-10  4:33 dewar
2002-01-10  2:16 dewar
2002-01-10  1:22 dewar
2002-01-10  1:21 dewar
2002-01-10  4:37 ` Tim Hollebeek
2002-01-09 21:54 dewar
2002-01-09 20:32 dewar
2002-01-09 21:43 ` Paul Koning
2002-01-09 20:08 dewar
2002-01-09 19:53 mike stump
2002-01-09 20:12 ` Paul Koning
2002-01-09 10:42 dewar
2002-01-09 10:41 Bernard Dautrevaux
2002-01-09 21:59 ` Gérard Roudier
2002-01-09 10:40 dewar
2002-01-09  9:06 Bernard Dautrevaux
2002-01-09  9:25 ` Bernd Petrovitsch
2002-01-09  2:18 dewar
2002-01-09  2:13 dewar
2002-01-09  1:51 mike stump
2002-01-09  1:19 dewar
2002-01-09  0:51 dewar
2002-01-08 11:12 Bernard Dautrevaux
2002-01-11  9:52 ` Horst von Brand
2002-01-08  9:44 Bernard Dautrevaux
2002-01-08 11:44 ` 'jtv'
2002-01-08  0:16 mike stump
2002-01-08 11:33 ` jtv
2002-01-07 23:46 mike stump
2002-01-07 23:20 dewar
2002-01-07 23:15 dewar
2002-01-07 23:12 dewar
2002-01-07 23:11 dewar
2002-01-07 22:56 mike stump
2002-01-07 22:26 Tim McDaniel
2002-01-07 19:36 mike stump
2002-01-07 21:21 ` Theodore Tso
2002-01-08  0:19 ` Paul Mackerras
2002-01-08  1:02   ` Richard Henderson
2002-01-07 19:18 mike stump
2002-01-07 19:17 Bernard Dautrevaux
2002-01-07 18:38 mike stump
2002-01-07 13:29 Bernard Dautrevaux
2002-01-07 13:24 Bernard Dautrevaux
2002-01-07 21:49 ` jtv
2002-01-07 22:28   ` Tim Hollebeek
2002-01-07 22:16     ` jtv
2002-01-08  0:27       ` J.A. Magallon
2002-01-08 11:41         ` jtv
2002-01-08 12:36           ` Alexandre Oliva
2002-01-08 12:58             ` jtv
2002-01-09 19:47         ` Gérard Roudier
2002-01-09 20:44           ` jtv
2002-01-09 23:49           ` J.A. Magallon
2002-01-10  0:19             ` Peter Barada
2002-01-10  1:47               ` Fergus Henderson
2002-01-10 15:30                 ` Peter Barada
2002-01-10 10:13             ` Matthias Benkmann
2002-01-10 10:44           ` Bernd Petrovitsch
2002-01-06 19:32 dewar
2002-01-06 19:29 dewar
2002-01-06 19:29 dewar
2002-01-06 18:37 mike stump
2002-01-06 18:24 mike stump
2002-01-06 20:37 ` Gabriel Dos Reis
2002-01-06 21:59   ` Paul Mackerras
2002-01-06 22:19     ` Jakub Jelinek
2002-01-07  0:09       ` Tom Rini
2002-01-07  1:40         ` Alexandre Oliva
2002-01-06 18:20 mike stump
2002-01-06 16:22 dewar
2002-01-06 16:39 ` Alan Cox
2002-01-06 19:27   ` Laurent Guerby
2002-01-06 19:43     ` Alan Cox
2002-01-06 13:43 dewar
2002-01-06 13:55 ` Laurent Guerby
2002-01-06 13:41 dewar
2002-01-06 16:58 ` Gabriel Dos Reis
2002-01-06 13:16 dewar
2002-01-06 13:22 ` Gabriel Dos Reis
2002-01-06 13:07 dewar
2002-01-06 13:05 dewar
2002-01-06 13:41 ` Laurent Guerby
2002-01-06  7:56 mike stump
2002-01-06  4:26 dewar
2002-01-06  5:32 ` Paul Mackerras
2002-01-06 11:09   ` Momchil Velikov
2002-01-06  0:52 dewar
2002-01-04 22:43 dewar
2002-01-06  3:40 ` Paul Mackerras
2002-01-04 12:15 dewar
2002-01-04 12:14 dewar
2002-01-03 13:28 dewar
2002-01-04  8:38 ` Florian Weimer
2002-01-04 11:35   ` Joseph S. Myers
2002-01-05 19:25     ` jkl
2002-01-05 19:37       ` Joseph S. Myers
2002-01-05 20:06         ` jkl
2002-01-05 21:42           ` Joseph S. Myers
2002-01-06  4:09         ` Paul Mackerras
2002-01-05 20:01       ` Florian Weimer
2002-01-05 20:17         ` jkl
2002-01-05 20:51           ` Florian Weimer
2002-01-03 12:51 dewar
2002-01-03 10:35 Bernard Dautrevaux
2002-01-03  0:49 dewar
2002-01-03  0:12 dewar
2002-01-03  0:32 ` jtv
2002-01-06 19:37   ` Alexandre Oliva
2002-01-02 23:53 dewar
2002-01-02 23:59 ` Joe Buck
2002-01-03  3:12   ` Paul Mackerras
2002-01-03 15:45     ` Joe Buck
2002-01-02 17:40 Petr Vandrovec
2002-01-02 22:24 ` David Woodhouse
2002-01-02 22:39   ` Joe Buck
2002-01-02 22:59     ` David Woodhouse
2002-01-03 18:44   ` Alexandre Oliva
2002-01-02 10:02 Bernard Dautrevaux
2002-01-02 23:02 ` Paul Mackerras
2002-01-02 23:27   ` Momchil Velikov
2002-01-01 23:03 Momchil Velikov
2002-01-01 23:43 ` Tom Rini
2002-01-02  6:54   ` Momchil Velikov
2002-01-02 15:39     ` Tom Rini
2002-01-02 15:50       ` Jakub Jelinek
2002-01-02 16:45         ` Paul Koning
2002-01-02 22:56     ` Paul Mackerras
2002-01-02 23:37       ` Momchil Velikov
2002-01-03  2:51         ` Paul Mackerras
2002-01-03  6:29           ` law
2002-01-03 13:16             ` Lars Brinkhoff
2002-01-04  9:05       ` Florian Weimer
2002-01-04 22:14         ` Paul Mackerras
2002-01-02 14:56   ` Joseph S. Myers
2002-01-02 10:29 ` Florian Weimer
2002-01-02 10:41   ` Momchil Velikov
2002-01-02 13:11     ` Jakub Jelinek
2002-01-02 15:54       ` Tom Rini
2002-01-02 11:28 ` Aaron Lehmann
2002-01-02 11:40   ` Momchil Velikov
2002-01-02 15:59     ` Tom Rini
2002-01-02 11:48   ` Alan Cox
2002-01-02 19:09 ` Tom Rini
2002-01-02 20:13   ` Joe Buck
2002-01-02 20:42     ` Tom Rini
2002-01-02 21:36   ` Richard Henderson
2002-01-02 22:05     ` Tom Rini
2002-01-02 22:23       ` jtv
2002-01-02 23:12         ` Tom Rini
2002-01-02 23:45           ` jtv
2002-01-03  0:01             ` Tom Rini
2002-01-03  0:07               ` Richard Henderson
2002-01-03  0:16                 ` Tom Rini
2002-01-03  1:12                   ` Richard Henderson
2002-01-03  0:20                 ` jtv
2002-01-03  2:33                 ` Paul Mackerras
2002-01-03  8:32                   ` Richard Henderson
2002-01-03 10:10                     ` Paul Mackerras
2002-01-03 22:41                       ` Tim Hollebeek
2002-01-04  8:48                       ` Florian Weimer
2002-01-03 10:03                   ` Geert Uytterhoeven
2002-01-03  0:25               ` Alan Cox
2002-01-03  0:35                 ` David Woodhouse
2002-01-03  2:10                   ` Tom Rini
2002-01-03 22:39                     ` Pavel Machek
2002-01-04  9:29                       ` Paul Mackerras
2002-01-03 15:46                   ` Edgar Toernig
2002-01-03 16:48                     ` Momchil Velikov
2002-01-03 17:13                     ` jtv
2002-01-03 21:26                   ` Daniel Jacobowitz
2002-01-02 22:27       ` Richard Henderson
2002-01-02 22:35         ` Tom Rini
2002-01-02 22:44           ` Richard Henderson
2002-01-02 22:50             ` Tom Rini
2002-01-03 22:40         ` Pavel Machek
2002-01-04  8:42           ` Richard Henderson
2002-01-02 23:11   ` Paul Mackerras
2002-01-02 23:26     ` Tom Rini
2002-01-02 23:28     ` Momchil Velikov
2002-01-02 23:34       ` Tom Rini
2002-01-03  0:19         ` jtv
2002-01-03  0:29           ` Tom Rini
2002-01-03  1:03             ` jtv
2002-01-03  1:17               ` Tom Rini
2002-01-03 17:44                 ` jtv
2002-01-04  8:42   ` Florian Weimer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox