phantom# /usr/sfw/bin/gcc -v Reading specs from /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/specs Configured with: /gates/sfw10/builds/sfw10-gate/usr/src/cmd/gcc/gcc-3.4.3/configure --prefix=/usr/sfw --with-as=/usr/sfw/bin/gas --with-gnu-as --with-ld=/usr/ccs/bin/ld --without-gnu-ld --enable-languages=c,c++ --enable-shared Thread model: posix gcc version 3.4.3 (csl-sol210-3_4-branch+sol_rpath)
This is a follow up to apache bug 34963 http://issues.apache.org/bugzilla/show_bug.cgi?id=39463 It seems to be present on at least Solaris 9 and 10. I'm not really sure how to describe this but the below text from a Sun Engineer with sample code explains / demonstrates the problem. Source code from Sun engineer to demonstrate problem. -------- Cut here -------- #include <stdio.h> #include <sys/sendfile.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <sys/mman.h> #include <unistd.h> int main (void) { sendfilevec64_t sfv[3]; int mmapfd; void *addr; /* Open a file to mmap */ if ((mmapfd = open ("/lib/libc.so", O_RDONLY)) == -1) { perror ("open of /lib/libc.so failed"); exit (1); } /* mmap file */ if ((addr = mmap (NULL, 8192, PROT_READ, MAP_SHARED, mmapfd, 0)) == MAP_FAILED) { perror ("mmap failed"); exit (1); } close (mmapfd); fprintf (stdout, "mmap() done. addr = %p\n", addr); sfv[0].sfv_off = (off64_t)addr; sfv[1].sfv_off = (long)addr; sfv[2].sfv_off = (unsigned long)addr; fprintf (stdout, "Value of sfv_off[0] = %llu\n", sfv[0].sfv_off); fprintf (stdout, "Value of sfv_off[1] = %llu\n", sfv[1].sfv_off); fprintf (stdout, "Value of sfv_off[2] = %llu\n", sfv[2].sfv_off); exit (0); } -------- Cut here -------- As you can see, it mmap's a file, then takes the same value and casts it as an off64_t (which it should be according to the definition of the struct sendfilevec64_t), and also as a "long" (which I believe the Apache apr_off_t type reduces to), then finally as an unsigned long. This was compiled with Sun's cc compiler (from Studio 10 or 11 I think). The output was this: $ cc -D_LARGEFILE64_SOURCE -o test test.c $ ./test mmap() done. addr = ff390000 Value of sfv_off[0] = 4281925632 Value of sfv_off[1] = 18446744073696509952 Value of sfv_off[2] = 4281925632 The correct value is given when cast either as the off64_t or as an unsigned value. When compiled and run using gcc (I happen to have version 3.4.3), the results are: $ gcc -Wall -D_LARGEFILE64_SOURCE -o test test.c test.c: In function `main': test.c:32: warning: cast from pointer to integer of different size $ ./test mmap() done. addr = ff390000 Value of sfv_off[0] = 18446744073696509952 Value of sfv_off[1] = 18446744073696509952 Value of sfv_off[2] = 4281925632 Here, the correct value is returned if an unsigned long is specified. I think there are two issues here: 1) If the correct type "off64_t" is used, gcc produces incorrect results. This would have to be investigated and taken up with the GCC team. 2) The data type "apr_off_t" is defined as a long, where it could (or should?) be defined as unsigned long. The obvious way forward to prevent any compiler dependencies would be to change the apr_off_t data type, but this is Apache's call. Please note that the above program is provided as is, and is only designed to demonstrate a particular point. It is a bit crude really, but I hope it serves its purpose! -- Summary: casting as off64_t gives wrong address for mmaped file using sendfilev64 on solaris Product: gcc Version: 3.4.3 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: dbb at st-andrews dot ac dot uk http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29764