aboutsummaryrefslogtreecommitdiff
path: root/lib/libc/csu
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2022-10-30 23:47:44 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2023-03-11 22:50:03 +0000
commit51015e6d0f570239b0c2088dc6cf2b018928375d (patch)
treebac148baabfb85020f64956855b2e2c7c2cab1cd /lib/libc/csu
parent3c3a434f8ee867e6e4a69de07bf0811f2ae0c46e (diff)
downloadsrc-51015e6d0f570239b0c2088dc6cf2b018928375d.tar.gz
src-51015e6d0f570239b0c2088dc6cf2b018928375d.zip
csu: move common code to libc
Why? Most trivial point, it shaves around 600 bytes from the dynamic binaries on amd64. Less trivial, the removed code is no longer part of the ABI, and we can ship updates to it with libc updates. Right now most of the csu is linked into the binaries and require us to do somewhat tricky ABI compat when it needs to change. For instance, the init_array change would be much simpler and does not require note tagging if we have init calling code in libc. This could be improved more, by splitting dynamic and static initialization. For instance, &_DYNAMIC tests can be removed then. Such change, nonetheless, would require building libc three times. I left this for later, after this change stabilizes, if ever. Reviewed by: markj Discussed with: jrtc27 (some objections, see the review), imp Tested by: markj (aarch64) Sponsored by: The FreeBSD Foundation MFC after: 3 weeks Differential revision: https://reviews.freebsd.org/D37220
Diffstat (limited to 'lib/libc/csu')
-rw-r--r--lib/libc/csu/Makefile.inc10
-rw-r--r--lib/libc/csu/Symbol.map4
-rw-r--r--lib/libc/csu/aarch64/Makefile.inc4
-rw-r--r--lib/libc/csu/aarch64/reloc.c46
-rw-r--r--lib/libc/csu/amd64/Makefile.inc4
-rw-r--r--lib/libc/csu/amd64/reloc.c63
-rw-r--r--lib/libc/csu/arm/Makefile.inc4
-rw-r--r--lib/libc/csu/i386/Makefile.inc4
-rw-r--r--lib/libc/csu/i386/reloc.c85
-rw-r--r--lib/libc/csu/ignore_init.c184
-rw-r--r--lib/libc/csu/powerpc/Makefile.inc4
-rw-r--r--lib/libc/csu/powerpc64/Makefile.inc4
-rw-r--r--lib/libc/csu/powerpc64/reloc.c69
-rw-r--r--lib/libc/csu/riscv/Makefile.inc4
14 files changed, 489 insertions, 0 deletions
diff --git a/lib/libc/csu/Makefile.inc b/lib/libc/csu/Makefile.inc
new file mode 100644
index 000000000000..453303bea608
--- /dev/null
+++ b/lib/libc/csu/Makefile.inc
@@ -0,0 +1,10 @@
+#
+
+.PATH: ${LIBC_SRCTOP}/csu
+.include "${LIBC_SRCTOP}/csu/${LIBC_ARCH}/Makefile.inc"
+
+SRCS+= \
+ ignore_init.c
+
+CFLAGS+= -I${LIBC_SRCTOP}/csu/${LIBC_ARCH}
+SYM_MAPS+=${LIBC_SRCTOP}/csu/Symbol.map
diff --git a/lib/libc/csu/Symbol.map b/lib/libc/csu/Symbol.map
new file mode 100644
index 000000000000..7fc09add5e45
--- /dev/null
+++ b/lib/libc/csu/Symbol.map
@@ -0,0 +1,4 @@
+FBSD_1.7 {
+ __libc_start1;
+ __libc_start1_gcrt;
+};
diff --git a/lib/libc/csu/aarch64/Makefile.inc b/lib/libc/csu/aarch64/Makefile.inc
new file mode 100644
index 000000000000..b3420a638164
--- /dev/null
+++ b/lib/libc/csu/aarch64/Makefile.inc
@@ -0,0 +1,4 @@
+#
+
+CFLAGS+= -DCRT_IRELOC_RELA \
+ -DINIT_IRELOCS=""
diff --git a/lib/libc/csu/aarch64/reloc.c b/lib/libc/csu/aarch64/reloc.c
new file mode 100644
index 000000000000..f3dbf3e3b570
--- /dev/null
+++ b/lib/libc/csu/aarch64/reloc.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2019 Leandro Lupori
+ * Copyright (c) 2021 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Andrew Turner
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+static void
+crt1_handle_rela(const Elf_Rela *r)
+{
+ typedef Elf_Addr (*ifunc_resolver_t)(
+ uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t, uint64_t, uint64_t, uint64_t);
+ Elf_Addr *ptr, *where, target;
+
+ switch (ELF_R_TYPE(r->r_info)) {
+ case R_AARCH64_IRELATIVE:
+ ptr = (Elf_Addr *)r->r_addend;
+ where = (Elf_Addr *)r->r_offset;
+ target = ((ifunc_resolver_t)ptr)(0, 0, 0, 0, 0, 0, 0, 0);
+ *where = target;
+ break;
+ }
+}
diff --git a/lib/libc/csu/amd64/Makefile.inc b/lib/libc/csu/amd64/Makefile.inc
new file mode 100644
index 000000000000..b3420a638164
--- /dev/null
+++ b/lib/libc/csu/amd64/Makefile.inc
@@ -0,0 +1,4 @@
+#
+
+CFLAGS+= -DCRT_IRELOC_RELA \
+ -DINIT_IRELOCS=""
diff --git a/lib/libc/csu/amd64/reloc.c b/lib/libc/csu/amd64/reloc.c
new file mode 100644
index 000000000000..adb52e42a32c
--- /dev/null
+++ b/lib/libc/csu/amd64/reloc.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2018 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/specialreg.h>
+#include <machine/cpufunc.h>
+
+static void
+crt1_handle_rela(const Elf_Rela *r)
+{
+ Elf_Addr *ptr, *where, target;
+ u_int p[4];
+ uint32_t cpu_feature, cpu_feature2;
+ uint32_t cpu_stdext_feature, cpu_stdext_feature2;
+
+ do_cpuid(1, p);
+ cpu_feature = p[3];
+ cpu_feature2 = p[2];
+ do_cpuid(0, p);
+ if (p[0] >= 7) {
+ cpuid_count(7, 0, p);
+ cpu_stdext_feature = p[1];
+ cpu_stdext_feature2 = p[2];
+ } else {
+ cpu_stdext_feature = 0;
+ cpu_stdext_feature2 = 0;
+ }
+
+ switch (ELF_R_TYPE(r->r_info)) {
+ case R_X86_64_IRELATIVE:
+ ptr = (Elf_Addr *)r->r_addend;
+ where = (Elf_Addr *)r->r_offset;
+ target = ((Elf_Addr (*)(uint32_t, uint32_t, uint32_t,
+ uint32_t))ptr)(cpu_feature, cpu_feature2,
+ cpu_stdext_feature, cpu_stdext_feature2);
+ *where = target;
+ break;
+ }
+}
diff --git a/lib/libc/csu/arm/Makefile.inc b/lib/libc/csu/arm/Makefile.inc
new file mode 100644
index 000000000000..2534e6579f38
--- /dev/null
+++ b/lib/libc/csu/arm/Makefile.inc
@@ -0,0 +1,4 @@
+#
+
+CFLAGS+= -DCRT_IRELOC_SUPPRESS \
+ -DINIT_IRELOCS=""
diff --git a/lib/libc/csu/i386/Makefile.inc b/lib/libc/csu/i386/Makefile.inc
new file mode 100644
index 000000000000..ac0984df2349
--- /dev/null
+++ b/lib/libc/csu/i386/Makefile.inc
@@ -0,0 +1,4 @@
+#
+
+CFLAGS+= -DCRT_IRELOC_REL \
+ -DINIT_IRELOCS=""
diff --git a/lib/libc/csu/i386/reloc.c b/lib/libc/csu/i386/reloc.c
new file mode 100644
index 000000000000..13438035841d
--- /dev/null
+++ b/lib/libc/csu/i386/reloc.c
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 2018 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/specialreg.h>
+#include <machine/cpufunc.h>
+
+static void
+crt1_handle_rel(const Elf_Rel *r)
+{
+ Elf_Addr *where, target;
+ u_int cpuid_supported, p[4];
+ uint32_t cpu_feature, cpu_feature2;
+ uint32_t cpu_stdext_feature, cpu_stdext_feature2;
+
+ __asm __volatile(
+ " pushfl\n"
+ " popl %%eax\n"
+ " movl %%eax,%%ecx\n"
+ " xorl $0x200000,%%eax\n"
+ " pushl %%eax\n"
+ " popfl\n"
+ " pushfl\n"
+ " popl %%eax\n"
+ " xorl %%eax,%%ecx\n"
+ " je 1f\n"
+ " movl $1,%0\n"
+ " jmp 2f\n"
+ "1: movl $0,%0\n"
+ "2:\n"
+ : "=r" (cpuid_supported) : : "eax", "ecx", "cc");
+ if (cpuid_supported) {
+ do_cpuid(1, p);
+ cpu_feature = p[3];
+ cpu_feature2 = p[2];
+ do_cpuid(0, p);
+ if (p[0] >= 7) {
+ cpuid_count(7, 0, p);
+ cpu_stdext_feature = p[1];
+ cpu_stdext_feature2 = p[2];
+ } else {
+ cpu_stdext_feature = 0;
+ cpu_stdext_feature2 = 0;
+ }
+ } else {
+ cpu_feature = 0;
+ cpu_feature2 = 0;
+ cpu_stdext_feature = 0;
+ cpu_stdext_feature2 = 0;
+ }
+
+ switch (ELF_R_TYPE(r->r_info)) {
+ case R_386_IRELATIVE:
+ where = (Elf_Addr *)r->r_offset;
+ target = ((Elf_Addr (*)(uint32_t, uint32_t, uint32_t,
+ uint32_t))*where)(cpu_feature, cpu_feature2,
+ cpu_stdext_feature, cpu_stdext_feature2);
+ *where = target;
+ break;
+ }
+}
diff --git a/lib/libc/csu/ignore_init.c b/lib/libc/csu/ignore_init.c
new file mode 100644
index 000000000000..60c45d7e735f
--- /dev/null
+++ b/lib/libc/csu/ignore_init.c
@@ -0,0 +1,184 @@
+/*-
+ * SPDX-License-Identifier: BSD-1-Clause
+ *
+ * Copyright 2012 Konstantin Belousov <kib@FreeBSD.org>
+ * Copyright (c) 2018, 2023 The FreeBSD Foundation
+ *
+ * Parts of this software was developed by Konstantin Belousov
+ * <kib@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/elf.h>
+#include <sys/elf_common.h>
+#include <stdlib.h>
+#include "libc_private.h"
+
+extern void (*__preinit_array_start[])(int, char **, char **) __hidden;
+extern void (*__preinit_array_end[])(int, char **, char **) __hidden;
+extern void (*__init_array_start[])(int, char **, char **) __hidden;
+extern void (*__init_array_end[])(int, char **, char **) __hidden;
+extern void (*__fini_array_start[])(void) __hidden;
+extern void (*__fini_array_end[])(void) __hidden;
+extern void _fini(void) __hidden;
+extern void _init(void) __hidden;
+
+extern int _DYNAMIC;
+#pragma weak _DYNAMIC
+
+#if defined(CRT_IRELOC_RELA)
+extern const Elf_Rela __rela_iplt_start[] __weak_symbol __hidden;
+extern const Elf_Rela __rela_iplt_end[] __weak_symbol __hidden;
+
+#include "reloc.c"
+
+static void
+process_irelocs(void)
+{
+ const Elf_Rela *r;
+
+ for (r = &__rela_iplt_start[0]; r < &__rela_iplt_end[0]; r++)
+ crt1_handle_rela(r);
+}
+#elif defined(CRT_IRELOC_REL)
+extern const Elf_Rel __rel_iplt_start[] __weak_symbol __hidden;
+extern const Elf_Rel __rel_iplt_end[] __weak_symbol __hidden;
+
+#include "reloc.c"
+
+static void
+process_irelocs(void)
+{
+ const Elf_Rel *r;
+
+ for (r = &__rel_iplt_start[0]; r < &__rel_iplt_end[0]; r++)
+ crt1_handle_rel(r);
+}
+#elif defined(CRT_IRELOC_SUPPRESS)
+#else
+#error "Define platform reloc type"
+#endif
+
+static void
+finalizer(void)
+{
+ void (*fn)(void);
+ size_t array_size, n;
+
+ array_size = __fini_array_end - __fini_array_start;
+ for (n = array_size; n > 0; n--) {
+ fn = __fini_array_start[n - 1];
+ if ((uintptr_t)fn != 0 && (uintptr_t)fn != 1)
+ (fn)();
+ }
+ _fini();
+}
+
+static void
+handle_static_init(int argc, char **argv, char **env)
+{
+ void (*fn)(int, char **, char **);
+ size_t array_size, n;
+
+ if (&_DYNAMIC != NULL)
+ return;
+
+ atexit(finalizer);
+
+ array_size = __preinit_array_end - __preinit_array_start;
+ for (n = 0; n < array_size; n++) {
+ fn = __preinit_array_start[n];
+ if ((uintptr_t)fn != 0 && (uintptr_t)fn != 1)
+ fn(argc, argv, env);
+ }
+ _init();
+ array_size = __init_array_end - __init_array_start;
+ for (n = 0; n < array_size; n++) {
+ fn = __init_array_start[n];
+ if ((uintptr_t)fn != 0 && (uintptr_t)fn != 1)
+ fn(argc, argv, env);
+ }
+}
+
+extern char **environ;
+
+static void
+handle_argv(int argc, char *argv[], char **env)
+{
+ const char *s;
+
+ if (environ == NULL)
+ environ = env;
+ if (argc > 0 && argv[0] != NULL) {
+ __progname = argv[0];
+ for (s = __progname; *s != '\0'; s++) {
+ if (*s == '/')
+ __progname = s + 1;
+ }
+ }
+}
+
+void
+__libc_start1(int argc, char *argv[], char *env[], void (*cleanup)(void),
+ int (*mainX)(int, char *[], char *[]))
+{
+ handle_argv(argc, argv, env);
+
+ if (&_DYNAMIC != NULL) {
+ atexit(cleanup);
+ } else {
+#ifndef CRT_IRELOC_SUPPRESS
+ INIT_IRELOCS;
+ process_irelocs();
+#endif
+ _init_tls();
+ }
+
+ handle_static_init(argc, argv, env);
+ exit(mainX(argc, argv, env));
+}
+
+/* XXXKIB _mcleanup and monstartup defs */
+extern void _mcleanup(void);
+extern void monstartup(void *, void *);
+
+void
+__libc_start1_gcrt(int argc, char *argv[], char *env[],
+ void (*cleanup)(void), int (*mainX)(int, char *[], char *[]),
+ int *eprolp, int *etextp)
+{
+ handle_argv(argc, argv, env);
+
+ if (&_DYNAMIC != NULL) {
+ atexit(cleanup);
+ } else {
+#ifndef CRT_IRELOC_SUPPRESS
+ INIT_IRELOCS;
+ process_irelocs();
+#endif
+ _init_tls();
+ }
+
+ atexit(_mcleanup);
+ monstartup(eprolp, etextp);
+
+ handle_static_init(argc, argv, env);
+ exit(mainX(argc, argv, env));
+}
diff --git a/lib/libc/csu/powerpc/Makefile.inc b/lib/libc/csu/powerpc/Makefile.inc
new file mode 100644
index 000000000000..2534e6579f38
--- /dev/null
+++ b/lib/libc/csu/powerpc/Makefile.inc
@@ -0,0 +1,4 @@
+#
+
+CFLAGS+= -DCRT_IRELOC_SUPPRESS \
+ -DINIT_IRELOCS=""
diff --git a/lib/libc/csu/powerpc64/Makefile.inc b/lib/libc/csu/powerpc64/Makefile.inc
new file mode 100644
index 000000000000..5d59d40eb393
--- /dev/null
+++ b/lib/libc/csu/powerpc64/Makefile.inc
@@ -0,0 +1,4 @@
+#
+
+CFLAGS+= -DCRT_IRELOC_RELA \
+ -DINIT_IRELOCS="init_cpu_features(env)"
diff --git a/lib/libc/csu/powerpc64/reloc.c b/lib/libc/csu/powerpc64/reloc.c
new file mode 100644
index 000000000000..5ba191d07cd9
--- /dev/null
+++ b/lib/libc/csu/powerpc64/reloc.c
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 2019 Leandro Lupori
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+static uint32_t cpu_features;
+static uint32_t cpu_features2;
+
+static void
+init_cpu_features(char **env)
+{
+ const Elf_Auxinfo *aux;
+
+ /* Find the auxiliary vector on the stack. */
+ while (*env++ != 0) /* Skip over environment, and NULL terminator */
+ ;
+ aux = (const Elf_Auxinfo *)env;
+
+ /* Digest the auxiliary vector. */
+ for (; aux->a_type != AT_NULL; aux++) {
+ switch (aux->a_type) {
+ case AT_HWCAP:
+ cpu_features = (uint32_t)aux->a_un.a_val;
+ break;
+ case AT_HWCAP2:
+ cpu_features2 = (uint32_t)aux->a_un.a_val;
+ break;
+ }
+ }
+}
+
+static void
+crt1_handle_rela(const Elf_Rela *r)
+{
+ typedef Elf_Addr (*ifunc_resolver_t)(
+ uint32_t, uint32_t, uint64_t, uint64_t,
+ uint64_t, uint64_t, uint64_t, uint64_t);
+ Elf_Addr *ptr, *where, target;
+
+ switch (ELF_R_TYPE(r->r_info)) {
+ case R_PPC_IRELATIVE:
+ ptr = (Elf_Addr *)r->r_addend;
+ where = (Elf_Addr *)r->r_offset;
+ target = ((ifunc_resolver_t)ptr)(cpu_features, cpu_features2,
+ 0, 0, 0, 0, 0, 0);
+ *where = target;
+ break;
+ }
+}
diff --git a/lib/libc/csu/riscv/Makefile.inc b/lib/libc/csu/riscv/Makefile.inc
new file mode 100644
index 000000000000..2534e6579f38
--- /dev/null
+++ b/lib/libc/csu/riscv/Makefile.inc
@@ -0,0 +1,4 @@
+#
+
+CFLAGS+= -DCRT_IRELOC_SUPPRESS \
+ -DINIT_IRELOCS=""