cloudius-systems / osv

OSv, a new operating system for the cloud.
osv.io
Other
4.12k stars 605 forks source link

Build fails on Fedora 38, missing strfromf128() and strtof128() #1238

Closed nyh closed 1 year ago

nyh commented 1 year ago

As usual, upgrading my Fedora home machine brings new build problems :-(

First we need to update scripts/setup.py to allow Fedora 38. That's trivial.

Then, the linking at the end of the build (ran make -j1 to get clearer error messages) fails:

  LINK loader.elf
ld.bfd: warning: build/release.x64/bootfs.o: missing .note.GNU-stack section implies executable stack
ld.bfd: NOTE: This behaviour is deprecated and will be removed in a future version of the linker
ld.bfd: warning: build/release.x64/loader.elf has a LOAD segment with RWX permissions
ld.bfd: /usr/lib/gcc/x86_64-redhat-linux/13/libstdc++.a(floating_from_chars.o): in function `_ZNSt12_GLOBAL__N_117from_chars_strtodIDF128_EESt17from_chars_resultPKcS3_RT_St12chars_format':
(.text._ZNSt12_GLOBAL__N_117from_chars_strtodIDF128_EESt17from_chars_resultPKcS3_RT_St12chars_format+0xe6): undefined reference to `strtof128'
ld.bfd: (.text._ZNSt12_GLOBAL__N_117from_chars_strtodIDF128_EESt17from_chars_resultPKcS3_RT_St12chars_format+0x1fc): undefined reference to `strtof128'
ld.bfd: /usr/lib/gcc/x86_64-redhat-linux/13/libstdc++.a(floating_to_chars.o): in function `_ZSt29__floating_to_chars_precisionIDF128_ESt15to_chars_resultPcS1_T_St12chars_formati':
(.text._ZSt29__floating_to_chars_precisionIDF128_ESt15to_chars_resultPcS1_T_St12chars_formati+0x1aa): undefined reference to `strfromf128'
ld.bfd: (.text._ZSt29__floating_to_chars_precisionIDF128_ESt15to_chars_resultPcS1_T_St12chars_formati+0x3fb): undefined reference to `strfromf128'
ld.bfd: /usr/lib/gcc/x86_64-redhat-linux/13/libstdc++.a(floating_to_chars.o): in function `_ZSt28__floating_to_chars_shortestIDF128_ESt15to_chars_resultPcS1_T_St12chars_format':
(.text._ZSt28__floating_to_chars_shortestIDF128_ESt15to_chars_resultPcS1_T_St12chars_format+0x668): undefined reference to `strfromf128'
ld.bfd: (.text._ZSt28__floating_to_chars_shortestIDF128_ESt15to_chars_resultPcS1_T_St12chars_format+0x141f): undefined reference to `strfromf128'
make: *** [Makefile:2129: build/release.x64/loader.elf] Error 1

It seems OSv needs to implement strtof128() and strfromf128() now to satisfy the new C++ library?

nyh commented 1 year ago

strtof128() can probably be an alias of the existing strtold() (which returns "long double", which hopefully means 128 bits). strfrom128() is a bigger problem - it's a new function in glibc, but it can probably be trivially implemented using snprintf() - see what Musl recently for strfromd here: https://www.openwall.com/lists/musl/2023/05/31/28

nyh commented 1 year ago

The following patch seems to make OSv work on Fedora 38. I didn't test whether strfrom128() / strtof128() work correctly - I should... I am guessing my workload doesn't even use it so even a stubbed implementation would have worked.

diff --git a/Makefile b/Makefile
index af0a9585..65223144 100644
--- a/Makefile
+++ b/Makefile
@@ -1721,6 +1721,7 @@ $(out)/libc/stdlib/qsort_r.o: COMMON += -Wno-dangling-pointer
 libc += stdlib/strtol.o
 libc += stdlib/strtod.o
 libc += stdlib/wcstol.o
+libc += stdlib/strfromd.o

 libc += string/__memcpy_chk.o
 libc += string/explicit_bzero.o
diff --git a/libc/aliases.ld b/libc/aliases.ld
index 5f3fc744..e6db87dc 100644
--- a/libc/aliases.ld
+++ b/libc/aliases.ld
@@ -67,6 +67,10 @@ lstat64 = lstat;
 fstatat64 = fstatat;
 __lseek = lseek;

+/* stdlib */
+strtof128 = strtold;
+strfromf128 = strfromld;
+
 __getauxval = getauxval;
 __getpagesize = getpagesize;

diff --git a/libc/stdlib/strfromd.c b/libc/stdlib/strfromd.c
new file mode 100644
index 00000000..169da5e2
--- /dev/null
+++ b/libc/stdlib/strfromd.c
@@ -0,0 +1,31 @@
+/* Based on recent addition to Musl, see
+ * https://www.openwall.com/lists/musl/2023/05/31/28
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+
+static size_t sanitize(const char*format) {
+       size_t slen = format ? strlen(format) : 0;
+       if (format[0] != '%'
+               || (slen > 2 && format[1] != '.')
+               || strchr(&format[1], '%')
+               || (strspn(&format[slen-1], "aAeEfFgG") != 1)) return 0;
+       else return slen;
+}
+
+int strfromd(char *restrict s, size_t n, const char *restrict format, double fp) {
+       return sanitize(format) ? snprintf(s, n, format, fp) : -1;
+}
+
+int strfromf(char *restrict s, size_t n, const char *restrict format, float fp) {
+       return sanitize(format) ? snprintf(s, n, format, fp) : -1;
+}
+
+int strfromld(char *restrict s, size_t n, const char *restrict format, float fp) {
+       return sanitize(format) ? snprintf(s, n, format, fp) : -1;
+}
+
diff --git a/scripts/setup.py b/scripts/setup.py
index d6b47919..323bfa5b 100755
--- a/scripts/setup.py
+++ b/scripts/setup.py
@@ -150,8 +150,16 @@ class Fedora(object):
         ec2_post_install = None
         version = '37'

+    class Fedora_38(object):
+        packages = []
+        ec2_packages = []
+        test_packages = []
+        ec2_post_install = None
+        version = '38'
+
+
     versions = [
-        Fedora_27, Fedora_28, Fedora_29, Fedora_30, Fedora_31, Fedora_32, Fedora_33, Fedora_34, Fedora_35, Fedora_37
+        Fedora_27, Fedora_28, Fedora_29, Fedora_30, Fedora_31, Fedora_32, Fedora_33, Fedora_34, Fedora_35, Fedora_37, Fedora_38
     ]

This patch makes my favorite scripts/build image=rogue; scripts/run.py work. However the default scripts/build image (the Lua shell) doesn't work completely:

OSv v0.57.0-36-g8c792811
eth0: 192.168.122.15
Booted up in 357.78 ms
Cmdline: /cli
Rest API server running on port 8000
/usr/lib/lua/5.3/ssl.so: failed looking up symbol OPENSSL_init_ssl

So I guess there's been a change to openssl that we also need to fix, or perhaps we need to build lua differently, without openssl (?)

nyh commented 1 year ago

I'm preparing a better PR for building OSv on Fedora 38. Unfortunately the above has some missing pieces, and also bugs. Namely, once I wrote a test for strfromf128, I realized it doesn't do the right thing :-(