diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2018-10-13 23:52:55 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2018-10-13 23:52:55 +0000 |
commit | bdafb02fcb88389fd1ab684cfe734cb429d35618 (patch) | |
tree | 41db9d0835ce63a1548f9622c748cd8878fd13c2 /lib/csu/amd64 | |
parent | c9504239e8e891292b751f9c498dc3b03234004b (diff) |
Process irelocs for statically linked binaries from crt1 on x86.
This makes statically linked binaries with ifuncs operational.
Reported and tested by: mjg
Reviewed by: emaste, markj
Sponsored by: The FreeBSD Foundation
Approved by: re (rgrimes)
Differential revision: https://reviews.freebsd.org/D17363
Notes
Notes:
svn path=/head/; revision=339351
Diffstat (limited to 'lib/csu/amd64')
-rw-r--r-- | lib/csu/amd64/Makefile | 4 | ||||
-rw-r--r-- | lib/csu/amd64/crt1.c | 6 | ||||
-rw-r--r-- | lib/csu/amd64/reloc.c | 66 |
3 files changed, 72 insertions, 4 deletions
diff --git a/lib/csu/amd64/Makefile b/lib/csu/amd64/Makefile index a6a2d5ec658d..493ad93173b0 100644 --- a/lib/csu/amd64/Makefile +++ b/lib/csu/amd64/Makefile @@ -5,9 +5,9 @@ SRCS= crt1.c crti.S crtn.S OBJS= ${SRCS:N*.h:R:S/$/.o/g} OBJS+= Scrt1.o gcrt1.o -CFLAGS+= -I${.CURDIR:H}/common \ +CFLAGS+= -I${.CURDIR} -I${.CURDIR:H}/common \ -I${SRCTOP}/lib/libc/include -CFLAGS+= -fno-omit-frame-pointer +CFLAGS+= -fno-omit-frame-pointer -DCRT_IRELOC_RELA FILES= ${OBJS} FILESMODE= ${LIBMODE} diff --git a/lib/csu/amd64/crt1.c b/lib/csu/amd64/crt1.c index a6001b2d5851..7b9b442a4c0a 100644 --- a/lib/csu/amd64/crt1.c +++ b/lib/csu/amd64/crt1.c @@ -59,10 +59,12 @@ _start(char **ap, void (*cleanup)(void)) env = ap + 2 + argc; handle_argv(argc, argv, env); - if (&_DYNAMIC != NULL) + if (&_DYNAMIC != NULL) { atexit(cleanup); - else + } else { + process_irelocs(); _init_tls(); + } #ifdef GCRT atexit(_mcleanup); diff --git a/lib/csu/amd64/reloc.c b/lib/csu/amd64/reloc.c new file mode 100644 index 000000000000..cc4a7e73caba --- /dev/null +++ b/lib/csu/amd64/reloc.c @@ -0,0 +1,66 @@ +/*- + * 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. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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; + } +} |