diff --git a/lib/libc/glibc/sysdeps/arc/bits/endianness.h b/lib/libc/glibc/sysdeps/arc/bits/endianness.h new file mode 100644 index 000000000000..8f17ca84b485 --- /dev/null +++ b/lib/libc/glibc/sysdeps/arc/bits/endianness.h @@ -0,0 +1,15 @@ +#ifndef _BITS_ENDIANNESS_H +#define _BITS_ENDIANNESS_H 1 + +#ifndef _BITS_ENDIAN_H +# error "Never use directly; include instead." +#endif + +/* ARC has selectable endianness. */ +#ifdef __BIG_ENDIAN__ +# define __BYTE_ORDER __BIG_ENDIAN +#else +# define __BYTE_ORDER __LITTLE_ENDIAN +#endif + +#endif /* bits/endianness.h */ diff --git a/lib/libc/glibc/sysdeps/arc/entry.h b/lib/libc/glibc/sysdeps/arc/entry.h new file mode 100644 index 000000000000..adb01d981afd --- /dev/null +++ b/lib/libc/glibc/sysdeps/arc/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/arc/start-2.33.S b/lib/libc/glibc/sysdeps/arc/start-2.33.S new file mode 100644 index 000000000000..dbec87e6bb78 --- /dev/null +++ b/lib/libc/glibc/sysdeps/arc/start-2.33.S @@ -0,0 +1,74 @@ +/* Startup code for ARC. + Copyright (C) 2020-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 + . */ + +#define __ASSEMBLY__ 1 +#include +#include + +#ifndef ENTRY_POINT +# error ENTRY_POINT needs to be defined for ARC +#endif + +/* When we enter this piece of code, the program stack looks like this: + argc argument counter (integer) + argv[0] program name (pointer) + argv[1...N] program args (pointers) + argv[argc-1] end of args (integer) + NULL + env[0...N] environment variables (pointers) + NULL. */ + +ENTRY (ENTRY_POINT) + + /* Needed to make gdb backtraces stop here. */ + .cfi_label .Ldummy + cfi_undefined (blink) + + mov fp, 0 + ld_s r1, [sp] /* argc. */ + + mov_s r5, r0 /* rltd_fini. */ + add_s r2, sp, 4 /* argv. */ + and sp, sp, -8 + mov r6, sp + + /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end). */ + +#ifdef SHARED + ld r0, [pcl, @main@gotpc] + ld r3, [pcl, @__libc_csu_init@gotpc] + ld r4, [pcl, @__libc_csu_fini@gotpc] + bl __libc_start_main@plt +#else + mov_s r0, main + mov_s r3, __libc_csu_init + mov r4, __libc_csu_fini + bl __libc_start_main +#endif + + /* Should never get here. */ + flag 1 +END (ENTRY_POINT) + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/lib/libc/glibc/sysdeps/arc/start.S b/lib/libc/glibc/sysdeps/arc/start.S new file mode 100644 index 000000000000..03ee8a0f2e66 --- /dev/null +++ b/lib/libc/glibc/sysdeps/arc/start.S @@ -0,0 +1,90 @@ +/* Startup code for ARC. + Copyright (C) 2020-2024 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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 + . */ + +#define __ASSEMBLY__ 1 +#include +#include + +#ifndef ENTRY_POINT +# error ENTRY_POINT needs to be defined for ARC +#endif + +/* When we enter this piece of code, the program stack looks like this: + argc argument counter (integer) + argv[0] program name (pointer) + argv[1...N] program args (pointers) + argv[argc-1] end of args (integer) + NULL + env[0...N] environment variables (pointers) + NULL. */ + +ENTRY (ENTRY_POINT) + + /* Needed to make gdb backtraces stop here. */ + .cfi_label .Ldummy + cfi_undefined (blink) + + mov fp, 0 + ld_s r1, [sp] /* argc. */ + + mov_s r5, r0 /* rltd_fini. */ + add_s r2, sp, 4 /* argv. */ + and sp, sp, -8 + mov r6, sp + + /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end). */ + + mov_s r3, 0 /* Used to be init. */ + mov r4, 0 /* Used to be fini. */ + +#ifdef SHARED + ld r0, [pcl, @main@gotpc] + bl __libc_start_main@plt +#else + mov_s r0, main + bl __libc_start_main +#endif + + /* Should never get here. */ + flag 1 +END (ENTRY_POINT) + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/lib/libc/glibc/sysdeps/csky/abiv2/start-2.33.S b/lib/libc/glibc/sysdeps/csky/abiv2/start-2.33.S new file mode 100644 index 000000000000..d65e37e61b0e --- /dev/null +++ b/lib/libc/glibc/sysdeps/csky/abiv2/start-2.33.S @@ -0,0 +1,112 @@ +/* Startup code compliant to the ELF C-SKY ABIV2. + Copyright (C) 2018-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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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 + . */ + +/* We need to call: + __libc_start_main (int (*main) (int, char **, char **), int argc, + char **argv, void (*init) (void), void (*fini) (void), + void (*rtld_fini) (void), void *stack_end) + */ + +#include + + .text + .globl _start; + .type _start,@function; + .align 4; +_start: + cfi_startproc + .cfi_label .Ldummy + cfi_undefined (lr) + subi sp, 8 + /* Clear the link register since this is the outermost frame. */ + movi lr, 0 + /* Pop argc off the stack and save a pointer to argv. */ + ldw a1, (sp, 8) /* Init argc for __libc_start_main. */ + addi a2, sp, 12 /* Init argv for __libc_start_main. */ + + /* Push stack limit. */ + stw a2, (sp, 8) + /* Push rtld_fini. */ + stw a0, (sp, 4) + +#ifdef SHARED + grs t0, .Lgetpc +.Lgetpc: + lrw gb, .Lgetpc@GOTPC + addu gb, t0 + lrw a3, __libc_csu_fini@GOT + ldr.w a3, (gb, a3 << 0) + stw a3, (sp, 0) + + lrw a3, __libc_csu_init@GOT + addu a3, gb + ldw a3, (a3, 0) + + lrw t0, main@GOT + addu t0, gb + ldw a0, (t0, 0) + lrw t1, __libc_start_main@PLT + ldr.w t1, (gb, t1 << 0) + jsr t1 + + lrw t1, abort@PLT + ldr.w t1, (gb, t1 << 0) + jsr t1 +#else + /* Fetch address of __libc_csu_fini. */ + lrw a0, __libc_csu_fini + /* Push __libc_csu_fini */ + stw a0, (sp, 0) + + /* Set up the other arguments in registers. */ + lrw a0, main + lrw a3, __libc_csu_init + /* Let the libc call main and exit with its return code. */ + jsri __libc_start_main + + /* Should never get here. */ + jsri abort +#endif /* !SHARED */ + cfi_endproc + .size _start,.-_start + + + /* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/lib/libc/glibc/sysdeps/csky/abiv2/start.S b/lib/libc/glibc/sysdeps/csky/abiv2/start.S new file mode 100644 index 000000000000..4c03a5533558 --- /dev/null +++ b/lib/libc/glibc/sysdeps/csky/abiv2/start.S @@ -0,0 +1,103 @@ +/* Startup code compliant to the ELF C-SKY ABIV2. + Copyright (C) 2018-2024 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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 + . */ + +/* We need to call: + __libc_start_main (int (*main) (int, char **, char **), int argc, + char **argv, void (*init) (void), void (*fini) (void), + void (*rtld_fini) (void), void *stack_end) + */ + +#include + + .text + .globl _start; + .type _start,@function; + .align 4; +_start: + cfi_startproc + .cfi_label .Ldummy + cfi_undefined (lr) + subi sp, 8 + /* Clear the link register since this is the outermost frame. */ + movi lr, 0 + /* Pop argc off the stack and save a pointer to argv. */ + ldw a1, (sp, 8) /* Init argc for __libc_start_main. */ + addi a2, sp, 12 /* Init argv for __libc_start_main. */ + + /* Push stack limit. */ + stw a2, (sp, 8) + /* Push rtld_fini. */ + stw a0, (sp, 4) + +#ifdef SHARED + grs t0, .Lgetpc +.Lgetpc: + lrw gb, .Lgetpc@GOTPC + addu gb, t0 + + movi a3, 0 /* Used to be init. */ + stw a3, (sp, 0) /* Used to be fini. */ + + lrw t0, main@GOT + addu t0, gb + ldw a0, (t0, 0) + lrw t1, __libc_start_main@PLT + ldr.w t1, (gb, t1 << 0) + jsr t1 + + lrw t1, abort@PLT + ldr.w t1, (gb, t1 << 0) + jsr t1 +#else + movi a3, 0 /* Used to be init. */ + stw a3, (sp, 0) /* Used to be fini. */ + lrw a0, main + /* Let the libc call main and exit with its return code. */ + jsri __libc_start_main + + /* Should never get here. */ + jsri abort +#endif /* !SHARED */ + cfi_endproc + .size _start,.-_start + + + /* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/lib/libc/glibc/sysdeps/csky/bits/endianness.h b/lib/libc/glibc/sysdeps/csky/bits/endianness.h new file mode 100644 index 000000000000..ad20cf64e0bb --- /dev/null +++ b/lib/libc/glibc/sysdeps/csky/bits/endianness.h @@ -0,0 +1,14 @@ +#ifndef _BITS_ENDIANNESS_H +#define _BITS_ENDIANNESS_H 1 + +#ifndef _BITS_ENDIAN_H +# error "Never use directly; include instead." +#endif + +#ifdef __CSKYBE__ +# error "Big endian not supported for C-SKY." +#else +# define __BYTE_ORDER __LITTLE_ENDIAN +#endif + +#endif /* bits/endianness.h */ diff --git a/src/glibc.zig b/src/glibc.zig index ee1b208cdd49..7042f9c102b9 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -369,6 +369,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progre "-fgnu89-inline", "-fmerge-all-constants", "-frounding-math", + "-Wno-unsupported-floating-point-opt", // For targets that don't support -frounding-math. "-fno-stack-protector", "-fno-common", "-fmath-errno", @@ -467,8 +468,16 @@ fn start_asm_path(comp: *Compilation, arena: Allocator, basename: []const u8) ![ } else { try result.appendSlice("powerpc" ++ s ++ "powerpc32"); } + } else if (arch == .s390x) { + try result.appendSlice("s390" ++ s ++ "s390-64"); } else if (arch.isLoongArch()) { try result.appendSlice("loongarch"); + } else if (arch == .m68k) { + try result.appendSlice("m68k"); + } else if (arch == .arc) { + try result.appendSlice("arc"); + } else if (arch == .csky) { + try result.appendSlice("csky" ++ s ++ "abiv2"); } try result.appendSlice(s); @@ -569,6 +578,10 @@ fn add_include_dirs_arch( try args.append("-I"); try args.append(try path.join(arena, &[_][]const u8{ dir, "x86_64", nptl })); } else { + if (target.abi == .gnux32) { + try args.append("-I"); + try args.append(try path.join(arena, &[_][]const u8{ dir, "x86_64", "x32" })); + } try args.append("-I"); try args.append(try path.join(arena, &[_][]const u8{ dir, "x86_64" })); } @@ -657,9 +670,36 @@ fn add_include_dirs_arch( try args.append("-I"); try args.append(try path.join(arena, &[_][]const u8{ dir, "riscv" })); } + } else if (arch == .s390x) { + if (opt_nptl) |nptl| { + try args.append("-I"); + try args.append(try path.join(arena, &[_][]const u8{ dir, "s390", nptl })); + } else { + try args.append("-I"); + try args.append(try path.join(arena, &[_][]const u8{ dir, "s390" ++ s ++ "s390-64" })); + try args.append("-I"); + try args.append(try path.join(arena, &[_][]const u8{ dir, "s390" })); + } } else if (arch.isLoongArch()) { try args.append("-I"); try args.append(try path.join(arena, &[_][]const u8{ dir, "loongarch" })); + } else if (arch == .m68k) { + if (opt_nptl) |nptl| { + try args.append("-I"); + try args.append(try path.join(arena, &[_][]const u8{ dir, "m68k", nptl })); + } else { + // coldfire ABI support requires: https://github.com/ziglang/zig/issues/20690 + try args.append("-I"); + try args.append(try path.join(arena, &[_][]const u8{ dir, "m68k" ++ s ++ "m680x0" })); + try args.append("-I"); + try args.append(try path.join(arena, &[_][]const u8{ dir, "m68k" })); + } + } else if (arch == .arc) { + try args.append("-I"); + try args.append(try path.join(arena, &[_][]const u8{ dir, "arc" })); + } else if (arch == .csky) { + try args.append("-I"); + try args.append(try path.join(arena, &[_][]const u8{ dir, "csky" })); } } @@ -814,6 +854,23 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi var opt_symbol_name: ?[]const u8 = null; var versions_buffer: [32]u8 = undefined; var versions_len: usize = undefined; + + // There can be situations where there are multiple inclusions for the same symbol with + // partially overlapping versions, due to different target lists. For example: + // + // lgammal: + // library: libm.so + // versions: 2.4 2.23 + // targets: ... powerpc64-linux-gnu s390x-linux-gnu + // lgammal: + // library: libm.so + // versions: 2.2 2.23 + // targets: sparc64-linux-gnu s390x-linux-gnu + // + // If we don't handle this, we end up writing the default `lgammal` symbol for version 2.33 + // twice, which causes a "duplicate symbol" assembler error. + var versions_written = std.AutoArrayHashMap(Version, void).init(arena); + while (sym_i < fn_inclusions_len) : (sym_i += 1) { const sym_name = opt_symbol_name orelse n: { const name = mem.sliceTo(metadata.inclusions[inc_i..], 0); @@ -867,6 +924,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi } } } + + versions_written.clearRetainingCapacity(); + try versions_written.ensureTotalCapacity(versions_len); + { var ver_buf_i: u8 = 0; while (ver_buf_i < versions_len) : (ver_buf_i += 1) { @@ -877,6 +938,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi // _Exit_2_2_5: const ver_index = versions_buffer[ver_buf_i]; const ver = metadata.all_versions[ver_index]; + + if (versions_written.getOrPutAssumeCapacity(ver).found_existing) continue; + // Default symbol version definition vs normal symbol version definition const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index; const at_sign_str: []const u8 = if (want_default) "@@" else "@"; @@ -1026,6 +1090,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi } } } + + versions_written.clearRetainingCapacity(); + try versions_written.ensureTotalCapacity(versions_len); + { var ver_buf_i: u8 = 0; while (ver_buf_i < versions_len) : (ver_buf_i += 1) { @@ -1037,6 +1105,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi // environ_2_2_5: const ver_index = versions_buffer[ver_buf_i]; const ver = metadata.all_versions[ver_index]; + + if (versions_written.getOrPutAssumeCapacity(ver).found_existing) continue; + // Default symbol version definition vs normal symbol version definition const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index; const at_sign_str: []const u8 = if (want_default) "@@" else "@";