| Summary: | troubles w/ -m32 executables on both amd64 and i386 | ||
|---|---|---|---|
| Product: | Base System | Reporter: | isupov <isupov> |
| Component: | amd64 | Assignee: | freebsd-amd64 (Nobody) <amd64> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 6.2-RELEASE | ||
| Hardware: | Any | ||
| OS: | Any | ||
Currently, building i386 programs under FreeBSD/amd64 is not supported. The reason for this is you need the i386 includes to build your program, but they are not installed during a installworld (see stage 5.1 in src/Makefile.inc1). It's not clear in your report, are you recompiling the program under i386, or copying the binary from FreeBSD/amd64 to the FreeBSD/i386 system? If you build your program under FreeBSD/i386, does your program run without these problems on i386 and amd64? Scot *From:* "Scot Hetzel" <swhetzel@gmail.com> *Date:* Fri, 18 Jan 2008 10:07:26 -0600 >Currently, building i386 programs under FreeBSD/amd64 is not >supported. The reason for this is you need the i386 includes to build >your program, but they are not installed during a installworld (see >stage 5.1 in src/Makefile.inc1). I assume, that all needed includes are the same under amd64 and i386... Problems are not connected with sizeof(int) or prototyping. Unfortunately, I can't port my program (that is cernlib) to 64-bit (I try !), because one intensively uses int (and integer*4 :) to store pointers, so I need to compile it in 32-bit environment - if possible, on FreeBSD/amd64, if not - I should choose to continue using the FreeBSD/i386 on 64-bit CPU :( Note, that Sun's OpenLook (ports/x11-toolkits/xview{,-clients}) compiled, but not work under amd64 for the same reasons - pointer should fit into int. However 32-bit binaries are OK. At least, I encounter too less problematic places (really two - syscalls getrlimit() and lseek(), see below) during 32-bit compiling in comparison with porting to 64-bit... >It's not clear in your report, are you recompiling the program under >i386, or copying the binary from FreeBSD/amd64 to the FreeBSD/i386 >system? Failed binary produced under FreeBSD/amd64 as static w/ -m32 and executed on FreeBSD/amd64 and (after copying :) on FreeBSD/i386 - with the same faulty results. >If you build your program under FreeBSD/i386, does your program run >without these problems on i386 and amd64? Yes, binary produced under FreeBSD/i386 as static have not a problem during execution under both FreeBSD/i386 and FreeBSD/amd64. So I conclude, that problem possibly in FreeBSD/amd64's 32-bit compatibility support, at least in syscall getrlimit(). Furthermore, I have now yet another example of faulty syscall - lseek(). Example text (see below) compiled natively under i386 and amd64 works as expected (outputs the same): i386> ./tseek.32 or amd64> ./tseek.64 fildes=3, nbdo=0 isw=0, errno=0 1 stat=0 1 write(): res=4096, errno=0 fildes=3, nbdo=8192 isw=8192, errno=0 2 stat=0 2 write(): res=4096, errno=0 fildes=3, nbdo=4096 isw=4096, errno=0 3 stat=0 3 write(): res=4096, errno=0 However compiled under amd64 as cc -c -g -W -Wall -m32 -o tseek.o tseek.c cc -c -g -W -Wall -m32 -o cfseek.o cfseek.c cc -g -W -Wall -m32 -static -B/usr/lib32 -o tseek tseek.o cfseek.o says: amd64> ./tseek.32on64 fildes=3, nbdo=0 isw=0, errno=0 1 stat=0 1 write(): res=4096, errno=0 fildes=3, nbdo=8192 isw=-1, errno=22 error in CFSEEK: Invalid argument 2 stat=-1 2 write(): res=4096, errno=0 fildes=3, nbdo=4096 isw=-1, errno=22 error in CFSEEK: Invalid argument 3 stat=-1 3 write(): res=4096, errno=0 Produced output file shows, that lseek() really does nothing when failed. Note, that effect also subtle and depends on statements near (before and after) lseek(), and totally absent in simplified example, where wrapper cfseek_() eliminated. -----cut here-tseek.c---- #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <strings.h> void cfseek_(int *lundes, int *medium, int *nwrec, int *jcrec, int *stat); int main() { int fd; int medium=0, nwrec, jcrec, stat=0; off_t res=0; char mbuf[4096]; errno = 0; fd = open("./seek.dat", O_RDWR|O_TRUNC|O_CREAT, 0644); if (fd==-1) { printf("open(): %i\n", errno); exit(1); } nwrec = 2; jcrec = 0; cfseek_(&fd, &medium, &nwrec, &jcrec, &stat); printf("1 stat=%i\n", stat); bzero((void *)mbuf, sizeof(mbuf)); strcpy(mbuf, "1wertyui"); strcpy(&mbuf[4088], "1xcvbnm"); errno = 0; res = write(fd, mbuf, 4096); printf("1 write(): res=%i, errno=%i\n", res, errno); nwrec = 2; jcrec = 1024; cfseek_(&fd, &medium, &nwrec, &jcrec, &stat); printf("2 stat=%i\n", stat); bzero((void *)mbuf, sizeof(mbuf)); strcpy(mbuf, "2wertyui"); strcpy(&mbuf[4088], "2xcvbnm"); errno = 0; res = write(fd, mbuf, 4096); printf("2 write(): res=%i, errno=%i\n", res, errno); nwrec = 1; jcrec = 1024; cfseek_(&fd, &medium, &nwrec, &jcrec, &stat); printf("3 stat=%i\n", stat); bzero((void *)mbuf, sizeof(mbuf)); strcpy(mbuf, "3wertyui"); strcpy(&mbuf[4088], "3xcvbnm"); errno = 0; res = write(fd, mbuf, 4096); printf("3 write(): res=%i, errno=%i\n", res, errno); close(fd); exit(0); } -----cut here----- -----cut here-cfseek.c---- #define NBYTPW 4 #include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <errno.h> void cfseek_(lundes, medium, nwrec, jcrec, stat) int *lundes, *medium, *nwrec, *jcrec, *stat; { int fildes; off_t nbdo; off_t isw; errno = 0; fildes = *lundes; nbdo = *jcrec * *nwrec * NBYTPW; fprintf(stderr, "fildes=%i, nbdo=%i\n", fildes, nbdo); isw = lseek (fildes, nbdo, SEEK_SET); fprintf(stderr, "isw=%i, errno=%i\n", isw, errno); if (isw < 0) goto trouble; *stat = 0; return; trouble: *stat = -1; perror (" error in CFSEEK"); return; } -----cut here----- Isupov A. On 1/19/08, A.Yu.Isupov <isupov@moonhe.jinr.ru> wrote: > *From:* "Scot Hetzel" <swhetzel@gmail.com> > *Date:* Fri, 18 Jan 2008 10:07:26 -0600 > > >Currently, building i386 programs under FreeBSD/amd64 is not > >supported. The reason for this is you need the i386 includes to build > >your program, but they are not installed during a installworld (see > >stage 5.1 in src/Makefile.inc1). > > I assume, that all needed includes are the same under amd64 and i386... > Problems are not connected with sizeof(int) or prototyping. The includes are not the same between amd64 and i386. sys/types.h pulls in machine/endian.h and machine/_types.h. These two includes are different. That is why you would need to build the includes for i386 under amd64. An example of building the includes is in stage 5.1 of buildworld. > Unfortunately, I can't port my program (that is cernlib) to 64-bit > (I try !), because one intensively uses int (and integer*4 :) to store > pointers, so I need to compile it in 32-bit environment - if possible, > on FreeBSD/amd64, if not - I should choose to continue using the > FreeBSD/i386 on 64-bit CPU :( You would need to create a 32-bit build environment similar to how buildworld stage 5.1 build the 32-bit libraries, or install FreeBSD/i386 into its own partition/directory and build it from there. 1. Create directory to install FreeBSD/i386 into: mkdir /usr/home/build32 2. Mount FreeBSD/i386 disc1 iso mount -t cd9660 /dev/cd0 /mnt or mount -t cd9660 /dev/`mdconfig -f 6.3-RELEASE-i386-disc1.iso` /mnt 3. Install FreeBSD/i386 into /usr/home/build32 cd /mnt/6.3-RELEASE/base DESTDIR=/usr/home/build32 install.sh 4. link ld-elf.so.1 to ld-elf32.so.1 cd /usr/home/build32/libexec ln -s ld-elf.so.1 ld-elf32.so.1 cd ../usr/libexec ln -s ld-elf.so.1 ld-elf32.so.1 Now place your source some where under /usr/home/build32, then chroot /usr/home/build32. Change to the location of your sources and build your binary. Scot >*From:* "Scot Hetzel" <swhetzel@gmail.com> >*Date:* Sat, 19 Jan 2008 14:18:43 -0600 >The includes are not the same between amd64 and i386. >sys/types.h pulls in machine/endian.h and machine/_types.h. These two >includes are different. >That is why you would need to build the includes for i386 under amd64. >An example of building the includes is in stage 5.1 of buildworld. Because I already got ready 32-bit libs from 6.2-RELEASE i386 (/usr/lib32 from amd64 contains code, produces SIGILL under i386, as I say above), so I do the same for i386 includes. And with addition -nostdinc -I/usr/include32 all reported strangeness are eliminated ! Thank you very very mach !! (I don't think about so dramatic effect from incorrect includes...) >You would need to create a 32-bit build environment similar to how >buildworld stage 5.1 build the 32-bit libraries, or install >FreeBSD/i386 into its own partition/directory and build it from there. This method SHOULD work, I understand. (The compiler suite will be used also 32-bit from i386, am I right ?) However such environment not so suitable for everyday working, namely building binaries with 32-bit cernlibs and running ones, and again, again, ... So receipt for me - to use under amd64 a native gcc with -m32, while /usr/lib32 and /usr/include32 are from corresponding i386 release, and to link -static binary for eliminating problems with correct dynamic linker and libs set (anyway, dynamic Xorg libs, as I seen, contains dependency names as absolute paths a la /usr/X11R6/lib/<lib>, so can't be used from /usr/X11R6/lib32). Because cernlibs itself are static only, the -static linking not so strong restriction... Thank you again ! Isupov A. State Changed From-To: open->closed User was compiling -m32 binaries with 64-bit headers. |
Code mentioned in How-To-Repeat: obtains SIGSEGV: 6.0-RELEASE i386> ./ddd f=0 cur=-1 max=2.14748e+09 Segmentation fault (core dumped) due to stack frames damage, as we can see: 6.0-RELEASE i386> gdb ./ddd ddd.core GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-marcel-freebsd"... Core was generated by `ddd'. Program terminated with signal 11, Segmentation fault. #0 0x7fffffff in ?? () (gdb) bt #0 0x7fffffff in ?? () #1 0xbfbfdeb4 in ?? () #2 0x00000000 in ?? () #3 0x00000000 in ?? () #4 0x00000001 in ?? () #5 0xbfbfdf10 in ?? () #6 0x00000000 in ?? () #7 0xbfbfdec8 in ?? () #8 0x080515b5 in atexit () Cannot access memory at address 0x3 (gdb) q Step-by-steping under debugger shows, that SIGSEGV generated during return from bbb() to main(), while really stack frames damaged after return from getrlimit(2): 6.0-RELEASE i386> gdb ./ddd GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-marcel-freebsd"... (gdb) break main Breakpoint 1 at 0x804825c: file ddd.c, line 41. (gdb) run Starting program: /home/users/alis/misc/F/F+C/ddd Breakpoint 1, main () at ddd.c:41 41 float f=0.0; (gdb) step 43 printf("f=%g\n", f); (gdb) f=0 44 bbb(&f); (gdb) bbb (f=0xbfbfde84) at ddd.c:18 18 if (!flag) (gdb) 21 if (!getrlimit(RLIMIT_CPU, &rlim)) { (gdb) info frame 0 Stack frame at 0xbfbfde60: eip = 0x80481d1 in bbb (ddd.c:21); saved eip 0x8048282 called by frame at 0xbfbfde90 source language c. Arglist at 0xbfbfde58, args: f=0xbfbfde84 Locals at 0xbfbfde58, Previous frame's sp is 0xbfbfde60 Saved registers: ebp at 0xbfbfde58, eip at 0xbfbfde5c (gdb) info frame 1 Stack frame at 0xbfbfde90: eip = 0x8048282 in main (ddd.c:44); saved eip 0x8048106 caller of frame at 0xbfbfde60 source language c. Arglist at 0xbfbfde88, args: Locals at 0xbfbfde88, Previous frame's sp is 0xbfbfde90 Saved registers: ebp at 0xbfbfde88, eip at 0xbfbfde8c (gdb) step 22 printf("cur=%g max=%g\n", (gdb) info frame 0 Stack frame at 0xbfbfde60: eip = 0x80481e8 in bbb (ddd.c:22); saved eip 0x7fffffff called by frame at 0xbfbfde64 source language c. Arglist at 0xbfbfde58, args: f=0xbfbfde84 Locals at 0xbfbfde58, Previous frame's sp is 0xbfbfde60 Saved registers: ebp at 0xbfbfde58, eip at 0xbfbfde5c (gdb) info frame 1 Stack frame at 0xbfbfde64: eip = 0x7fffffff; saved eip 0xbfbfde84 called by frame at 0xbfbfde68, caller of frame at 0xbfbfde60 Arglist at 0xbfbfde5c, args: Locals at 0xbfbfde5c, Previous frame's sp is 0xbfbfde64 Saved registers: ebp at 0xbfbfde58, eip at 0xbfbfde60 (gdb) info frame 2 Stack frame at 0xbfbfde68: eip = 0xbfbfde84; saved eip 0x0 called by frame at 0xbfbfde6c, caller of frame at 0xbfbfde64 Arglist at 0xbfbfde60, args: Locals at 0xbfbfde60, Previous frame's sp is 0xbfbfde68 Saved registers: ebp at 0xbfbfde58, eip at 0xbfbfde64 (gdb) info frame 3 Stack frame at 0xbfbfde6c: eip = 0x0; saved eip 0x0 called by frame at 0xbfbfde70, caller of frame at 0xbfbfde68 Arglist at 0xbfbfde64, args: Locals at 0xbfbfde64, Previous frame's sp is 0xbfbfde6c Saved registers: ebp at 0xbfbfde58, eip at 0xbfbfde68 (gdb) step cur=-1 max=2.14748e+09 25 if (rlim.rlim_cur != RLIM_INFINITY) (gdb) 28 *f = (float)rlim.rlim_max; (gdb) 36 flag = 0; (gdb) 37 } (gdb) Program received signal SIGSEGV, Segmentation fault. 0x7fffffff in ?? () (gdb) c Continuing. Program terminated with signal SIGSEGV, Segmentation fault. The program no longer exists. (gdb) q Some another syscalls, for example getpid(2) or getpriority(2), does not produce such effect. Picture under i386 and amd64 6.2-RELEASE very similar: 6.2-RELEASE amd64> ./ddd f=0 cur=-1 max=2.14748e+09 Segmentation fault (core dumped) 6.2-RELEASE amd64> gdb ./ddd ddd.core GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "amd64-marcel-freebsd"... Core was generated by `ddd'. Program terminated with signal 11, Segmentation fault. #0 0x7fffffff in ?? () (gdb) bt #0 0x7fffffff in ?? () #1 0xffffced4 in ?? () #2 0x00000000 in ?? () #3 0x00000000 in ?? () #4 0x00000001 in ?? () #5 0xffffcf28 in ?? () #6 0x00000000 in ?? () #7 0xffffcee8 in ?? () #8 0x080515b5 in atexit () Cannot access memory at address 0x3 (gdb) q 6.2-RELEASE amd64> gdb ./ddd GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "amd64-marcel-freebsd"... (gdb) break main Breakpoint 1 at 0x804825c: file ddd.c, line 41. (gdb) run Starting program: /home/users/alis/misc/F/F+C/ddd Breakpoint 1, main () at ddd.c:41 41 float f=0.0; (gdb) step 43 printf("f=%g\n", f); (gdb) f=0 44 bbb(&f); (gdb) bbb (f=0xffffcea4) at ddd.c:18 18 if (!flag) (gdb) 21 if (!getrlimit(RLIMIT_CPU, &rlim)) { (gdb) info frame 0 Stack frame at 0xffffce80: eip = 0x80481d1 in bbb (ddd.c:21); saved eip 0x8048282 called by frame at 0xffffceb0 source language c. Arglist at 0xffffce78, args: f=0xffffcea4 Locals at 0xffffce78, Previous frame's sp is 0xffffce80 Saved registers: ebp at 0xffffce78, eip at 0xffffce7c (gdb) info frame 1 Stack frame at 0xffffceb0: eip = 0x8048282 in main (ddd.c:44); saved eip 0x8048106 caller of frame at 0xffffce80 source language c. Arglist at 0xffffcea8, args: Locals at 0xffffcea8, Previous frame's sp is 0xffffceb0 Saved registers: ebp at 0xffffcea8, eip at 0xffffceac (gdb) step 22 printf("cur=%g max=%g\n", (gdb) info frame 0 Stack frame at 0xffffce80: eip = 0x80481e8 in bbb (ddd.c:22); saved eip 0x7fffffff called by frame at 0xffffce84 source language c. Arglist at 0xffffce78, args: f=0xffffcea4 Locals at 0xffffce78, Previous frame's sp is 0xffffce80 Saved registers: ebp at 0xffffce78, eip at 0xffffce7c (gdb) info frame 1 Stack frame at 0xffffce84: eip = 0x7fffffff; saved eip 0xffffcea4 called by frame at 0xffffce88, caller of frame at 0xffffce80 Arglist at 0xffffce7c, args: Locals at 0xffffce7c, Previous frame's sp is 0xffffce84 Saved registers: ebp at 0xffffce78, eip at 0xffffce80 (gdb) info frame 2 Stack frame at 0xffffce88: eip = 0xffffcea4; saved eip 0x0 called by frame at 0xffffce8c, caller of frame at 0xffffce84 Arglist at 0xffffce80, args: Locals at 0xffffce80, Previous frame's sp is 0xffffce88 Saved registers: ebp at 0xffffce78, eip at 0xffffce84 (gdb) info frame 3 Stack frame at 0xffffce8c: eip = 0x0; saved eip 0x0 called by frame at 0xffffce90, caller of frame at 0xffffce88 Arglist at 0xffffce84, args: Locals at 0xffffce84, Previous frame's sp is 0xffffce8c Saved registers: ebp at 0xffffce78, eip at 0xffffce88 (gdb) step cur=-1 max=2.14748e+09 25 if (rlim.rlim_cur != RLIM_INFINITY) (gdb) 28 *f = (float)rlim.rlim_max; (gdb) 36 flag = 0; (gdb) 37 } (gdb) Program received signal SIGSEGV, Segmentation fault. 0x7fffffff in ?? () (gdb) c Continuing. Program terminated with signal SIGSEGV, Segmentation fault. The program no longer exists. (gdb) q I think, this problem similar or connected with one in the amd64/110655 bug report ? Fix: Unknown for both SIGSEGV and SIGILL. SIGSEGV effect too subtle, because as workaround we can use, for example, #ifdef CURE cludge (see ddd.c text), which produces workable binary with -DCURE and 2) or 3) library sets. SIGILL with 1) library set effect possibly requires more accurate building of the /usr/lib32 under amd64. How-To-Repeat: Following very simple code ddd.c ---------cut here--------- #include <sys/types.h> #include <sys/time.h> #include <sys/resource.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> static int flag = 1; void bbb(float *); void bbb(float *f) { struct rlimit rlim; if (!flag) return; if (!getrlimit(RLIMIT_CPU, &rlim)) { printf("cur=%g max=%g\n", (float)rlim.rlim_cur, (float)rlim.rlim_max); if (rlim.rlim_cur != RLIM_INFINITY) *f = (float)rlim.rlim_cur; else *f = (float)rlim.rlim_max; } else { #ifdef CURE printf("errno=%i (%s)\n", errno, strerror(errno)); #else printf("errno=%i\n", errno); #endif } flag = 0; } int main() { float f=0.0; printf("f=%g\n", f); bbb(&f); printf("f=%g\n", f); f = 0.0; printf("f=%g\n", f); bbb(&f); printf("f=%g\n", f); exit(0); } ---------cut here--------- compiled by following command line cc -g -W -Wall -m32 -static -B/usr/lib32 -o ddd ddd.c with 2) and 3) library sets ( mentioned in Environment: ) produces SIGSEGV during execution under each of 1) 6.2-RELEASE amd64 2) 6.2-RELEASE i386 3) 6.0-RELEASE i386 Another trouble with 1) library set that the same code produces SIGILL under both i386 systems while still produce SIGSEGV under amd64. However we can see damaged stack frames in the ./ddd and normal in the ./ddd.CURE (compiled w/ -DCURE, see Fix: ) 6.0-RELEASE i386> ./ddd.CURE f=0 Illegal instruction (core dumped) 6.0-RELEASE i386> gdb ./ddd.CURE ddd.CURE.core GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-marcel-freebsd"... Core was generated by `ddd.CURE'. Program terminated with signal 4, Illegal instruction. #0 0x0804e258 in __dtoa () (gdb) bt #0 0x0804e258 in __dtoa () #1 0x0804c710 in __vfprintf () #2 0x0804dc3e in vfprintf () #3 0x08049b81 in printf () #4 0x08048216 in bbb (f=0xbfbfded4) at ddd.c:22 #5 0x080482b2 in main () at ddd.c:44 (gdb) q 6.0-RELEASE i386> ./ddd f=0 Illegal instruction (core dumped) 6.0-RELEASE i386> gdb ./ddd ddd.core GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-marcel-freebsd"... Core was generated by `ddd'. Program terminated with signal 4, Illegal instruction. #0 0x0804e038 in __dtoa () (gdb) bt #0 0x0804e038 in __dtoa () #1 0x0804c4f0 in __vfprintf () #2 0x0804da1e in vfprintf () #3 0x08049a31 in printf () #4 0x08048212 in bbb (f=0xbfbfded4) at ddd.c:22 #5 0x7fffffff in ?? () #6 0xbfbfded4 in ?? () #7 0x00000000 in ?? () #8 0x00000000 in ?? () #9 0x080520c9 in atexit () Cannot access memory at address 0x3 (gdb) q