From 895ece012481194592198bf18a1b70790e784685 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 24 Apr 2013 16:09:43 +0000 Subject: [PATCH] * faq-programming.xml (faq.programming.64bitporting): New FAQ entry. (faq.programming.objective-c): Include gcc4. (faq.programming.make-execvp): Drop text discouraging usage of -j. (faq.programming.undeclared-functions): Drop entry. (faq.programming.x86-assembly): Ditto. (faq.programming.djgpp): Ditto. --- winsup/doc/ChangeLog | 11 +- winsup/doc/faq-programming.xml | 196 ++++++++++++++++++++++++++------- 2 files changed, 165 insertions(+), 42 deletions(-) diff --git a/winsup/doc/ChangeLog b/winsup/doc/ChangeLog index 9f66a7607..c49e3b474 100644 --- a/winsup/doc/ChangeLog +++ b/winsup/doc/ChangeLog @@ -1,4 +1,13 @@ -2013-04-23 Corinna Vinschen +2013-04-24 Corinna Vinschen + + * faq-programming.xml (faq.programming.64bitporting): New FAQ entry. + (faq.programming.objective-c): Include gcc4. + (faq.programming.make-execvp): Drop text discouraging usage of -j. + (faq.programming.undeclared-functions): Drop entry. + (faq.programming.x86-assembly): Ditto. + (faq.programming.djgpp): Ditto. + +2013-04-24 Corinna Vinschen * cygwinenv.sgml (cygwinenv-implemented-options): Change description for winsymlink option to explain new implementation. diff --git a/winsup/doc/faq-programming.xml b/winsup/doc/faq-programming.xml index bfc27fac7..c46e05f18 100644 --- a/winsup/doc/faq-programming.xml +++ b/winsup/doc/faq-programming.xml @@ -48,6 +48,158 @@ package. Or compile with the -s option to gcc. + +What do I have to look out for when porting applications to 64 bit Cygwin? + + +The Cygwin x86_64 toolchain is using the +LP64 +data model. That means, in contrast to Windows, which uses an +LLP64 +data model, sizeof(long) != sizeof(int), just as on Linux. + +For comparison: + + + Cygwin Windows Cygwin + Linux x86_64 Linux + Windows x86_64 + i686 + +sizeof(int) 4 4 4 +sizeof(long) 4 4 8 +sizeof(size_t) 4 8 8 +sizeof(void*) 4 8 8 + + +This difference can result in interesting problems, especially when +using Win32 functions, especially when using pointers to Windows +datatypes like LONG, ULONG, DWORD. Given that Windows is LLP64, all of +the aforementioned types are 4 byte in size, while `long' on 64 bit Cygwin +is 8 bytes. + +Take the example ReadFile: + + + ReadFile (HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED); + + +In the 32 bit Cygwin and Mingw environments, as well as in the 64 bit +Mingw environment, it is no problem to substitute DWORD with unsigned +long: + + + unsigned long number_of_bytes_read; + [...] + ReadFile (fhdl, buf, buflen, &number_of_bytes_read, NULL); + + +However, in 64 bit Cygwin, using LP64, number_of_bytes_read is 8 bytes +in size. But since ReadFile expects a pointer to a 4 byte type, the function +will only change the lower 4 bytes of number_of_bytes_read on return, while +the content of the upper 4 bytes stays undefined. + +Here are a few donts which should help porting +applications from the known ILP32 data model of 32 bit Cygwin, to the LP64 +data model of 64 bit Cygwin. Note that these are not Cygwin-only problems. +Many Linux applications suffered the same somewhat liberal handling of +datatypes when the AMD64 CPU was new. + + + + +Don't mix up int and long in printf/scanf. This: + + + int i; long l; + printf ("%d %ld\n", l, i); + + +may not print what you think it should. + + + +Don't mix int and long pointers. + + + long *long_ptr = (long *) &my_int; /* Uh oh! */ + *long_ptr = 42; + + +The assignment will write 8 bytes to the address of my_int. Since my_int +is only 4 bytes, something else gets randomly overwritten. +Finding this kind of bug is very hard, because you will often see a problem +which has no immediate connection to the actual bug. + + + +Don't mix int and pointers at all! This will +not work as expected anymore: + + + void *ptr; + printf ("Pointer value is %x\n", (int) ptr); + + +The value printed by printf is missing the upper 4 bytes, so the printed +value is very likely wrong. + + + +Along the same lines don't use the type int in +pointer arithmetic. Don't cast pointers to int, don't cast pointer +differences to int, and don't store pointer differences in an int type. +Use the types intptr_t, uintptr_t +and ptrdiff_t instead, they are designed for performing +pointer arithmetic. + + + +Don't make blind assumptions about the size of a POSIX +type. For instance, time_t is 8 bytes on 64 bit Cygwin, +while it is (still, at the time of writing this) 4 bytes on 32 bit Cygwin, +since time_t is based on the type long. + + + +Don't use functions returning pointers without declaration. +For instance + + + printf ("Error message is: %s\n", strerror (errno)); + + +This code will crash, unless you included +string.h. The implicit rule in C is that an undeclared +function is of type int. But int is 4 byte and pointers are 8 byte, so the +string pointer given to printf is missing the upper 4 bytes. + + + +Don't use C base types together with Win32 functions. +Keep in mind that DWORD, LONG, ULONG are *not* the same as long and unsigned +long. Try to use only Win32 datatypes in conjunction with Win32 API function +calls to avoid type problems. See the above ReadFile example. + + + +Don't mix Windows dataypes with POSIX type-specific +MIN/MAX values. + + + unsigned long l_max = ULONG_MAX; /* That's right. */ + ULONG w32_biggest = ULONG_MAX; /* Hey, wait! What? */ + ULONG w32_biggest = UINT_MAX; /* Ok, but borderline. */ + + +Again, keep in mind that ULONG (or DWORD) is not unsigned +long but rather unsigned int on 64 bit. + + + + + + Where is glibc? @@ -62,7 +214,7 @@ would be difficult. Where is Objective C? -Support for compiling Objective C is available in the gcc4-objc +Support for compiling Objective C is available in the gcc{4}-objc package; resulting binaries will depend on the libobjc2 package at runtime. @@ -72,10 +224,8 @@ package at runtime. Why does my make fail on Cygwin with an execvp error? -First of all, if you are using make -j[N], then stop. It doesn't -work well. Also beware of using non-portable shell features in your -Makefiles (see tips at ). +Beware of using non-portable shell features in your Makefiles (see tips +at ). Errors of make: execvp: /bin/sh: Illegal Argument or make: execvp: /bin/sh: Argument list too long are often @@ -681,15 +831,6 @@ This is right gcc hello.cc -lstdc++. use struct stat. It's 64 bit aware. - -I use a function I know is in the API, but I still get a link error. - - -The function probably isn't declared in the header files, or -the UNICODE stuff for it isn't filled in. - - - Can you make DLLs that are linked against libc ? @@ -758,17 +899,6 @@ data types, line numbers, local variables etc. - -Where can I find info on x86 assembly? - - -CPU reference manuals for Intel's current chips are available in -downloadable PDF form on Intel's web site: - -http://developer.intel.com/ - - - Shell scripts aren't running properly from my makefiles? @@ -848,19 +978,3 @@ executable. linker flag. - - -Why not use DJGPP ? - - -DJGPP is a similar idea, but for DOS instead of Win32. DJGPP uses a -"DOS extender" to provide a more reasonable operating interface for its -applications. The Cygwin toolset doesn't have to do this since all of -the applications are native WIN32. Applications compiled with the -Cygwin tools can access the Win32 API functions, so you can write -programs which use the Windows GUI. - -You can get more info on DJGPP by following -http://www.delorie.com/. - -