Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Toolchain update #420

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Conversation

Vogtinator
Copy link
Contributor

  • binutils 2.42
  • GCC 14.1.0
  • newlib 4.4.0
  • GDB 14.2

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.

- binutils 2.42
- GCC 14.1.0
- newlib 4.4.0
- GDB 14.2
@Legimet
Copy link
Contributor

Legimet commented May 25, 2024

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
Copy link
Contributor Author

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
Copy link
Contributor

Legimet commented May 26, 2024

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
Copy link
Contributor Author

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
Copy link
Contributor Author

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)

@Vogtinator
Copy link
Contributor Author

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 Vogtinator marked this pull request as ready for review June 1, 2024 17:41
@Vogtinator
Copy link
Contributor Author

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.

* Add support to the linker script and startup code.
* Add tests for init_priority to the zehn sample
Avoids the creation of RWX segments which newer binutils warns about.
@Legimet
Copy link
Contributor

Legimet commented Jun 13, 2024

I think SDL_image has to be rebuilt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants