[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Hidden visibility for obstack symbols
From: |
Bruno Haible |
Subject: |
Re: Hidden visibility for obstack symbols |
Date: |
Fri, 02 Dec 2022 17:38:12 +0100 |
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