Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functions with weak attribute sometimes don't get built into executables if built as a static library #906

Open
leventev opened this issue Aug 18, 2023 · 2 comments

Comments

@leventev
Copy link

Description

When mlibc is built as a static library functions that are marked as weak with [[gnu::weak]] sometimes aren't included in the final executable. Namely I implemented sys_ttyname and sys_isatty in sysdeps/rook/generic/posix.cpp, both functions are declared in options/posix/include/mlibc/posix-sysdeps.h. Running the final executable causes MLIBC_CHECK_OR_ENOSYS to fail on line 764 in options/posix/generic/unistd-stubs.cpp because the mlibc::sys_ttyname function is not found meaning the weak symbol is undefined. If I move the function definitions to sysdeps/rook/generic/generic.cpp the executable is linked properly and MLIBC_CHECK_OR_ENOSYS does not fail.

Symbols and build file

symbols when functions are defined in posix.cpp:
$ nm root/bin/bash | grep ttyname
00000000004da6aa T ttyname
00000000004da76a T ttyname_r
0000000000000084 b _ZZ7ttynameE3buf
$ nm root/usr/lib/libc.a | grep ttyname
000000000000001b W _ZN5mlibc11sys_ttynameEiPcm
0000000000002d6d T ttyname
0000000000002e2d T ttyname_r
                 w _ZN5mlibc11sys_ttynameEiPcm
0000000000000000 b _ZZ7ttynameE3buf
symbols when functions are defined in generic.cpp:
$ nm root/bin/bash | grep ttyname
00000000004da6aa T ttyname
00000000004da76a T ttyname_r
000000000051f6b6 W _ZN5mlibc11sys_ttynameEiPcm
0000000000000084 b _ZZ7ttynameE3buf
$ nm root/usr/lib/libc.a | grep ttyname
0000000000000276 W _ZN5mlibc11sys_ttynameEiPcm
0000000000002d6d T ttyname
0000000000002e2d T ttyname_r
                 w _ZN5mlibc11sys_ttynameEiPcm
0000000000000000 b _ZZ7ttynameE3buf
meson.build
libc_sources += files(
	'generic/generic.cpp',
	'generic/entry.cpp',
	'generic/posix.cpp'
)

if not no_headers
	install_headers(
		'include/abi-bits/seek-whence.h',
		'include/abi-bits/vm-flags.h',
		'include/abi-bits/errno.h',
		'include/abi-bits/fcntl.h',
		'include/abi-bits/in.h',
		'include/abi-bits/resource.h',
		'include/abi-bits/signal.h',
		'include/abi-bits/stat.h',
		'include/abi-bits/socket.h',
		'include/abi-bits/termios.h',
		'include/abi-bits/time.h',
		'include/abi-bits/blkcnt_t.h',
		'include/abi-bits/blksize_t.h',
		'include/abi-bits/dev_t.h',
		'include/abi-bits/gid_t.h',
		'include/abi-bits/ino_t.h',
		'include/abi-bits/mode_t.h',
		'include/abi-bits/nlink_t.h',
		'include/abi-bits/pid_t.h',
		'include/abi-bits/uid_t.h',
		'include/abi-bits/access.h',
		'include/abi-bits/wait.h',
		'include/abi-bits/limits.h',
		'include/abi-bits/utsname.h',
		'include/abi-bits/ptrace.h',
		'include/abi-bits/poll.h',
		'include/abi-bits/epoll.h',
		'include/abi-bits/packet.h',
		'include/abi-bits/inotify.h',
		'include/abi-bits/clockid_t.h',
		'include/abi-bits/shm.h',
		'include/abi-bits/mqueue.h',
		'include/abi-bits/suseconds_t.h',
		'include/abi-bits/fsfilcnt_t.h',
		'include/abi-bits/fsblkcnt_t.h',
		'include/abi-bits/socklen_t.h',
		'include/abi-bits/statfs.h',
		'include/abi-bits/statvfs.h',
		'include/abi-bits/ioctls.h',
		'include/abi-bits/xattr.h',
		subdir: 'abi-bits'
	)
	install_headers(
		'include/rook/syscall.h',
		'include/rook/syscalls.h',
		subdir: 'rook'
	)
endif

if not headers_only
	crt0 = custom_target('crt0',
		build_by_default: true,
		command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'],
		input: 'crt-x86_64/crt0.S',
		output: 'crt0.o',
		install: true,
		install_dir: get_option('libdir')
	)
endif

if host_machine.cpu_family() != 'x86_64'
	error('Unknown architecture')
endif

Details

  • changing the order of the files in libc_sources didn't work
  • both files include the exact same headers in the exact same order
  • the functions were in the right namespace in both files and their function signatures, mangled symbol names matched which can be confirmed by comparing the outputs of nm which i provided above
  • the function body is irrelevant, whether it was a stub or the function was actually implemented didn't make a difference
  • in both cases the right symbols exist in the static library but at different addresses

Temporary solutions

  • removing the '[[gnu:weak]]' attribute from the 2 function declarations in the header file thus changing it to a strong symbol
  • putting all function definitions in the same source file
@moodyhunter
Copy link
Contributor

same issue here, I ended up removing weak attributes manually for failing sysdeps

@64
Copy link
Member

64 commented Apr 14, 2024

Not really sure what causes this -- can anyone provide a reproducer?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants