zig icon indicating copy to clipboard operation
zig copied to clipboard

glibc: add changes to make riscv64-linux-gnu works

Open RossComputerGuy opened this issue 1 year ago • 21 comments
trafficstars

Fixes #3340, builds with zig build-exe bootstrap.c -lc -target riscv64-linux-gnu -mcpu=generic_rv64. I can't test this until I can get RISC-V hardware but this does fix compiling.

RossComputerGuy avatar Feb 04 '24 05:02 RossComputerGuy

I applied this PR's patch to the prebuilt zig-linux-x86_64-0.12.0-dev.2341+92211135f and was able to compile a hello world with zig cc -target riscv64-linux-gnu.2.34 -mcpu=generic_rv64 hello-world.c and run it under QEMU

bjia56 avatar Feb 04 '24 05:02 bjia56

I've fixed that missing header issue and I compiled glibc just to check if that header had anything worth adding and all I got was this:

/* This file is automatically generated.
   It defines a symbol `__stub_FUNCTION' for each function
   in the C library which is a stub, meaning it will fail
   every time called, usually setting errno to ENOSYS.  */

#ifdef _LIBC
 #error Applications may not define the macro _LIBC
#endif

RossComputerGuy avatar Feb 04 '24 06:02 RossComputerGuy

note that this patch should additionally be sent upstream so its not lost in zig when we next upgrade glibc

nektro avatar Feb 04 '24 07:02 nektro

Woops, made a mistake

RossComputerGuy avatar Feb 04 '24 07:02 RossComputerGuy

@nektro Yeah, the fini/ini stuff is actually upstream already. I just simplified it a bit since idk how we do things with glibc. The stub file though can be copied from a built version of glibc.

RossComputerGuy avatar Feb 04 '24 07:02 RossComputerGuy

Might also fix https://github.com/ziglang/zig-bootstrap/issues/115

LinuxUserGD avatar Feb 04 '24 13:02 LinuxUserGD

@RossComputerGuy Regarding the stubs-lp64d.h file, I see that the libc6-dev package from Debian sid includes:

/* This file is automatically generated.
   It defines a symbol `__stub_FUNCTION' for each function
   in the C library which is a stub, meaning it will fail
   every time called, usually setting errno to ENOSYS.  */

#ifdef _LIBC
# error Applications may not define the macro _LIBC
#endif

#define __stub___compat_bdflush
#define __stub___compat_create_module
#define __stub___compat_get_kernel_syms
#define __stub___compat_query_module
#define __stub___compat_uselib
#define __stub_chflags
#define __stub_fchflags
#define __stub_fedisableexcept
#define __stub_feenableexcept
#define __stub_fegetexcept
#define __stub_gtty
#define __stub_revoke
#define __stub_setlogin
#define __stub_sigreturn
#define __stub_stty

While an empty file might fix compilation, I'm not sure if it'll produce correct behavior.

bjia56 avatar Feb 04 '24 14:02 bjia56

@bjia56 Alright, I'll copy that in.

RossComputerGuy avatar Feb 04 '24 14:02 RossComputerGuy

I've got a draft PR In https://github.com/ziglang/zig/pull/18815 that builds on this PR. It enables Zig code to target riscv64-linux , with or without glibc (previously this would fail with missing "ucontext_t" errors).

