Discussion:
What you have to look for on 64 bit
Corinna Vinschen
2013-03-19 10:48:06 UTC
Permalink
Hi guys,


it just occured to me that it might be helpful to report a typical 64
bit porting bug we observed yesterday, while testing the sigdelayed
patch.

Kai was going to run the gas testsuite which requires dejagnu and
expect, but expect simply crashed. After a bit of debugging it
turned out that expect was calling the openpty function, like so:

char *master, *slave,*name;
openpty (master, slave, name, 0, 0);

The last two parameters to openpty are pointers, just like the first
three. However, the constant 0 is int by default. int is 32 bit, but
pointers are 64 bit on x86_64. This would have been no problem, if
expect had included the pty.h header which provides a prototype for
openpty. GCC would have known to extend the 0 constants to 64 bit in
this case. Alas, expect did not include pty.h and so the 0 were not 64
bit extended, but given as 32 bit parameter to openpty. Since all
parameters take 64 bit slots, the upper 32 bit of the parameters were
undefined. Instead of NULL pointers, openpty got pointers with just
the lower 32 bit guaranteed to be 0.

Another simple example: Try `printf ("%s\n", strerror (EINVAL));'
without including string.h. Same thing as above. The missing prototype
for strerror leads gcc to think it's a function returning int. No
problem on 32 bit where sizeof(int)==sizeof(char*), but on 64 bit...

<annoying lecturing>

Bottom line is, when building packages for 64 bit, make sure to
switch on warnings for missing prototypes and if you get these
warnings, make sure to include the right headers to get the prototype.
Otherwise, SEGV ensues.

</annoying lecturing>


Hope that helps,
Corinna
--
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat
Ken Brown
2013-03-19 17:12:27 UTC
Permalink
Post by Corinna Vinschen
Hi guys,
it just occured to me that it might be helpful to report a typical 64
bit porting bug we observed yesterday, while testing the sigdelayed
patch.
Kai was going to run the gas testsuite which requires dejagnu and
expect, but expect simply crashed. After a bit of debugging it
char *master, *slave,*name;
openpty (master, slave, name, 0, 0);
The last two parameters to openpty are pointers, just like the first
three. However, the constant 0 is int by default. int is 32 bit, but
pointers are 64 bit on x86_64. This would have been no problem, if
expect had included the pty.h header which provides a prototype for
openpty. GCC would have known to extend the 0 constants to 64 bit in
this case. Alas, expect did not include pty.h and so the 0 were not 64
bit extended, but given as 32 bit parameter to openpty. Since all
parameters take 64 bit slots, the upper 32 bit of the parameters were
undefined. Instead of NULL pointers, openpty got pointers with just
the lower 32 bit guaranteed to be 0.
Another simple example: Try `printf ("%s\n", strerror (EINVAL));'
without including string.h. Same thing as above. The missing prototype
for strerror leads gcc to think it's a function returning int. No
problem on 32 bit where sizeof(int)==sizeof(char*), but on 64 bit...
<annoying lecturing>
Bottom line is, when building packages for 64 bit, make sure to
switch on warnings for missing prototypes and if you get these
warnings, make sure to include the right headers to get the prototype.
Otherwise, SEGV ensues.
</annoying lecturing>
I tried your printf example, and as you said, it compiled but crashed.
But gcc didn't report the missing prototype, even though I compiled with
`gcc -Wmissing-prototypes'. Did I do something wrong? Here's the
source file:

#include <stdio.h>
#include <errno.h>
int
main ()
{
printf ("%s\n", strerror (EINVAL));
}

Ken
marco atzeri
2013-03-19 17:33:14 UTC
Permalink
Post by Ken Brown
Post by Corinna Vinschen
Hi guys,
it just occured to me that it might be helpful to report a typical 64
bit porting bug we observed yesterday, while testing the sigdelayed
patch.
Kai was going to run the gas testsuite which requires dejagnu and
expect, but expect simply crashed. After a bit of debugging it
char *master, *slave,*name;
openpty (master, slave, name, 0, 0);
The last two parameters to openpty are pointers, just like the first
three. However, the constant 0 is int by default. int is 32 bit, but
pointers are 64 bit on x86_64. This would have been no problem, if
expect had included the pty.h header which provides a prototype for
openpty. GCC would have known to extend the 0 constants to 64 bit in
this case. Alas, expect did not include pty.h and so the 0 were not 64
bit extended, but given as 32 bit parameter to openpty. Since all
parameters take 64 bit slots, the upper 32 bit of the parameters were
undefined. Instead of NULL pointers, openpty got pointers with just
the lower 32 bit guaranteed to be 0.
Another simple example: Try `printf ("%s\n", strerror (EINVAL));'
without including string.h. Same thing as above. The missing prototype
for strerror leads gcc to think it's a function returning int. No
problem on 32 bit where sizeof(int)==sizeof(char*), but on 64 bit...
<annoying lecturing>
Bottom line is, when building packages for 64 bit, make sure to
switch on warnings for missing prototypes and if you get these
warnings, make sure to include the right headers to get the prototype.
Otherwise, SEGV ensues.
</annoying lecturing>
I tried your printf example, and as you said, it compiled but crashed.
But gcc didn't report the missing prototype, even though I compiled with
`gcc -Wmissing-prototypes'. Did I do something wrong? Here's the
#include <stdio.h>
#include <errno.h>
int
main ()
{
printf ("%s\n", strerror (EINVAL));
}
Ken
with -Wall

prova.c: In function ‘main’:
prova.c:6:3: warning: implicit declaration of function ‘strerror’
[-Wimplicit-function-declaration]
printf ("%s\n", strerror (EINVAL));
^
prova.c:6:3: warning: format ‘%s’ expects argument of type ‘char *’, but
argument 2 has type ‘int’ [-Wformat=]
prova.c:6:3: warning: format ‘%s’ expects argument of type ‘char *’, but
argument 2 has type ‘int’ [-Wformat=]
prova.c:7:1: warning: control reaches end of non-void function
[-Wreturn-type]
}
^
Corinna Vinschen
2013-03-19 17:46:31 UTC
Permalink
Post by Ken Brown
Post by Corinna Vinschen
<annoying lecturing>
Bottom line is, when building packages for 64 bit, make sure to
switch on warnings for missing prototypes and if you get these
warnings, make sure to include the right headers to get the prototype.
Otherwise, SEGV ensues.
</annoying lecturing>
I tried your printf example, and as you said, it compiled but
crashed. But gcc didn't report the missing prototype, even though I
compiled with `gcc -Wmissing-prototypes'. Did I do something wrong?
#include <stdio.h>
#include <errno.h>
int
main ()
{
printf ("%s\n", strerror (EINVAL));
}
Sorry, I didn't notice that. Try -Wimplicit-function-declaration
instead.


