C undefined behavior fix
Quoted 11 lines
From: Paul Mackerras <[email protected]>
Date: Mon, 7 Jan 2002 08:59:47 +1100 (EST)
To: Gabriel Dos Reis <[email protected]>Quoted 3 lines
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.
Quoted 2 lines
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.
Quoted 2 lines
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.
Quoted 2 lines
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.
Quoted 2 lines
- 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.
Quoted 2 lines
- it is a statement, which makes it less convenient to use than an expression
? In my example, it is an expression.
Quoted 1 line
- it requires an extra dummy variable declaration.
Mine doesn't.
Quoted 2 lines
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.
Quoted 8 lines · mike stump
#define hide(x) ({ void *vp = x; asm ("" : "+r" (vp)); vp; })
Quoted 2 lines
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.
Quoted 6 lines
Quoted 2 lines
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.
Why not fix the problem by adding some a GCC-specific construct which allows the programmer to say, I know what I'm doing; don't make any assumptions about this pointer. (i.e., "my gun, my foot, my rules").
I.e., something like this:
#hide(x) (__builtin_gcc_this_is_not_the_pointer_you_were_looking_for__(x))
(or __builtin_gcc_jedi_mind_trick__, or pick some other name if you like :-)
That way, you don't have to posit adding AI to GCC in the future to be able to intuit what was going on, and programmers can take comfort in the fact the behaviour is will defined, and won't get screwed up when in GCC 4.0, the compiler writers decide that "Gee, most people write inefficient assembly; so let's go and reverse engineering people's __asm__ statements in an effort to 'optimize' their code".
- Ted
Quoted 8 lines · mike stump
#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.
Clear to you, I had to look up the gcc info pages to find out what the "+" constraint does. :)
Is the "r" constraint available (and reasonable) on all architectures that GCC targets?
Quoted 6 lines
Quoted 2 lines
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.
Quoted 6 lines
Quoted 2 lines
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 guess I am reacting to the criticism expressed in this thread against people who write code which happens to work with a particular compiler version but for which there is nothing in the standard or documentation which says that it should work or will continue to work. It seems to me that the asm is in that category. If the gcc maintainers were willing to document that side effect that would make me more comfortable with it. But it still seems like using an ax as a screwdriver to me.
Quoted 2 lines
Then move the bits to the right address before you execute the C code and code the thing that moves the bits in assembly.
Yes, I'm using -mrelocatable on the relevant files now instead of the RELOC macro. But there are still a couple of places where I need to take a pointer value which is valid when running at the initial address and adjust it so it will be valid later when running at the final address.
The broader issue is one of how the kernel can construct pointers from addresses in general and be sure that gcc won't assume it knows what the pointer points to. The kernel needs to be able to do this.
Quoted 4 lines
Quoted 2 lines
- it is a statement, which makes it less convenient to use than an expression
? In my example, it is an expression.
Well, it's a statement expression. :) Aren't those deprecated these days?
Quoted 3 lines
Quoted 1 line
- it requires an extra dummy variable declaration.
Mine doesn't.
<nitpicking> What's the "void *vp;" then? </nitpicking>
Quoted 5 lines
Quoted 2 lines
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.
That gives me no way to turn an address into a pointer.
Paul.
Quoted 2 lines · Paul Mackerras
Is the "r" constraint available (and reasonable) on all architectures that GCC targets?
Yes, though "g" is probably better for this purpose.
r~