Florian Weimer wrote: > Someone reported that ls in coreutils exported _obstack* symbols. This > is because ls uses the obstack module from gnulib (I assume). Due to > the way ELF linking works by default, this promotes the symbols to > global visibility, so that there is a single definition in the entire > process. This is always a bit iffy (glibc supports it explicitly for > malloc-related symbols, though), but in case of obstack it's really not > great because the gnulib ABI is different from the glibc ABI: > > $ gdb /usr/bin/ls > […] > (gdb) ptype _obstack_begin > type = int (struct obstack *, size_t, size_t, void *(*)(size_t), > void (*)(void *)) > $ gdb /lib64/libc.so.6 > […] > (gdb) ptype _obstack_begin > type = int (struct obstack *, int, int, void *(*)(long), > void (*)(void *)) > > This is on x86-64, so the types aren't equivalent. > > Would it be possible to give the obstack symbols hidden visibility?
I would suggest to do something about it *only* if it is an actual problem. I claim that it is not an actual problem: $ nm --dynamic /bin/ls | grep -v ' U ' w __cxa_finalize@GLIBC_2.2.5 w __gmon_start__ w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable 00000000000106e0 T _obstack_allocated_p 00000000000220a0 D obstack_alloc_failed_handler 000000000000fc80 T _obstack_begin 000000000000fca0 T _obstack_begin_1 0000000000010720 T _obstack_free 00000000000107b0 T _obstack_memory_used 000000000000fcc0 T _obstack_newchunk Among these symbols: * _obstack_allocated_p is irrelevant, since it is only present for debugging, not even declared in <obstack.h>. The remaining symbols are (with prototypes and parameter names): extern void _obstack_newchunk (struct obstack *, int length); extern int _obstack_begin (struct obstack *, int size, int alignment, void *(*)(long size), void (*)(void *)); extern int _obstack_begin_1 (struct obstack *, int size, int alignment, void *(*)(void *, long size), void (*)(void *, void *), void *); extern int _obstack_memory_used (struct obstack *) __attribute_pure__; extern void _obstack_free (struct obstack *, void *); extern void (*obstack_alloc_failed_handler) (void); For arguments of type 'int' and with names 'length', 'size', 'alignment', the valid values are in the range 0..INT_MAX. Similarly, the return value of _obstack_memory_used must be in the range 0..INT_MAX. For 32-bit platforms, such arguments are passed in the same location, whether it's declared as 'int' or 'size_t'. Likewise for a return value. For 64-bit platforms: * On the Linux platforms with CPU aarch64, powerpc64, s390x, x86_64, 32-bit values are passed in a 64-bit register. Whether sign-extended or zero-extended, does not matter, since the value is in the range 0..INT_MAX. * On the Linux platforms with CPU alpha, ia64, loongarch64, mips64, riscv64, sparc64, 32-bit values are passed as a 64-bit value in the stack argument sequence (part of which can be mapped to registers). Again, whether it's sign-extended or zero-extended, does not matter, since the value is in the range 0..INT_MAX. Finally, there are the ABIs mips-n32 and x86_64-x32. Here, 32-bit values are passed as 32-bit, and 64-bit values as 64-bit. So, for these ABIs there would be a problem. But there are no distros that use these ABIs for the coreutils package. - Porting to x86_64-x32 essentially stopped in 2012; there have already been discussions whether to deprecate this ABI. [1] - For mips-n32, I can see that distros prefer to ship mips-32 binaries. For example: $ file /bin/ls /bin/ls: ELF 32-bit LSB executable, MIPS, MIPS-II version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 2.6.32, BuildID[sha1]=7f52495c14dbba5d1918cb3450fcc47a44f275bd, stripped If it was an n32 binary, this output would show /lib32/ld.so.1, not /lib/ld.so.1. Bruno [1] https://en.wikipedia.org/wiki/X32_ABI