Corinna
--
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat
Kai Tietz
2013-03-20 10:03:30 UTC
Permalink
Hi,

I would like to add some notes and tips about porting for the new
cygwin64 target, too.

First, the options -Wall and -Wextra should be turned on always for
compiling. And the warnings shown should be fixed, or at least looked
at in detail. My experience has shown that a lot of them are
indicating that there might be serious issues.

It is important to understand that cygwin64 and native windows 64-bit
targets are sharing same ABI, beside the size of the type 'long'. The
native version defines 'long' type as a 32-bit wide integer-scalar,
but for cygwin64 we choose to make it 64-bit wide as for most 64-bit
linux, too.

This difference becomes important when you begin to use the native
windows platform headers. Here it is necessary that you are using
current trunk version of mingw-w64's platform-headers. Those headers
are capable to handle this ABI-difference for cygwin64 proper. Those
headers are supporting to translate Win32 ABI in regards of 'long'
type size for cygwin and native Windows 'long'. E.g ,the platform
type LONG is not identical to 'long' type for cygwin64 target. So
please use, if you are forced to use Win32 API, the platform
abstraction types instead of the standard C integer-types.

Well, this brings me to a side-note I would like to tell about. Please
avoid to talk about Win64. There is no Win64 API. There is only the
Win32 API. The Win32 API exists for different architectures. Two of
them are the Intel-architectures x64, and x86. So please avoid the
term "Win64 API", as it is simply misleading and wrong.

Regards,
Kai

Loading...