v-zhangxiaomeng5 commented on PR #20723:
URL: https://github.com/apache/nuttx/pull/20723#issuecomment-6267514214
Hi Marco,
I would share some comments I met for the abandoned solution locally.
## 1. `CONFIG_DEBUG_LINK_WHOLE_ARCHIVE` fails to link
Notice that, now no board on upstream enables the option --whole-archive by
default, but it is used downstream often.
./tools/configure.sh lm3s6965-ek:nsh
kconfig-tweak --enable CONFIG_ARM_TOOLCHAIN_GNU_EABI
kconfig-tweak --disable CONFIG_ARM_TOOLCHAIN_BUILDROOT_OABI
kconfig-tweak --enable CONFIG_DEBUG_OPT_UNUSED_SECTIONS
kconfig-tweak --enable CONFIG_DEBUG_LINK_WHOLE_ARCHIVE
make olddefconfig && make
emutls.c: multiple definition of __emutls_get_address';
staging/libc.a(tls_emutls.o): first defined here
emutls.c: multiple definition of __emutls_register_common';
staging/libc.a(tls_emutls.o): first defined here
`--whole-archive` brings in `libgcc.a(emutls.o)` whether anything calls it
or not, which would cause above linking errors.
One way out is to leave the libgcc names alone and let the linker redirect
the calls, by naming the two functions `__wrap___emutls_get_address` and
`__wrap___emutls_register_common` and adding `--wrap=__emutls_get_address
--wrap=__emutls_register_common` to the link.
And one thing worth highlighting about that: `LDFLAGS` set in
`libs/libc/tls/Make.defs` never reaches the link, because that file is included
while libc is built while the link runs from `arch/<arch>/src`. The file still
compiles, so the mistake is quiet: the wrapper is never called and
`--gc-sections` drops it.
`tools/Config.mk` is on the path of the link and works. The CMake build has
no such issue, since `target_link_options(nuttx PRIVATE -Wl,--wrap=...)`
reaches the executable directly.
## 2. `size_t` in `__emutls_object` may be an ABI mismatch
`libgcc/emutls.c` describes the object the compiler emits as
```c
typedef unsigned int word __attribute__((mode(word)));
typedef unsigned int pointer __attribute__((mode(pointer)));
struct __emutls_object
{
word size;
word align;
union { pointer offset; void *ptr; } loc;
void *templ;
};
```
The layout has to match what the compiler emits, so using `size_t` and
`uintptr_t` relies on them being as wide as `word` and `pointer`. That holds on
arm, arm64, risc-v and xtensa, which is why it works today.
But it does not hold everywhere: `gcc/config/avr/avr.h` has `UNITS_PER_WORD
1` with `POINTER_SIZE 16`, so `word` is one byte while `size_t` is two and
every field of the object moves, and the ILP32 variants of aarch64 and risc-v,
as well as x32 on x86-64, make the pointer narrower than the machine word in
the same way.
Since the compiler emits the object and libc only reads it, a mismatch gives
wrong values rather than a diagnostic. The same applies to the `size_t`
parameters of `__emutls_register_common()`, which libgcc declares with `word`.
I have not built an AVR configuration to check whether this file is even
selected there, so this is a note about keeping the ABI explicit rather than a
bug I hit.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]