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

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

RossComputerGuy
Copy link
Sponsor Contributor

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.

@bjia56
Copy link

bjia56 commented Feb 4, 2024

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

@RossComputerGuy
Copy link
Sponsor Contributor Author

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

@nektro
Copy link
Contributor

nektro commented Feb 4, 2024

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

@RossComputerGuy
Copy link
Sponsor Contributor Author

Woops, made a mistake

@RossComputerGuy
Copy link
Sponsor Contributor Author

@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.

@LinuxUserGD
Copy link
Contributor

Might also fix ziglang/zig-bootstrap#115

@bjia56
Copy link

bjia56 commented Feb 4, 2024

@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.

@RossComputerGuy
Copy link
Sponsor Contributor Author

@bjia56 Alright, I'll copy that in.

rootbeer added a commit to rootbeer/zig that referenced this pull request Feb 4, 2024
Borrow the ucontext layout from Go (probably reasonable?) and fix up
some missing imports for shared structures.

I can compile a glibc-linked hello.zig with:

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu
setup.  I've no experience in riscv64, so this maybe be broken in subtle
ways, but perhaps its a useful point for someone with the right hardware
to make more progress.

Builds on ziglang#18803
@rootbeer
Copy link
Contributor

rootbeer commented Feb 4, 2024

I've got a draft PR In #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.

@RossComputerGuy
Copy link
Sponsor Contributor Author

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.

@bjia56
Copy link

bjia56 commented Feb 4, 2024

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

bjia56 commented Feb 4, 2024

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

@RossComputerGuy
Copy link
Sponsor Contributor Author

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.

@bjia56
Copy link

bjia56 commented Feb 4, 2024

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

bjia56 commented Feb 5, 2024

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

@bjia56
Copy link

bjia56 commented Feb 5, 2024

I think I found it - this line needs to switch on the abi to determine if it should use lp64, lp64f, or lp64d:

.riscv64 => return copy(&result, "/lib/ld-linux-riscv64-lp64.so.1"),

bjia56 added a commit to bjia56/portable-python that referenced this pull request Feb 5, 2024
RossComputerGuy pushed a commit to ExpidusOS/zig that referenced this pull request Feb 5, 2024
Borrow the ucontext layout from Go (probably reasonable?) and fix up
some missing imports for shared structures.

I can compile a glibc-linked hello.zig with:

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu
setup.  I've no experience in riscv64, so this maybe be broken in subtle
ways, but perhaps its a useful point for someone with the right hardware
to make more progress.

Builds on ziglang#18803
@RossComputerGuy
Copy link
Sponsor Contributor Author

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

@bjia56
Copy link

bjia56 commented Feb 5, 2024

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

RossComputerGuy pushed a commit to ExpidusOS/zig that referenced this pull request Feb 8, 2024
Borrow the ucontext layout from Go (probably reasonable?) and fix up
some missing imports for shared structures.

I can compile a glibc-linked hello.zig with:

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu
setup.  I've no experience in riscv64, so this maybe be broken in subtle
ways, but perhaps its a useful point for someone with the right hardware
to make more progress.

Builds on ziglang#18803
rootbeer added a commit to rootbeer/zig that referenced this pull request Feb 11, 2024
Borrow the ucontext layout from Go (probably reasonable?) and fix up
some missing imports for shared structures.

I can compile a glibc-linked hello.zig with:

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu
setup.  I've no experience in riscv64, so this maybe be broken in subtle
ways, but perhaps its a useful point for someone with the right hardware
to make more progress.

Builds on ziglang#18803
RossComputerGuy pushed a commit to ExpidusOS/zig that referenced this pull request Feb 12, 2024
Borrow the ucontext layout from Go (probably reasonable?) and fix up
some missing imports for shared structures.

I can compile a glibc-linked hello.zig with:

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu
setup.  I've no experience in riscv64, so this maybe be broken in subtle
ways, but perhaps its a useful point for someone with the right hardware
to make more progress.

Builds on ziglang#18803
RossComputerGuy pushed a commit to ExpidusOS/zig that referenced this pull request Feb 15, 2024
Borrow the ucontext layout from Go (probably reasonable?) and fix up
some missing imports for shared structures.

I can compile a glibc-linked hello.zig with:

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu
setup.  I've no experience in riscv64, so this maybe be broken in subtle
ways, but perhaps its a useful point for someone with the right hardware
to make more progress.

