From e977455f7c5693369d547c4d9b2e0b902f578d65 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 15 Dec 2021 17:53:29 -0700 Subject: [PATCH] glibc: improve RISC-V support * omit crti.o / crtn.o for this architecture * add missing entry.h header from upstream --- lib/libc/glibc/sysdeps/generic/entry.h | 5 +++ lib/libc/glibc/sysdeps/hppa/entry.h | 13 +++++++ lib/libc/glibc/sysdeps/ia64/entry.h | 13 +++++++ .../glibc/sysdeps/powerpc/powerpc64/entry.h | 37 +++++++++++++++++++ lib/libc/glibc/sysdeps/unix/mips/entry.h | 5 +++ src/Compilation.zig | 22 +++++------ src/glibc.zig | 8 ++++ 7 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 lib/libc/glibc/sysdeps/generic/entry.h create mode 100644 lib/libc/glibc/sysdeps/hppa/entry.h create mode 100644 lib/libc/glibc/sysdeps/ia64/entry.h create mode 100644 lib/libc/glibc/sysdeps/powerpc/powerpc64/entry.h create mode 100644 lib/libc/glibc/sysdeps/unix/mips/entry.h diff --git a/lib/libc/glibc/sysdeps/generic/entry.h b/lib/libc/glibc/sysdeps/generic/entry.h new file mode 100644 index 0000000000..16d3e3045e --- /dev/null +++ b/lib/libc/glibc/sysdeps/generic/entry.h @@ -0,0 +1,5 @@ +#ifndef __ASSEMBLY__ +extern void _start (void) attribute_hidden; +#endif + +#define ENTRY_POINT _start diff --git a/lib/libc/glibc/sysdeps/hppa/entry.h b/lib/libc/glibc/sysdeps/hppa/entry.h new file mode 100644 index 0000000000..5ea5b47448 --- /dev/null +++ b/lib/libc/glibc/sysdeps/hppa/entry.h @@ -0,0 +1,13 @@ +#ifndef __ASSEMBLY__ +extern void _start (void); +#endif + +/* Lives in libgcc.so and canonicalizes function pointers for comparison. */ +extern unsigned int __canonicalize_funcptr_for_compare (unsigned int fptr); + +/* The function's entry point is stored in the first word of the + function descriptor (plabel) of _start(). */ +#define ENTRY_POINT __canonicalize_funcptr_for_compare((unsigned int)_start) + +/* We have to provide a special declaration. */ +#define ENTRY_POINT_DECL(class) class void _start (void); diff --git a/lib/libc/glibc/sysdeps/ia64/entry.h b/lib/libc/glibc/sysdeps/ia64/entry.h new file mode 100644 index 0000000000..e11b49fc53 --- /dev/null +++ b/lib/libc/glibc/sysdeps/ia64/entry.h @@ -0,0 +1,13 @@ +#include +#include + +#ifndef __ASSEMBLY__ +extern void _start (void); +#endif + +/* The function's entry point is stored in the first word of the + function descriptor (plabel) of _start(). */ +#define ENTRY_POINT ELF_PTR_TO_FDESC (_start)->ip + +/* We have to provide a special declaration. */ +#define ENTRY_POINT_DECL(class) class void _start (void); diff --git a/lib/libc/glibc/sysdeps/powerpc/powerpc64/entry.h b/lib/libc/glibc/sysdeps/powerpc/powerpc64/entry.h new file mode 100644 index 0000000000..99c81cb982 --- /dev/null +++ b/lib/libc/glibc/sysdeps/powerpc/powerpc64/entry.h @@ -0,0 +1,37 @@ +/* Finding the entry point and start of text. PowerPC64 version. + Copyright (C) 2002-2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + + +#ifndef __ASSEMBLY__ +extern void _start (void); +#endif + +#define ENTRY_POINT _start + +#if _CALL_ELF != 2 +/* We have to provide a special declaration. */ +#define ENTRY_POINT_DECL(class) class void _start (void); + +/* Use the address of ._start as the lowest address for which we need + to keep profiling records. We can't copy the ia64 scheme as our + entry poiny address is really the address of the function + descriptor, not the actual function entry. */ +#define TEXT_START \ + ({ extern unsigned long int _start_as_data[] asm ("_start"); \ + _start_as_data[0]; }) +#endif diff --git a/lib/libc/glibc/sysdeps/unix/mips/entry.h b/lib/libc/glibc/sysdeps/unix/mips/entry.h new file mode 100644 index 0000000000..04d05d2b0a --- /dev/null +++ b/lib/libc/glibc/sysdeps/unix/mips/entry.h @@ -0,0 +1,5 @@ +#ifndef __ASSEMBLY__ +extern void __start (void); +#endif + +#define ENTRY_POINT __start diff --git a/src/Compilation.zig b/src/Compilation.zig index d87ad78a71..236a344027 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1586,7 +1586,17 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { // If we need to build glibc for the target, add work items for it. // We go through the work queue so that building can be done in parallel. if (comp.wantBuildGLibCFromSource()) { - try comp.addBuildingGLibCJobs(); + if (glibc.needsCrtiCrtn(comp.getTarget())) { + try comp.work_queue.write(&[_]Job{ + .{ .glibc_crt_file = .crti_o }, + .{ .glibc_crt_file = .crtn_o }, + }); + } + try comp.work_queue.write(&[_]Job{ + .{ .glibc_crt_file = .scrt1_o }, + .{ .glibc_crt_file = .libc_nonshared_a }, + .{ .glibc_shared_objects = {} }, + }); } if (comp.wantBuildMuslFromSource()) { try comp.work_queue.ensureUnusedCapacity(6); @@ -4046,16 +4056,6 @@ pub fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const return full_path; } -fn addBuildingGLibCJobs(comp: *Compilation) !void { - try comp.work_queue.write(&[_]Job{ - .{ .glibc_crt_file = .crti_o }, - .{ .glibc_crt_file = .crtn_o }, - .{ .glibc_crt_file = .scrt1_o }, - .{ .glibc_crt_file = .libc_nonshared_a }, - .{ .glibc_shared_objects = {} }, - }); -} - fn wantBuildLibCFromSource(comp: Compilation) bool { const is_exe_or_dyn_lib = switch (comp.bin_file.options.output_mode) { .Obj => false, diff --git a/src/glibc.zig b/src/glibc.zig index 9426cf48a2..dac913f476 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -1062,3 +1062,11 @@ fn buildSharedLib( try sub_compilation.updateSubCompilation(); } + +// Return true if glibc has crti/crtn sources for that architecture. +pub fn needsCrtiCrtn(target: std.Target) bool { + return switch (target.cpu.arch) { + .riscv32, .riscv64 => false, + else => true, + }; +}