Open vrza opened 2 years ago
You know you're doing something interesting when you crash the linker 😄
I notice you said 2.37 and not 2.38 - is it possible this is already fixed?
Now I tried building 2.38 locally (we need to modify binutils.sh
to build as
as well!). Linker doesn't crash anymore, but I see the same problem as on NetBSD:
$ make
./check-binutils-coff.sh
cc forceplt.o -m32 -ggdb3 -O0 -fno-stack-protector -m32 -ggdb3 -O0 -fno-stack-protector -lc -B. -Wl,-b,coff-i386 -no-pie 123.o dl_init.o main.o wrappers.o patch.o filemap.o graphics.o draw.o ttydraw/ttydraw.a atfuncs/atfuncs.a forceplt.o -Wl,--whole-archive,ttydraw/ttydraw.a,atfuncs/atfuncs.a,--no-whole-archive -o bin/123 -lncurses -lm
cc: warning: argument unused during compilation: '-no-pie' [-Wunused-command-line-argument]
./ld: 123.o:fseek.c:(.text+0xd9d8c): multiple definition of `ftell'
./ld: 123.o:getopt.c:(.text+0xda394): multiple definition of `fputs'
./ld: 123.o:mon.c:(.text+0xdb81c): multiple definition of `nlist'
./ld: 123.o: warning: warning: tempnam() possibly used unsafely; consider using mkstemp()
./ld: 123.o:time_comm.c:(.text+0xdf104): warning: warning: tmpnam() possibly used unsafely; consider using mkstemp()
./ld: 123.o:fopen.c:(.text+0xdf354): multiple definition of `mktemp'
./ld: 123.o:dtop.c:(.text+0xe183c): multiple definition of `fwrite'
./ld: 123.o:dcell.c:(.text+0xb808): multiple definition of `isnumber'
./ld: 123.o:drand48.c:(.text+0xd8e44): multiple definition of `exect'
./ld: 123.o:qsort.c:(.text+0xdc710): multiple definition of `getdents'
./ld: 123.o:ltostr.c:(.text+0xe2029): multiple definition of `brk'
./ld: forceplt.o: in function `__require_ref':
(.text+0x6f): undefined reference to `cuserid'
./ld: (.text+0x74): undefined reference to `daylight'
./ld: (.text+0x8d): undefined reference to `ecvt'
./ld: (.text+0x9c): undefined reference to `endutent'
./ld: (.text+0xce): undefined reference to `fcvt'
./ld: (.text+0xf1): undefined reference to `gcvt'
./ld: (.text+0x155): undefined reference to `getutent'
./ld: (.text+0x15a): undefined reference to `getutid'
./ld: (.text+0x15f): undefined reference to `getutline'
./ld: (.text+0x16e): undefined reference to `gsignal'
./ld: (.text+0x1c8): undefined reference to `mallinfo'
./ld: (.text+0x1d2): undefined reference to `mallopt'
./ld: (.text+0x1d7): undefined reference to `_mcount'
./ld: (.text+0x263): undefined reference to `putpwent'
./ld: (.text+0x26d): undefined reference to `pututline'
./ld: (.text+0x2db): undefined reference to `setutent'
./ld: (.text+0x32b): undefined reference to `ssignal'
./ld: (.text+0x3d0): undefined reference to `ttyslot'
./ld: (.text+0x3ee): undefined reference to `umount'
./ld: (.text+0x407): undefined reference to `utmpname'
./ld: (.text+0x461): undefined reference to `fstat64'
./ld: (.text+0x466): undefined reference to `stat64'
./ld: 123.o:lefwin.c:(.text+0x9ea88): undefined reference to `cuserid'
./ld: 123.o:baseten.c:(.text+0xc7438): undefined reference to `ecvt'
./ld: 123.o:ftw.c:(.text+0xd95ba): undefined reference to `ecvt'
./ld: 123.o:gethz.c:(.text+0xd9f11): undefined reference to `ttyslot'
./ld: 123.o:doprnt.c:(.text+0xe01d3): undefined reference to `ecvt'
./ld: 123.o:doprnt.c:(.text+0xe03d7): undefined reference to `fcvt'
./ld: 123.o:doprnt.c:(.text+0xe06bf): undefined reference to `ecvt'
./ld: forceplt.o: in function `__require_ref':
(.text+0x6f): undefined reference to `cuserid'
./ld: (.text+0x74): undefined reference to `daylight'
./ld: (.text+0x8d): undefined reference to `ecvt'
./ld: (.text+0x9c): undefined reference to `endutent'
./ld: (.text+0xce): undefined reference to `fcvt'
./ld: (.text+0xf1): undefined reference to `gcvt'
./ld: (.text+0x155): undefined reference to `getutent'
./ld: (.text+0x15a): undefined reference to `getutid'
./ld: (.text+0x15f): undefined reference to `getutline'
./ld: (.text+0x16e): undefined reference to `gsignal'
./ld: (.text+0x1c8): undefined reference to `mallinfo'
./ld: (.text+0x1d2): undefined reference to `mallopt'
./ld: (.text+0x1d7): undefined reference to `_mcount'
./ld: (.text+0x263): undefined reference to `putpwent'
./ld: (.text+0x26d): undefined reference to `pututline'
./ld: (.text+0x2db): undefined reference to `setutent'
./ld: (.text+0x32b): undefined reference to `ssignal'
./ld: (.text+0x3d0): undefined reference to `ttyslot'
./ld: (.text+0x3ee): undefined reference to `umount'
./ld: (.text+0x407): undefined reference to `utmpname'
./ld: (.text+0x461): undefined reference to `fstat64'
./ld: (.text+0x466): undefined reference to `stat64'
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** Error code 1
Stop.
Trying to figure out what's happening here -- are these undefined references symbols present on System V and Linux but not on BSD?
Okay, got it to link by modifyingundefine.lst
(removed "undefined reference" symbols and added "multiple definitions" symbols -- I'm still figuring out how this custom linking process works).
Next step is fixing file mapping -- /proc/self/exe
is Linux specific and thus not portable. [edit] It can be done on BSD by calling readlink
on /proc/<pid>/file
Program segfaults on startup:
Program received signal SIGSEGV, Segmentation fault.
Address not mapped to object.
0x0008e6f0 in ?? ()
(gdb) bt
#0 0x0008e6f0 in ?? ()
#1 0x0811aa27 in tc_setup_line_funcs ()
#2 0x08116d7d in tty_find_changes ()
#3 0x08116ad4 in lotus_udiv ()
#4 0x0811470c in gen_disp_txt_unlock ()
#5 0x0807eab2 in real_refresh_display ()
#6 0x0807ea52 in real_redisplay ()
#7 0x08112a5a in sched ()
#8 0x08111e4f in __unix_main ()
#9 0x0812e968 in main (argc=1, argv=0xffbfec20, envp=0xffbfec28) at main.c:151
System call trace from truss(8)
:
sigaction(SIGUSR1,{ 0x8113e80 SA_RESTART ss_t },{ SIG_DFL 0x0 ss_t }) = 0 (0x0)
sigaction(SIGHUP,{ 0x811976c SA_RESTART ss_t },{ 0x8119780 SA_RESTART ss_t }) = 0 (0x0)
sigaction(SIGQUIT,{ 0x81197d8 SA_RESTART ss_t },{ 0x8119780 SA_RESTART ss_t }) = 0 (0x0)
sigaction(SIGTERM,{ 0x811976c SA_RESTART ss_t },{ 0x8119780 SA_RESTART ss_t }) = 0 (0x0)
sigaction(SIGINT,{ 0x8119854 SA_RESTART ss_t },{ 0x8119780 SA_RESTART ss_t }) = 0 (0x0)
sigaction(SIGUSR2,{ 0x8119898 SA_RESTART ss_t },{ SIG_DFL 0x0 ss_t }) = 0 (0x0)
open("/etc/localtime",O_RDONLY,05011127744) = 4 (0x4)
fstat(4,{ mode=-r--r--r-- ,inode=19131,size=1931,blksize=4096 }) = 0 (0x0)
mmap(0x0,36864,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON|MAP_ALIGNED(12),-1,0x0) = 678113280 (0x286b3000)
read(4,"TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0"...,29000) = 1931 (0x78b)
close(4) = 0 (0x0)
write(1,"\^[[?25l\^[[?25l\^[[?12l\^[[?25h",24) = 24 (0x18)
SIGNAL 11 (SIGSEGV) code=SEGV_MAPERR trapno=12 addr=0x8e6f0
write(1,"\^[[H\^[[2J\^[[?12l\^[[?25h",19) = 19 (0x13)
ioctl(1,TIOCGETA,0xffbfe4b0) = 0 (0x0)
ioctl(1,TIOCGETA,0xffbfe4ac) = 0 (0x0)
ioctl(1,TIOCSETA,0xffbfe4ac) = 0 (0x0)
sigaction(SIGSEGV,{ SIG_DFL SA_RESTART ss_t },{ 0x81197d8 SA_RESTART ss_t }) = 0 (0x0)
getpid() = 57116 (0xdf1c)
kill(57116,SIGSEGV) = 0 (0x0)
sigreturn(0xffbfe540) EJUSTRETURN
SIGNAL 11 (SIGSEGV) code=SI_USER pid=57116 uid=1001
process killed, signal = 11 (core dumped)
Looks like a wrapper around fwrite(3)
is needed. I tried a trivial shim:
size_t __unix_fwrite(const void * __restrict ptr, size_t size, size_t nmemb, FILE * __restrict stream) {
return fwrite(ptr, size, nmemb, stream);
}
Program runs, accepts input, the cursor moves around, but the output is all blank (no visible characters or highlighting).
My guess here is that System V struct FILE
binary layout is different from the one on BSD, and that we need to convert it, but I'm not yet sure how to go about figuring out the System V FILE definition. @taviso how did you figure out the layouts of SysV stat
, dirent
etc?
I think maybe fwrite()
should be localized, that way it can do whatever it wants to the FILE
structure, but eventually when it needs to use write()
that can be intercepted... I think maybe it's a bug that it's not localized already, can you check if that helps?
(I did the same thing as you to figure out the structure, looked at the disassembly and googled for old header files!)
@taviso Spot on, intercepting write
instead of fwrite
worked like a charm, thank you!
FreeBSD port now seems to work 🎉
Since the undefine/redefine lists might differ between platforms, we'll need some sort of platform-specific configuration prior to build. I can try to cobble up some shell script for this. Please let me know your thoughts.
@vrza I am curious what ver. of FreeBSD are you as not even the binutils can be compiled...
@Unixware You probably misunderstood the conversation above, the GNU binutils suite itself could be compiled on FreeBSD. Since the conversation above is from June 2022, it was probably on FreeBSD 13.1, it had devel/binutils-2.37 in ports, and I compiled a newer version (binutils-2.38) from the upstream tarball.
What's described in the conversation above are various issues in getting not binutils, but this project (123elf) to compile and link on FreeBSD (which is basically the point of this GitHub ticket) and these issues I solved back then in PR #86.
The feature branch is still up, try it on FreeBSD. By this time I'd expect it to link just fine using the ports version of binutils.
thanks! Sorry I thought your PR was merged already! I think you may need to fix the make file to reflect the correct names of i386 binutils , as they have the prefix "i386-unknown-freebsd14.0-" edit: I think you are using a i386 FreeBSD system, as the makefile stops because the cc does not support coff-i386
@Unixware The original 123 object code that this project is linking is i386, so you must have coff-i386 in order to build it.
thanks Vladimir, using the latest binutils works! 123 loads ok , Just segfault while trying to open the 'help' (F1 key)
Next step is fixing file mapping --
/proc/self/exe
is Linux specific and thus not portable. [edit] It can be done on BSD by callingreadlink
on/proc/<pid>/file
FreeBSD has a procfs implementation but it is not preferred, and on many systems is not normally mounted. The canonical way to query this on FreeBSD is via the sysctl(3) interface. There's a good blog on implementing this functionality for FreeBSD in GHC at https://frasertweedale.github.io/blog-fp/posts/2021-01-01-fixing-getExecutablePath-FreeBSD.html (and the sysctl node itself is documented in the man page, https://man.freebsd.org/cgi/man.cgi?sysctl(3) )
ld
(GNU binutils 2.37) segfaults when attempting to link123
on FreeBSD: