Module Name: src
Committed By: joerg
Date: Thu Mar 29 13:23:40 UTC 2018
Modified Files:
src/distrib/sets/lists/comp: md.sparc md.sparc64
src/lib/csu/common: crt0-common.c
src/libexec/ld.elf_so/arch/sparc: mdreloc.c
src/libexec/ld.elf_so/arch/sparc64: mdreloc.c
src/sys/arch/sparc/include: Makefile
src/sys/arch/sparc64/include: Makefile
Added Files:
src/sys/arch/sparc/include: elf_support.h
src/sys/arch/sparc64/include: elf_support.h
Log Message:
Move the complex logic for dynamically writing branches from ld.elf_so
into a header for reuse in crt0.o for static ifunc support. Change the
existing logic for sparc64 to use the Bicc variant of ba,a as it allows
+-8MB displacement compared to the BPcc variant's +-1MB. Teach the sparc
variant the same trick for using ba,a and not sethi+jmp when possible.
To generate a diff of this commit:
cvs rdiff -u -r1.92 -r1.93 src/distrib/sets/lists/comp/md.sparc
cvs rdiff -u -r1.199 -r1.200 src/distrib/sets/lists/comp/md.sparc64
cvs rdiff -u -r1.15 -r1.16 src/lib/csu/common/crt0-common.c
cvs rdiff -u -r1.53 -r1.54 src/libexec/ld.elf_so/arch/sparc/mdreloc.c
cvs rdiff -u -r1.67 -r1.68 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c
cvs rdiff -u -r1.33 -r1.34 src/sys/arch/sparc/include/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/arch/sparc/include/elf_support.h
cvs rdiff -u -r1.30 -r1.31 src/sys/arch/sparc64/include/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/arch/sparc64/include/elf_support.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/distrib/sets/lists/comp/md.sparc
diff -u src/distrib/sets/lists/comp/md.sparc:1.92 src/distrib/sets/lists/comp/md.sparc:1.93
--- src/distrib/sets/lists/comp/md.sparc:1.92 Sat Feb 3 21:27:45 2018
+++ src/distrib/sets/lists/comp/md.sparc Thu Mar 29 13:23:39 2018
@@ -1,4 +1,4 @@
-# $NetBSD: md.sparc,v 1.92 2018/02/03 21:27:45 mrg Exp $
+# $NetBSD: md.sparc,v 1.93 2018/03/29 13:23:39 joerg Exp $
./usr/include/gcc-4.5/tgmath.h comp-obsolete obsolete
./usr/include/gcc-4.8/tgmath.h comp-c-include obsolete
./usr/include/gcc-4.8/visintrin.h comp-c-include obsolete
@@ -24,6 +24,7 @@
./usr/include/sparc/disklabel.h comp-c-include
./usr/include/sparc/eeprom.h comp-c-include
./usr/include/sparc/elf_machdep.h comp-c-include
+./usr/include/sparc/elf_support.h comp-c-include
./usr/include/sparc/endian.h comp-c-include
./usr/include/sparc/endian_machdep.h comp-c-include
./usr/include/sparc/fbio.h comp-obsolete obsolete
@@ -92,6 +93,7 @@
./usr/include/sparc64/disklabel.h comp-c-include
./usr/include/sparc64/eeprom.h comp-c-include
./usr/include/sparc64/elf_machdep.h comp-c-include
+./usr/include/sparc64/elf_support.h comp-c-include
./usr/include/sparc64/endian.h comp-c-include
./usr/include/sparc64/endian_machdep.h comp-c-include
./usr/include/sparc64/fbio.h comp-obsolete obsolete
Index: src/distrib/sets/lists/comp/md.sparc64
diff -u src/distrib/sets/lists/comp/md.sparc64:1.199 src/distrib/sets/lists/comp/md.sparc64:1.200
--- src/distrib/sets/lists/comp/md.sparc64:1.199 Sat Feb 3 21:27:45 2018
+++ src/distrib/sets/lists/comp/md.sparc64 Thu Mar 29 13:23:39 2018
@@ -1,4 +1,4 @@
-# $NetBSD: md.sparc64,v 1.199 2018/02/03 21:27:45 mrg Exp $
+# $NetBSD: md.sparc64,v 1.200 2018/03/29 13:23:39 joerg Exp $
./usr/include/g++/bits/sparc comp-c-include compat
./usr/include/g++/bits/sparc/c++config.h comp-c-include gcc,compat
./usr/include/g++/bits/sparc64 comp-c-include compat
@@ -28,6 +28,7 @@
./usr/include/sparc/disklabel.h comp-c-include
./usr/include/sparc/eeprom.h comp-c-include
./usr/include/sparc/elf_machdep.h comp-c-include
+./usr/include/sparc/elf_support.h comp-c-include
./usr/include/sparc/endian.h comp-c-include
./usr/include/sparc/endian_machdep.h comp-c-include
./usr/include/sparc/fbio.h comp-obsolete obsolete
@@ -95,6 +96,7 @@
./usr/include/sparc64/disklabel.h comp-c-include
./usr/include/sparc64/eeprom.h comp-c-include
./usr/include/sparc64/elf_machdep.h comp-c-include
+./usr/include/sparc64/elf_support.h comp-c-include
./usr/include/sparc64/endian.h comp-c-include
./usr/include/sparc64/endian_machdep.h comp-c-include
./usr/include/sparc64/fbio.h comp-obsolete obsolete
Index: src/lib/csu/common/crt0-common.c
diff -u src/lib/csu/common/crt0-common.c:1.15 src/lib/csu/common/crt0-common.c:1.16
--- src/lib/csu/common/crt0-common.c:1.15 Fri Mar 9 20:20:47 2018
+++ src/lib/csu/common/crt0-common.c Thu Mar 29 13:23:39 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: crt0-common.c,v 1.15 2018/03/09 20:20:47 joerg Exp $ */
+/* $NetBSD: crt0-common.c,v 1.16 2018/03/29 13:23:39 joerg Exp $ */
/*
* Copyright (c) 1998 Christos Zoulas
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: crt0-common.c,v 1.15 2018/03/09 20:20:47 joerg Exp $");
+__RCSID("$NetBSD: crt0-common.c,v 1.16 2018/03/29 13:23:39 joerg Exp $");
#include <sys/types.h>
#include <sys/exec.h>
@@ -140,6 +140,14 @@ static void fix_iplt(void) __noinline;
#include <stdio.h>
extern const Elf_Rela __rela_iplt_start[] __dso_hidden __weak;
extern const Elf_Rela __rela_iplt_end[] __dso_hidden __weak;
+#ifdef __sparc__
+#define IFUNC_RELOCATION R_TYPE(JMP_IREL)
+#include <machine/elf_support.h>
+#define write_plt(where, value) sparc_write_branch((void *)where, (void *)value)
+#else
+#define IFUNC_RELOCATION R_TYPE(IRELATIVE)
+#define write_plt(where, value) *where = value
+#endif
static void
fix_iplta(void)
@@ -150,31 +158,20 @@ fix_iplta(void)
rela = __rela_iplt_start;
relalim = __rela_iplt_end;
-#if DEBUG
- printf("%p - %p\n", rela, relalim);
-#endif
for (; rela < relalim; ++rela) {
- if (ELF_R_TYPE(rela->r_info) != R_TYPE(IRELATIVE))
+ if (ELF_R_TYPE(rela->r_info) != IFUNC_RELOCATION)
abort();
where = (Elf_Addr *)(relocbase + rela->r_offset);
-#if DEBUG
- printf("location: %p\n", where);
-#endif
target = (Elf_Addr)(relocbase + rela->r_addend);
-#if DEBUG
- printf("target: %p\n", (void *)target);
-#endif
target = ((Elf_Addr(*)(void))target)();
-#if DEBUG
- printf("...resolves to: %p\n", (void *)target);
-#endif
- *where = target;
+ write_plt(where, target);
}
}
#endif
#ifdef HAS_IPLT
extern const Elf_Rel __rel_iplt_start[] __dso_hidden __weak;
extern const Elf_Rel __rel_iplt_end[] __dso_hidden __weak;
+#define IFUNC_RELOCATION R_TYPE(IRELATIVE)
static void
fix_iplt(void)
@@ -186,7 +183,7 @@ fix_iplt(void)
rel = __rel_iplt_start;
rellim = __rel_iplt_end;
for (; rel < rellim; ++rel) {
- if (ELF_R_TYPE(rel->r_info) != R_TYPE(IRELATIVE))
+ if (ELF_R_TYPE(rel->r_info) != IFUNC_RELOCATION)
abort();
where = (Elf_Addr *)(relocbase + rel->r_offset);
target = ((Elf_Addr(*)(void))*where)();
Index: src/libexec/ld.elf_so/arch/sparc/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.53 src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.54
--- src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.53 Sun Mar 25 18:56:01 2018
+++ src/libexec/ld.elf_so/arch/sparc/mdreloc.c Thu Mar 29 13:23:39 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.53 2018/03/25 18:56:01 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.54 2018/03/29 13:23:39 joerg Exp $ */
/*-
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
@@ -31,9 +31,11 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.53 2018/03/25 18:56:01 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.54 2018/03/29 13:23:39 joerg Exp $");
#endif /* not lint */
+#include <machine/elf_support.h>
+
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -404,31 +406,6 @@ _rtld_relocate_plt_lazy(Obj_Entry *obj)
return 0;
}
-static inline void
-_rtld_write_plt(Elf_Word *where, Elf_Addr value)
-{
- /*
- * At the PLT entry pointed at by `where', we now construct
- * a direct transfer to the now fully resolved function
- * address. The resulting code in the jump slot is:
- *
- * sethi %hi(roffset), %g1
- * sethi %hi(addr), %g1
- * jmp %g1+%lo(addr)
- *
- * We write the third instruction first, since that leaves the
- * previous `b,a' at the second word in place. Hence the whole
- * PLT slot can be atomically change to the new sequence by
- * writing the `sethi' instruction at word 2.
- */
- const uint32_t SETHI = 0x03000000U;
- const uint32_t JMP = 0x81c06000U;
- where[2] = JMP | (value & 0x000003ff);
- where[1] = SETHI | ((value >> 10) & 0x003fffff);
- __asm volatile("iflush %0+8" : : "r" (where));
- __asm volatile("iflush %0+4" : : "r" (where));
-}
-
void
_rtld_call_ifunc(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
{
@@ -444,7 +421,7 @@ _rtld_call_ifunc(Obj_Entry *obj, sigset_
_rtld_exclusive_exit(mask);
target = _rtld_resolve_ifunc2(obj, target);
_rtld_exclusive_enter(mask);
- _rtld_write_plt(where, target);
+ sparc_write_branch(where + 1, (void *)target);
}
while (obj->ifunc_remaining_nonplt > 0 && _rtld_objgen == cur_objgen) {
@@ -521,7 +498,7 @@ _rtld_relocate_plt_object(const Obj_Entr
rdbg(("bind now/fixup in %s --> new=%p",
defobj->strtab + def->st_name, (void *)value));
- _rtld_write_plt(where, value);
+ sparc_write_branch(where + 1, (void *)value);
if (tp)
*tp = value;
Index: src/libexec/ld.elf_so/arch/sparc64/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.67 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.68
--- src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.67 Mon Dec 25 17:00:15 2017
+++ src/libexec/ld.elf_so/arch/sparc64/mdreloc.c Thu Mar 29 13:23:39 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.67 2017/12/25 17:00:15 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.68 2018/03/29 13:23:39 joerg Exp $ */
/*-
* Copyright (c) 2000 Eduardo Horvath.
@@ -32,9 +32,11 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.67 2017/12/25 17:00:15 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.68 2018/03/29 13:23:39 joerg Exp $");
#endif /* not lint */
+#include <machine/elf_support.h>
+
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -192,19 +194,6 @@ static const long reloc_target_bitmask[]
/*
* Instruction templates:
*/
-#define BAA 0x30680000 /* ba,a %xcc, 0 */
-#define SETHI 0x03000000 /* sethi %hi(0), %g1 */
-#define JMP 0x81c06000 /* jmpl %g1+%lo(0), %g0 */
-#define NOP 0x01000000 /* sethi %hi(0), %g0 */
-#define OR 0x82106000 /* or %g1, 0, %g1 */
-#define XOR 0x82186000 /* xor %g1, 0, %g1 */
-#define MOV71 0x8213e000 /* or %o7, 0, %g1 */
-#define MOV17 0x9e106000 /* or %g1, 0, %o7 */
-#define CALL 0x40000000 /* call 0 */
-#define SLLX 0x83287000 /* sllx %g1, 0, %g1 */
-#define NEG 0x82200001 /* neg %g1 */
-#define SETHIG5 0x0b000000 /* sethi %hi(0), %g5 */
-#define ORG5 0x82104005 /* or %g1, %g5, %g1 */
/* %hi(v)/%lo(v) with variable shift */
@@ -589,34 +578,6 @@ static inline void
_rtld_write_plt(Elf_Word *where, Elf_Addr value, const Elf_Rela *rela,
const Obj_Entry *obj)
{
- Elf_Addr offset, offBAA;
-
- /*
- * At the PLT entry pointed at by `where', we now construct a direct
- * transfer to the now fully resolved function address.
- *
- * A PLT entry is supposed to start by looking like this:
- *
- * sethi %hi(. - .PLT0), %g1
- * ba,a %xcc, .PLT1
- * nop
- * nop
- * nop
- * nop
- * nop
- * nop
- *
- * When we replace these entries we start from the last instruction
- * and do it in reverse order so the last thing we do is replace the
- * branch. That allows us to change this atomically.
- *
- * We now need to find out how far we need to jump. We have a choice
- * of several different relocation techniques which are increasingly
- * expensive.
- */
-
- offset = ((Elf_Addr)where) - value;
- offBAA = value - (((Elf_Addr)where) + 4); /* ba,a at where[1] */
if (rela && rela->r_addend) {
Elf_Addr *ptr = (Elf_Addr *)where;
/*
@@ -625,169 +586,8 @@ _rtld_write_plt(Elf_Word *where, Elf_Add
* PLT section. Update it to point to the target function.
*/
ptr[0] += value - (Elf_Addr)obj->pltgot;
- } else if (offBAA <= (1L<<20) && (Elf_SOff)offBAA >= -(1L<<20)) {
- /*
- * We're within 1MB -- we can use a direct branch insn.
- *
- * We can generate this pattern:
- *
- * sethi %hi(. - .PLT0), %g1
- * ba,a %xcc, addr
- * nop
- * nop
- * nop
- * nop
- * nop
- * nop
- *
- */
- where[1] = BAA | ((offBAA >> 2) & 0x7ffff);
- __asm volatile("iflush %0+4" : : "r" (where));
- } else if (value < (1L<<32)) {
- /*
- * We're within 32-bits of address zero.
- *
- * The resulting code in the jump slot is:
- *
- * sethi %hi(. - .PLT0), %g1
- * sethi %hi(addr), %g1
- * jmp %g1+%lo(addr)
- * nop
- * nop
- * nop
- * nop
- * nop
- *
- */
- where[2] = JMP | LOVAL(value, 0);
- where[1] = SETHI | HIVAL(value, 10);
- __asm volatile("iflush %0+8" : : "r" (where));
- __asm volatile("iflush %0+4" : : "r" (where));
- } else if ((Elf_SOff)value <= 0 && (Elf_SOff)value > -(1L<<32)) {
- /*
- * We're within 32-bits of address -1.
- *
- * The resulting code in the jump slot is:
- *
- * sethi %hi(. - .PLT0), %g1
- * sethi %hix(addr), %g1
- * xor %g1, %lox(addr), %g1
- * jmp %g1
- * nop
- * nop
- * nop
- * nop
- *
- */
- where[3] = JMP;
- where[2] = XOR | (value & 0x00003ff) | 0x1c00;
- where[1] = SETHI | HIVAL(~value, 10);
- __asm volatile("iflush %0+12" : : "r" (where));
- __asm volatile("iflush %0+8" : : "r" (where));
- __asm volatile("iflush %0+4" : : "r" (where));
- } else if ((offset+8) <= (1L<<31) &&
- (Elf_SOff)(offset+8) >= -((1L<<31) - 4)) {
- /*
- * We're within 32-bits -- we can use a direct call insn
- *
- * The resulting code in the jump slot is:
- *
- * sethi %hi(. - .PLT0), %g1
- * mov %o7, %g1
- * call (.+offset)
- * mov %g1, %o7
- * nop
- * nop
- * nop
- * nop
- *
- */
- offset += 8; /* call is at where[2], 8 byte further */
- where[3] = MOV17;
- where[2] = CALL | ((-offset >> 2) & 0x3fffffff);
- where[1] = MOV71;
- __asm volatile("iflush %0+12" : : "r" (where));
- __asm volatile("iflush %0+8" : : "r" (where));
- __asm volatile("iflush %0+4" : : "r" (where));
- } else if ((Elf_SOff)value > 0 && value < (1L<<44)) {
- /*
- * We're within 44 bits. We can generate this pattern:
- *
- * The resulting code in the jump slot is:
- *
- * sethi %hi(. - .PLT0), %g1
- * sethi %h44(addr), %g1
- * or %g1, %m44(addr), %g1
- * sllx %g1, 12, %g1
- * jmp %g1+%l44(addr)
- * nop
- * nop
- * nop
- *
- */
- where[4] = JMP | LOVAL(value, 0);
- where[3] = SLLX | 12;
- where[2] = OR | (((value) >> 12) & 0x00001fff);
- where[1] = SETHI | HIVAL(value, 22);
- __asm volatile("iflush %0+16" : : "r" (where));
- __asm volatile("iflush %0+12" : : "r" (where));
- __asm volatile("iflush %0+8" : : "r" (where));
- __asm volatile("iflush %0+4" : : "r" (where));
- } else if ((Elf_SOff)value < 0 && (Elf_SOff)value > -(1L<<44)) {
- /*
- * We're within 44 bits. We can generate this pattern:
- *
- * The resulting code in the jump slot is:
- *
- * sethi %hi(. - .PLT0), %g1
- * sethi %hi((-addr)>>12), %g1
- * or %g1, %lo((-addr)>>12), %g1
- * neg %g1
- * sllx %g1, 12, %g1
- * jmp %g1+(addr&0x0fff)
- * nop
- * nop
- *
- */
- Elf_Addr neg = (~value+1)>>12;
- where[5] = JMP | (value & 0x0fff);
- where[4] = SLLX | 12;
- where[3] = NEG;
- where[2] = OR | (LOVAL(neg, 0)+1);
- where[1] = SETHI | HIVAL(neg, 10);
- __asm volatile("iflush %0+20" : : "r" (where));
- __asm volatile("iflush %0+16" : : "r" (where));
- __asm volatile("iflush %0+12" : : "r" (where));
- __asm volatile("iflush %0+8" : : "r" (where));
- __asm volatile("iflush %0+4" : : "r" (where));
} else {
- /*
- * We need to load all 64-bits
- *
- * The resulting code in the jump slot is:
- *
- * sethi %hi(. - .PLT0), %g1
- * sethi %hh(addr), %g1
- * sethi %lm(addr), %g5
- * or %g1, %hm(addr), %g1
- * sllx %g1, 32, %g1
- * or %g1, %g5, %g1
- * jmp %g1+%lo(addr)
- * nop
- *
- */
- where[6] = JMP | LOVAL(value, 0);
- where[5] = ORG5;
- where[4] = SLLX | 32;
- where[3] = OR | LOVAL(value, 32);
- where[2] = SETHIG5 | HIVAL(value, 10);
- where[1] = SETHI | HIVAL(value, 42);
- __asm volatile("iflush %0+24" : : "r" (where));
- __asm volatile("iflush %0+20" : : "r" (where));
- __asm volatile("iflush %0+16" : : "r" (where));
- __asm volatile("iflush %0+12" : : "r" (where));
- __asm volatile("iflush %0+8" : : "r" (where));
- __asm volatile("iflush %0+4" : : "r" (where));
+ sparc_write_branch(where + 1, (void *)value);
}
}
@@ -851,7 +651,7 @@ _rtld_call_ifunc(Obj_Entry *obj, sigset_
_rtld_exclusive_exit(mask);
target = _rtld_resolve_ifunc2(obj, target);
_rtld_exclusive_enter(mask);
- _rtld_write_plt(where2, target, NULL, obj);
+ sparc_write_branch(where2 + 1, (void *)target);
}
while (obj->ifunc_remaining_nonplt > 0 && _rtld_objgen == cur_objgen) {
Index: src/sys/arch/sparc/include/Makefile
diff -u src/sys/arch/sparc/include/Makefile:1.33 src/sys/arch/sparc/include/Makefile:1.34
--- src/sys/arch/sparc/include/Makefile:1.33 Wed Jul 23 18:19:45 2014
+++ src/sys/arch/sparc/include/Makefile Thu Mar 29 13:23:39 2018
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.33 2014/07/23 18:19:45 alnsn Exp $
+# $NetBSD: Makefile,v 1.34 2018/03/29 13:23:39 joerg Exp $
INCSDIR= /usr/include/sparc
@@ -6,7 +6,7 @@ INCS= ansi.h aout_machdep.h apmvar.h asm
bswap.h bootinfo.h \
cdefs.h cgtworeg.h cpu.h cpuconf.h \
disklabel.h \
- eeprom.h elf_machdep.h endian.h endian_machdep.h \
+ eeprom.h elf_machdep.h elf_support.h endian.h endian_machdep.h \
fenv.h float.h frame.h fsr.h \
idprom.h ieee.h ieeefp.h \
int_const.h int_fmtio.h int_limits.h int_mwgwtypes.h int_types.h \
Index: src/sys/arch/sparc64/include/Makefile
diff -u src/sys/arch/sparc64/include/Makefile:1.30 src/sys/arch/sparc64/include/Makefile:1.31
--- src/sys/arch/sparc64/include/Makefile:1.30 Wed Jul 23 18:19:45 2014
+++ src/sys/arch/sparc64/include/Makefile Thu Mar 29 13:23:40 2018
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.30 2014/07/23 18:19:45 alnsn Exp $
+# $NetBSD: Makefile,v 1.31 2018/03/29 13:23:40 joerg Exp $
INCSDIR= /usr/include/sparc64
@@ -6,7 +6,7 @@ INCS= ansi.h aout_machdep.h asm.h autoco
bswap.h bsd_openprom.h \
cdefs.h cgtworeg.h cpu.h ctlreg.h \
disklabel.h \
- eeprom.h elf_machdep.h endian.h endian_machdep.h \
+ eeprom.h elf_machdep.h elf_support.h endian.h endian_machdep.h \
fenv.h float.h frame.h fsr.h \
idprom.h ieee.h ieeefp.h instr.h intr.h \
int_const.h int_fmtio.h int_limits.h int_mwgwtypes.h int_types.h \
Added files:
Index: src/sys/arch/sparc/include/elf_support.h
diff -u /dev/null src/sys/arch/sparc/include/elf_support.h:1.1
--- /dev/null Thu Mar 29 13:23:40 2018
+++ src/sys/arch/sparc/include/elf_support.h Thu Mar 29 13:23:39 2018
@@ -0,0 +1,64 @@
+/* $NetBSD: elf_support.h,v 1.1 2018/03/29 13:23:39 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+#ifndef _SPARC_ELF_SUPPORT_H
+#define _SPARC_ELF_SUPPORT_H
+
+static inline void
+sparc_write_branch(void *where_, void *target)
+{
+ const unsigned int BAA = 0x30800000U; /* ba,a (offset / 4) */
+ const unsigned int SETHI = 0x03000000U; /* sethi %hi(0), %g1 */
+ const unsigned int JMP = 0x81c06000U; /* jmpl %g1+%lo(0), %g0 */
+
+ unsigned int *where = (unsigned int *)where_;
+ unsigned long value = (unsigned long)target;
+ unsigned long offset = value - (unsigned long)where;
+
+#define HIVAL(v, s) (((v) >> (s)) & 0x003fffffU)
+#define LOVAL(v, s) (((v) >> (s)) & 0x000003ffU)
+ if (offset + 0x800000 <= 0x7ffffc) {
+ /* Displacement is within 8MB, use a direct branch. */
+ where[0] = BAA | ((offset >> 2) & 0x3fffff);
+ __asm volatile("iflush %0+0" : : "r" (where));
+ return;
+ }
+
+ /*
+ * The absolute address is a 32bit value.
+ * This can be encoded as:
+ * sethi %hi(value), %g1
+ * jmp %g1+%lo(value)
+ */
+ where[1] = JMP | LOVAL(value, 0);
+ __asm volatile("iflush %0+4" : : "r" (where));
+ where[0] = SETHI | HIVAL(value, 10);
+ __asm volatile("iflush %0+0" : : "r" (where));
+#undef HIVAL
+#undef LOVAL
+}
+#endif
Index: src/sys/arch/sparc64/include/elf_support.h
diff -u /dev/null src/sys/arch/sparc64/include/elf_support.h:1.1
--- /dev/null Thu Mar 29 13:23:40 2018
+++ src/sys/arch/sparc64/include/elf_support.h Thu Mar 29 13:23:40 2018
@@ -0,0 +1,186 @@
+/* $NetBSD: elf_support.h,v 1.1 2018/03/29 13:23:40 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2000 Eduardo Horvath.
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+#ifndef _SPARC64_ELF_SUPPORT_H
+#define _SPARC64_ELF_SUPPORT_H
+
+#ifdef __arch64__
+/*
+ * Create a jump to the location `target` starting at `where`.
+ * This requires up to 6 instructions.
+ * The first instruction is written last as it replaces a branch
+ * in the PLT during lazy binding.
+ * The resulting code can trash %g1 and %g5.
+ */
+static inline void
+sparc_write_branch(void *where_, void *target)
+{
+ const unsigned int BAA = 0x30800000U; /* ba,a (offset / 4) */
+ const unsigned int SETHI = 0x03000000U; /* sethi %hi(0), %g1 */
+ const unsigned int JMP = 0x81c06000U; /* jmpl %g1+%lo(0), %g0 */
+ const unsigned int OR = 0x82106000U; /* or %g1, 0, %g1 */
+ const unsigned int XOR = 0x82186000U; /* xor %g1, 0, %g1 */
+ const unsigned int MOV71 = 0x8213e000U; /* or %o7, 0, %g1 */
+ const unsigned int MOV17 = 0x9e106000U; /* or %g1, 0, %o7 */
+ const unsigned int CALL = 0x40000000U; /* call 0 */
+ const unsigned int SLLX = 0x83287000U; /* sllx %g1, 0, %g1 */
+ const unsigned int NEG = 0x82200001U; /* neg %g1 */
+ const unsigned int SETHIG5 = 0x0b000000U; /* sethi %hi(0), %g5 */
+ const unsigned int ORG5 = 0x82104005U; /* or %g1, %g5, %g1 */
+
+ unsigned int *where = (unsigned int *)where_;
+ unsigned long value = (unsigned long)target;
+ unsigned long offset = value - (unsigned long)where;
+
+#define HIVAL(v, s) (((v) >> (s)) & 0x003fffffU)
+#define LOVAL(v, s) (((v) >> (s)) & 0x000003ffU)
+ if (offset + 0x800000 <= 0x7ffffc) {
+ /* Displacement is within 8MB, use a direct branch. */
+ where[0] = BAA | ((offset >> 2) & 0x3fffff);
+ __asm volatile("iflush %0+0" : : "r" (where));
+ return;
+ }
+
+ if (value <= 0xffffffffUL) {
+ /*
+ * The absolute address is a 32bit value.
+ * This can be encoded as:
+ * sethi %hi(value), %g1
+ * jmp %g1+%lo(value)
+ */
+ where[1] = JMP | LOVAL(value, 0);
+ __asm volatile("iflush %0+4" : : "r" (where));
+ where[0] = SETHI | HIVAL(value, 10);
+ __asm volatile("iflush %0+0" : : "r" (where));
+ return;
+ }
+
+ if (value >= 0xffffffff00000000UL) {
+ /*
+ * The top 32bit address range can be encoded as:
+ * sethi %hix(addr), %g1
+ * xor %g1, %lox(addr), %g1
+ * jmp %g1
+ */
+ where[2] = JMP;
+ where[1] = XOR | (value & 0x00003ff) | 0x1c00;
+ __asm volatile("iflush %0+4" : : "r" (where));
+ __asm volatile("iflush %0+8" : : "r" (where));
+ where[0] = SETHI | HIVAL(~value, 10);
+ __asm volatile("iflush %0+0" : : "r" (where));
+ return;
+ }
+
+ if ((offset + 4) + 0x80000000UL <= 0x100000000UL) {
+ /*
+ * Displacement of the second instruction is within
+ * +-2GB. This can use a direct call instruction:
+ * mov %o7, %g1
+ * call (value - .)
+ * mov %g1, %o7
+ */
+ where[1] = CALL | ((-(offset + 4)>> 2) & 0x3fffffffU);
+ where[2] = MOV17;
+ __asm volatile("iflush %0+4" : : "r" (where));
+ __asm volatile("iflush %0+8" : : "r" (where));
+ where[0] = MOV71;
+ __asm volatile("iflush %0+0" : : "r" (where));
+ return;
+ }
+
+ if (value < 0x100000000000UL) {
+ /*
+ * The absolute address is a 44bit value.
+ * This can be encoded as:
+ * sethi %h44(addr), %g1
+ * or %g1, %m44(addr), %g1
+ * sllx %g1, 12, %g1
+ * jmp %g1+%l44(addr)
+ */
+ where[1] = OR | (((value) >> 12) & 0x00001fff);
+ where[2] = SLLX | 12;
+ where[3] = JMP | LOVAL(value, 0);
+ __asm volatile("iflush %0+4" : : "r" (where));
+ __asm volatile("iflush %0+8" : : "r" (where));
+ __asm volatile("iflush %0+12" : : "r" (where));
+ where[0] = SETHI | HIVAL(value, 22);
+ __asm volatile("iflush %0+0" : : "r" (where));
+ return;
+ }
+
+ if (value > 0xfffff00000000000UL) {
+ /*
+ * The top 44bit address range can be encoded as:
+ * sethi %hi((-addr)>>12), %g1
+ * or %g1, %lo((-addr)>>12), %g1
+ * neg %g1
+ * sllx %g1, 12, %g1
+ * jmp %g1+(addr&0x0fff)
+ */
+ unsigned long neg = (-value)>>12;
+ where[1] = OR | (LOVAL(neg, 0)+1);
+ where[2] = NEG;
+ where[3] = SLLX | 12;
+ where[4] = JMP | (value & 0x0fff);
+ __asm volatile("iflush %0+4" : : "r" (where));
+ __asm volatile("iflush %0+8" : : "r" (where));
+ __asm volatile("iflush %0+12" : : "r" (where));
+ __asm volatile("iflush %0+16" : : "r" (where));
+ where[0] = SETHI | HIVAL(neg, 10);
+ __asm volatile("iflush %0+0" : : "r" (where));
+ return;
+ }
+
+ /*
+ * The general case of a 64bit address is encoded as:
+ * sethi %hh(addr), %g1
+ * sethi %lm(addr), %g5
+ * or %g1, %hm(addr), %g1
+ * sllx %g1, 32, %g1
+ * or %g1, %g5, %g1
+ * jmp %g1+%lo(addr)
+ */
+ where[1] = SETHIG5 | HIVAL(value, 10);
+ where[2] = OR | LOVAL(value, 32);
+ where[3] = SLLX | 32;
+ where[4] = ORG5;
+ where[5] = JMP | LOVAL(value, 0);
+ __asm volatile("iflush %0+4" : : "r" (where));
+ __asm volatile("iflush %0+8" : : "r" (where));
+ __asm volatile("iflush %0+12" : : "r" (where));
+ __asm volatile("iflush %0+16" : : "r" (where));
+ __asm volatile("iflush %0+20" : : "r" (where));
+ where[0] = SETHI | HIVAL(value, 42);
+ __asm volatile("iflush %0+0" : : "r" (where));
+#undef HIVAL
+#undef LOVAL
+}
+#else
+#include <sparc/elf_support.h>
+#endif
+#endif