ndless-nspire / Ndless

The TI-Nspire calculator extension for native applications
http://ndless.me
856 stars 104 forks source link

Toolchain update #420

Open Vogtinator opened 6 months ago

Vogtinator commented 6 months ago

Might need nSDL rebuilt, could also drop --enable-newlib-reent-binary-compat then.

For some reason, the newlib-c++ sample pulls in arc4random which requires _getentropy and is massive. Needs investigation why.

Legimet commented 6 months ago

The _getentropy issue is because in the newer version of Newlib, the headers declare arc4random/getentropy and libstdc++ detects it during configuration. This was supposed to fix it (by doing a compile+link test, not just compile) but doesn't work here because linking isn't possible. One solution is to include a _getentropy stub that fails and sets errno=ENOSYS, but the arc4random function will still be included in that case. The other solution is to remove arc4random/getentropy from the Newlib headers before building GCC.

The more concerning issue is that after fixing the above issue, the newlib-c++ sample crashes because std::cout is not initialized, due to this change (more description here). The __ioinit object is not brought in at link time. This seems like possibly a bug in libstdc++.

The new version of ld gives a warning about a "LOAD segment with RWX permissions," this can be suppressed with --no-warn-rwx-segments. It's also possible to have this warning suppressed by default by setting --enable-warn-rwx-segments=no at configure time.

nSDL seems to work fine for me without --enable-newlib-reent-binary-compat.

Vogtinator commented 6 months ago

The _getentropy issue is because in the newer version of Newlib, the headers declare arc4random/getentropy and libstdc++ detects it during configuration. This was supposed to fix it (by doing a compile+link test, not just compile) but doesn't work here because linking isn't possible. One solution is to include a _getentropy stub that fails and sets errno=ENOSYS, but the arc4random function will still be included in that case. The other solution is to remove arc4random/getentropy from the Newlib headers before building GCC.

What actually pulls in the randomness functions? The program doesn't use std::random_device directly, but somehow ends up needing it.

The more concerning issue is that after fixing the above issue, the newlib-c++ sample crashes because std::cout is not initialized, due to this change (more description here). The __ioinit object is not brought in at link time. This seems like possibly a bug in libstdc++.

The init_array content was in a separate section not handled by the linker script and startup code. Should be fixed.

The new version of ld gives a warning about a "LOAD segment with RWX permissions," this can be suppressed with --no-warn-rwx-segments. It's also possible to have this warning suppressed by default by setting --enable-warn-rwx-segments=no at configure time.

Hm, maybe we should try to make .text separate from data:

diff --git a/ndless-sdk/system/ldscript b/ndless-sdk/system/ldscript
index 5ff03eb..8c7a3bf 100644
--- a/ndless-sdk/system/ldscript
+++ b/ndless-sdk/system/ldscript
@@ -1,5 +1,10 @@
 ENTRY(_start)

+PHDRS {
+       text PT_LOAD;
+       data PT_LOAD;
+}
+
 SECTIONS {
        .text 0x0 : {
                _start = .;
@@ -10,13 +15,13 @@ SECTIONS {
                KEEP(*(.fini_array))
                KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)))
                *(.text.*)
-       }
+       } :text

        .got : {
                *(.got.plt*)
                *(.got)
                LONG(0xFFFFFFFF)
-       }
+       } :data

        .data : {
                *(.rodata*)

genzehn doesn't care about segments so it's pretty much a noop though.

Legimet commented 6 months ago

What actually pulls in the randomness functions? The program doesn't use std::random_device directly, but somehow ends up needing it.

This, apparently.

The init_array content was in a separate section not handled by the linker script and startup code. Should be fixed.

Yes, that fixes it.

Vogtinator commented 6 months ago

What actually pulls in the randomness functions? The program doesn't use std::random_device directly, but somehow ends up needing it.

This, apparently.

That looks like the other way around: It's pulled in if old (pre-C++11) std::string is passed to std::random_device.

Vogtinator commented 6 months ago

What actually pulls in the randomness functions? The program doesn't use std::random_device directly, but somehow ends up needing it.

This, apparently.

That looks like the other way around: It's pulled in if old (pre-C++11) std::string is passed to std::random_device.

Nope, you're correct - I missed that #include "string-inst.cc" isn't a header but a whole massive source file. Apparently it's pulled in by some objects which also provide non-cow std::string. If that's not the case for the non-cow c++11 and later std::string, I'd like to just disable the old cow string ABI, but apparently there's only an option to disable the new ABI :-/

Maybe building libstdc++ with -ffunction-sections helps, trying that now. The documentation lists it as one of the Fun flags to try :grin: (https://gcc.gnu.org/onlinedocs/gcc-14.1.0/libstdc++/manual/manual/configure.html)

Vogtinator commented 6 months ago

What actually pulls in the randomness functions? The program doesn't use std::random_device directly, but somehow ends up needing it.

This, apparently.

That looks like the other way around: It's pulled in if old (pre-C++11) std::string is passed to std::random_device.

Nope, you're correct - I missed that #include "string-inst.cc" isn't a header but a whole massive source file. Apparently it's pulled in by some objects which also provide non-cow std::string. If that's not the case for the non-cow c++11 and later std::string, I'd like to just disable the old cow string ABI, but apparently there's only an option to disable the new ABI :-/

Maybe building libstdc++ with -ffunction-sections helps, trying that now. The documentation lists it as one of the Fun flags to try 😁 (https://gcc.gnu.org/onlinedocs/gcc-14.1.0/libstdc++/manual/manual/configure.html)

No, doesn't. Probably because of the static constructor which ends up in the .elf before sections get GC'd.

Vogtinator commented 5 months ago

I played around with the newlib-c++ bloat a bit and I don't think there's much we can effectively do. Even avoiding the random stuff by force only gets rid of ~20K which isn't really worth it. <iostream> is just incredibly heavy.

Legimet commented 5 months ago

I think SDL_image has to be rebuilt.