I don't have any experience with riscv*, so I'm not able to test anything, so it may be wrong in obvious or subtle ways (I copied some details from https://go.dev/src/runtime/defs_linux_riscv64.go), but it does compile successfully. Just putting the PR out there in case someone with riscv access/experience/motivation needs pointers on how to get Zig's built-in library and/or the glibc linking for Zig code to work.

There are also glibc linking tests in test/link/glibc_compat that could be expanded to cover cross-compiling to riscv targets pretty easily I think.

rootbeer avatar Feb 04 '24 19:02 rootbeer

I've just been using QEMU userspace emulation (qemu-riscv64) @rootbeer. Interesting PR though, I plan on getting some RISC-V hardware when I have the money so hopefully I can help more with future RISC-V developments. I was going to run the tests in std this evening with -fqemu set.

RossComputerGuy avatar Feb 04 '24 19:02 RossComputerGuy

With the most recent patches from this PR applied to zig-linux-x86_64-0.12.0-dev.2341+92211135f, I'm getting the following:

$ ./zig-linux-x86_64-0.12.0-dev.2341+92211135f/zig cc -target riscv64-linux-gnu.2.34 hello-world.c
$ file a.out
a.out: ELF 64-bit LSB executable, UCB RISC-V, RVC, double-float ABI, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-riscv64-lp64.so.1, for GNU/Linux 2.0.0, with debug_info, not stripped

Note that the interpreter is /lib/ld-linux-riscv64-lp64.so.1, even though stubs-lp64d.h was pulled in as part of compilation. The lp64 interpreter does not exist in either Debian or Ubuntu, both of which supply /lib/ld-linux-riscv64-lp64d.so.1.

bjia56 avatar Feb 04 '24 20:02 bjia56

Using patchelf to switch the interpreter to ld-linux-riscv64-lp64d.so.1 allows the program to run inside QEMU

bjia56 avatar Feb 04 '24 20:02 bjia56

Yeah, that's what I have to do on NixOS. I think Zig's interpreter selection or target guessing not quite there yet. If it at least compiles and can execute, I'd call that a win. I can probably look into fixing that once I have hardware.

RossComputerGuy avatar Feb 04 '24 20:02 RossComputerGuy

Btw - looks like we may be missing another file (this is Debian sid):

root@c3cfce38249c:/# cat /usr/include/riscv64-linux-gnu/gnu/lib-names-lp64d.h
/* This file is automatically generated.  */
#ifndef __GNU_LIB_NAMES_H
# error "Never use <gnu/lib-names-lp64d.h> directly; include <gnu/lib-names.h> instead."
#endif

#define LD_LINUX_RISCV64_LP64D_SO       "ld-linux-riscv64-lp64d.so.1"
#define LD_SO                           "ld-linux-riscv64-lp64d.so.1"
#define LIBANL_SO                       "libanl.so.1"
#define LIBBROKENLOCALE_SO              "libBrokenLocale.so.1"
#define LIBCRYPT_SO                     "libcrypt.so.1"
#define LIBC_MALLOC_DEBUG_SO            "libc_malloc_debug.so.0"
#define LIBC_SO                         "libc.so.6"
#define LIBDL_SO                        "libdl.so.2"
#define LIBGCC_S_SO                     "libgcc_s.so.1"
#define LIBMVEC_SO                      "libmvec.so.1"
#define LIBM_SO                         "libm.so.6"
#define LIBNSL_SO                       "libnsl.so.1"
#define LIBNSS_COMPAT_SO                "libnss_compat.so.2"
#define LIBNSS_DB_SO                    "libnss_db.so.2"
#define LIBNSS_DNS_SO                   "libnss_dns.so.2"
#define LIBNSS_FILES_SO                 "libnss_files.so.2"
#define LIBNSS_HESIOD_SO                "libnss_hesiod.so.2"
#define LIBNSS_LDAP_SO                  "libnss_ldap.so.2"
#define LIBPTHREAD_SO                   "libpthread.so.0"
#define LIBRESOLV_SO                    "libresolv.so.2"
#define LIBRT_SO                        "librt.so.1"
#define LIBTHREAD_DB_SO                 "libthread_db.so.1"
#define LIBUTIL_SO                      "libutil.so.1"

Looks like this is where the lp64d interpreter is referenced. Still testing if this makes any difference...

bjia56 avatar Feb 04 '24 23:02 bjia56

Actually, nvm on the previous post - this file doesn't seem to be pulled in as part of compilation.

bjia56 avatar Feb 05 '24 00:02 bjia56

I think I found it - this line needs to switch on the abi to determine if it should use lp64, lp64f, or lp64d: https://github.com/ziglang/zig/blob/f5dbcd1cb4374be619ba0b18e40a069a7e860d93/lib/std/Target.zig#L1674

bjia56 avatar Feb 05 '24 00:02 bjia56

@bjia56 Would you be willing to add the fix for the interpreter to your PR?

RossComputerGuy avatar Feb 05 '24 19:02 RossComputerGuy

@RossComputerGuy I haven't gotten around to building zig to test the interpreter fix yet, but hopefully will get to it later this week

bjia56 avatar Feb 05 '24 19:02 bjia56

From testing with _freeze_importlib (CPython), it looks like the binary depends on ld-linux-riscv64-lp64.so.1 as a shared library and would segfault in __libc_start_main (before the C main starts) even after manually using patchelf to switch the interpreter to ld-linux-riscv64-lp64d.so.1. Using patchelf to replace it with the lp64d shared object fixes the segfault, so the abi fix mentioned above is likely required for the glibc dynamic loader to work properly.

bjia56 avatar Feb 05 '24 21:02 bjia56

I will have a VisionFive2 tomorrow so I can start looking into real hardware testing then.

RossComputerGuy avatar Feb 06 '24 03:02 RossComputerGuy

Thank you @RossComputerGuy

andrewrk avatar May 09 '24 23:05 andrewrk

Just checking since I need this for my work over at #20389: What remains to be done here? :eyes:

alexrp avatar Jun 23 '24 12:06 alexrp

@alexrp Just a review and merge

RossComputerGuy avatar Jun 23 '24 13:06 RossComputerGuy

Hey @RossComputerGuy I built on your work here in #20909 which is now in master. There's still the .cfi_label issue, but I expect us to upgrade to LLVM 19 in this release cycle, so that should be resolved soon-ish. Thanks for getting the ball rolling on this!

alexrp avatar Aug 07 '24 18:08 alexrp

Closing since our riscv64-linux-gnu support is now (to my knowledge) fully usable.

alexrp avatar Oct 02 '24 21:10 alexrp