Skip to content

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

Open
@leventev

Description

@leventev

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions