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]

Reply via email to