Builds on ziglang#18803
RossComputerGuy pushed a commit to ExpidusOS/zig that referenced this pull request Feb 22, 2024
Borrow the ucontext layout from Go (probably reasonable?) and fix up
some missing imports for shared structures.

I can compile a glibc-linked hello.zig with:

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu
setup.  I've no experience in riscv64, so this maybe be broken in subtle
ways, but perhaps its a useful point for someone with the right hardware
to make more progress.

Builds on ziglang#18803
RossComputerGuy pushed a commit to ExpidusOS/zig that referenced this pull request Feb 29, 2024
Borrow the ucontext layout from Go (probably reasonable?) and fix up
some missing imports for shared structures.

I can compile a glibc-linked hello.zig with:

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu
setup.  I've no experience in riscv64, so this maybe be broken in subtle
ways, but perhaps its a useful point for someone with the right hardware
to make more progress.

Builds on ziglang#18803
RossComputerGuy pushed a commit to ExpidusOS/zig that referenced this pull request Mar 11, 2024
Borrow the ucontext layout from Go (probably reasonable?) and fix up
some missing imports for shared structures.

I can compile a glibc-linked hello.zig with:

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu
setup.  I've no experience in riscv64, so this maybe be broken in subtle
ways, but perhaps its a useful point for someone with the right hardware
to make more progress.

Builds on ziglang#18803
RossComputerGuy pushed a commit to ExpidusOS/zig that referenced this pull request Mar 11, 2024
Borrow the ucontext layout from Go (probably reasonable?) and fix up
some missing imports for shared structures.

I can compile a glibc-linked hello.zig with:

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu
setup.  I've no experience in riscv64, so this maybe be broken in subtle
ways, but perhaps its a useful point for someone with the right hardware
to make more progress.

Builds on ziglang#18803
RossComputerGuy pushed a commit to ExpidusOS/zig that referenced this pull request Mar 20, 2024
Borrow the ucontext layout from Go (probably reasonable?) and fix up
some missing imports for shared structures.

I can compile a glibc-linked hello.zig with:

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu
setup.  I've no experience in riscv64, so this maybe be broken in subtle
ways, but perhaps its a useful point for someone with the right hardware
to make more progress.

Builds on ziglang#18803
@andrewrk
Copy link
Member

andrewrk commented May 9, 2024

Thank you @RossComputerGuy

@alexrp alexrp mentioned this pull request Jun 22, 2024
4 tasks
@alexrp
Copy link
Contributor

alexrp commented Jun 23, 2024

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

@RossComputerGuy
Copy link
Sponsor Contributor Author

@alexrp Just a review and merge

@@ -0,0 +1 @@
#define NO_INITFINI 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upstream glibc sets this to zero in this file.

Copy link
Sponsor Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, will change

Copy link
Sponsor Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I should have been clearer earlier. As a general principle, I think it's better to copy the file 1:1 from upstream glibc when we don't need any changes to it (which seems to be the case here), so there are less diffs to review when upgrading glibc.

@@ -56,6 +56,12 @@
# define cfi_personality(enc, exp) .cfi_personality enc, exp
# define cfi_lsda(enc, exp) .cfi_lsda enc, exp

# ifndef __clang__
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see this in upstream glibc. Should a patch be submitted?

Copy link
Sponsor Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe? Idk if we've ever sent a patch to glibc before.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, something is weird here:

clang --version
Ubuntu clang version 16.0.6 (15)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/binclang -target riscv test.s -cclang -target riscv64 test.s -c
test.s:5:1: error: unknown directive
.cfi_label .Ldummy
^

Copy link
Sponsor Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clang doesn't support the directive which is why we have this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clang doesn't support the directive which is why we have this.

It's definitely an oversight. The MCStreamer code in LLVM has an API for emitting CFI labels, it's just that the MCParser hasn't been taught to parse them. Honestly a bit a surprised no one has run into this before as it affects ARC, C-SKY, and LoongArch too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to drop this workaround in LLVM 19: llvm/llvm-project#97922

Copy link
Sponsor Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sweet, amazing getting that done. Would that mean this PR will have to wait for the next LLVM version bump in Zig?

@alexrp
Copy link
Contributor

alexrp commented Aug 7, 2024

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!

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.

unable to build glibc for target riscv64-linux-gnu
7 participants